The new flags mark glyphs that join to the right and downwards. The
effect of these, and a new effect of JOIN_U and JOIN_L, is to arrange
that getpix() treats pixels beyond the edge of the character cell as
repeating the last row of real pixels.
In practice, this means that a diagonal stroke touching the right or
bottom edge of the cell will now be drawn as though it turns into an
orthogonal stroke across the edge rather than as though it stops. This
doesn't affect the outline of any existing glyph.
There is a more subtle consequence, which is that joining glyphs no
longer get edge hints on their joining edges. I think that's an
improvement: such hints might move those edges so that they don't touch
the adjacent character, which would be rather unhelpful.
Specifically, this adds:
U+1D0C LATIN LETTER SMALL CAPITAL L WITH STROKE
U+1D23 LATIN LETTER SMALL CAPITAL EZH
U+1D7B LATIN SMALL CAPITAL LETTER I WITH STROKE
U+1DF04 LATIN LETTER SMALL CAPITAL L WITH BELT
U+1DF10 LATIN LETTER SMALL CAPITAL TURNED K
Three of this had private-use encodings that appeared in earlier
Bedstead releases. These encodings have been preserved for backward
compatibility.
I've designed new versions of 0, 1, and 2 that fit within the
x-height. 6 and 8 don't change at all (and are unmapped). The other
digits are all moved down by two pixels so their top edges are at the
x-height and their bottom edges at the descender height.
This is very simple (and much simpler than my previous attempts), but
seems to be satisfactory.
I had been trying to find an upper-case that was visibly distinct from
the existing lower-case, but I realised that I could do the same as we
do with accented 'o' and instead make a new lower-case version and
declare the existing glyph to be upper-case. This seems to work
tolerably and removes the most embarrassing gaps in Bedstead's
repertoire.
Not cities, but capital versions of some letters we already had in
lower-case for IPA. Specifically:
U+0186 LATIN CAPITAL LETTER OPEN O
U+0189 LATIN CAPITAL LETTER AFRICAN D
U+0190 LATIN CAPITAL LETTER OPEN E
U+0196 LATIN CAPITAL LETTER IOTA
U+01B2 LATIN CAPITAL LETTER V WITH HOOK
Between them, Hyperglot thinks this gains us useful coverage of
languages with a few tens of millions of speakers, which seems like good
value to me.
The all also have small caps, and in the case of the African D all the
capital-D variants.
The International Phonetic Association's preferred sans-serif font
doesn't give this character a serif at the top left, so Bedstead
shouldn't either. Also the bottom-left corner of the letter is subtly
curved, so I've rounded off that corner a bit as well. The result is
more like the IPA's ideal and also easier to design a capital version
of.
Now all of the caps and small caps have a central peak four pixels
above the baseline, and all of the lower-case have a central peak
three pixels above the baseline. The outer arms vary as necessary to
accommodate accents and for small caps.
Hyperglot says these are needed for Welsh, and they're trivial to
draw.
There seems to be some confusion around the proper shape for small-cap
W in Bedstead; I should investigate this in more detail.
When generating hints for a symmetric glyph like 'v', it's helpful if
the hits are symmetric because that means that the hinted bitmap is
also likely to be symmetric. This is particularly visible on
Microsoft Windows where the version of 'v' before this patch ended up
horribly distorted when rendered at 20 ppem in Bedstead Condensed. To
try to avoid such horrors, we now select hints starting at the outside
edges of the character and working inwards, instead of going from left
to right or top to bottom. This means that where hints conflict,
we'll tend to choose the ones towards the outside edge of the
character, rather than towards the top or left.
This changes the hinting for 50 glyphs, but all in ways that look
superficially reasonable.
For more complicated characters we probably still want to think about
hint substitution, but that still scares me.
C23 marks asctime() as deprecated and it seems polite to keep up with
that. Using strftime() isn't noticeably more complicated: the "%c"
specifier does what we want and we don't get a spurious newline that
we have to remove again.
Microsoft Windows 11 pays some attention to counter hints, and the
results are disastrous. Specifically, at awkward ppem, characters
with counter hints end up one pixel smaller that characters without
them. That makes the counters the same size, and puts every
horizontal stem squarely on a pixel, but means that cap height is all
wobbly, which looks horrible. Additionally, some characters ('2' and
'3', at least) end up grossly distorted, with the top of the character
either stretched way above the character cell or squashed down to the
centre line.
Turning off the counter hints solves these problems. Windows does
then draw the 'B' with its centre-line below the centre rather than
above it, but that's not a regression from 002.009. As far as I can
tell, FreeType 2.12.1 ignores counter hints entirely. At least, the
output of ftlint at 11 ppem is the same before and after this change.
Vertical counter hints survive. They're also ignored by FreeType
2.12.1 (as are all vertical stem hints), but they seem to have a
broadly positive effect in Windows.
Rather than mucking about with errno, we can just take advantage of the
fact that on overflow, strtoull() is specified to return ULLONG_MAX,
which is guaranteed to be (much) bigger than the maximum
SOURCE_DATE_EPOCH that we can cope with. So our usual range check can
cope with overflow as well.
This seems to be necessary for the font viewer in MS Windows 11 to
consider the font to be valid. The semantics of this field are not
documented in the OpenType spec, but the Apple TrueType spec does at
least give an example. I've roughly followed Apple's example, putting
together the full name, version number, and build date that we already
have to hand and include in the font. Between them those should
uniquely identify reasonable builds of Bedstead fonts without adding
extra complexity or non-reproducibility.
I've never been comfortable with constructing or editing commit
messages that will appear under someone else's name, but on the other
hand I don't want to be forced either to use someone else's message
untouched or to remove their name from the "Author" field. Allowing
myself to make clearly-marked edits seems to be a good compromise, and
square brackets are a common way of marking edits and editorial
comments.
Now we don't make any assumption about being on a POSIX system, and
instead have our own implementation of gmtime(). This turns out to be
shorter than the comment explaining why the previous code was more or
less valid.
While I'm in the area, also fail if the year is after 9999, since
asctime() causes undefined behaviour in those cases.
That's a real cedilla, and hence gets the SAA5054 angular form. It's
also the last Latin letter with a cedilla that isn't blocked by
something else. At least, until Unicode adds a new one.
These are the remaining characters that Unicode calls "WITH CEDILLA" but
that the standard (and code charts) say should actually have a comma
below by default.
The Unicode code charts and all the fonts I have conveniently to hand
are agreed that the cedilla should be attached to the letter, usually
to the left leg. So now it is in Bedstead as well. This also allows
the body of the letter to return to its normal shape.
If I'm going to insist that U+0162 and U+0163 really have cedillas, I
should have their unambiguously comma-below versions, U+021A and
U+021B, as well.
According to Unicode 16.0.0 (chapter 7), U+0327 COMBINING CEDILLA is
ambiguous. It can mean an actual cedilla, but it can also mean a
comma below. This also applies to precomposed characters containing
it. Unicode recommends default forms for various letters and in
particular says that for D and T (upper- and lower-case) the comma
form should be the default.
However, Unicode now has a separate U+021A LATIN CAPITAL LETTER T WITH
COMMA BELOW and recommends its use for Romanian. So I think the
recommendation to render U+0162 LATIN CAPITAL LETTER T WITH CEDILLA with
a comma below is no longer applicable.
I have now updated Bedstead so that U+1E10 LATIN CAPITAL LETTER D WITH
CEDILLA is treated as having a comma below instead. In practice, this
just means that it's unaffected by 'cv96'
All references to capital letters above apply equally to the
corresponding small letters.
The OpenType spec (version 1.9.1) says, "The FeatureRecord array
should be sorted alphabetically by feature tag." Bedstead was instead
emitting them in the order in which they appeared in the gsub_features
array, which was determined by the order the lookups need to occur in.
In particular, the 'cvXX' lookups need to occur after the 'ssXX'
lookups so as to override them properly.
Fixing this required some care to keep all the indices straight, but I
think I've managed it.
This means that now each possible variant of a character covered by a
'cvXX' feature has a human-readable name. I don't know of anything
that uses these, so they're somewhat untested.