I was just looking at the code and finding it confusing. Maybe more
comments will help, but maybe generating XML with enormous piles of
preprocessory is intrinsically confusing.
I was looking for something completely different in the Unicode
Standard and found a note that U+23B4..U+23B6 can be used in terminal
applications with text printed vertically. So obviously I had to add
them.
Apparently the same doesn't apply to the other horizontal brackets at
U+23DC..U+32E1, which are purely stretchy mathematical brackets and
not interesting to us.
The odd positioning in the character cell is based on the Unicode code
chart.
These are treated as particularly odd Unicode code points and packed
into the "unicode" field. Currently only the encoding side is
implemented, withe the slashed zero, <U+0030, U+FE00>, as a motivating
example.
Generating a format 14 'cmap' subtable and properly formatting the
glyph complement are still to come.
This re-uses the old Oslash glyph I drew that had the slash entirely
inside the O. I've seen something similar on simulations of old
character generators, though I'm not sure I've seen any actual character
generators using this shape.
We were only using negative numbers for the "no Unicode mapping"
constant, and even there it was mostly cast to unsigned before we used
it (because it needed to sort last). So just using an unsigned type
throughout seems to be a bit cleaner. It will also make me less dubious
about packing extra information in when I want to support variation
selectors.
I noticed some occasions where my attempts at 16-bit cleanliness had
failed because I hadn't noticed that "unsigned" was a species of "int"
and hence potentially only 16 bits. So now I'm trying to be more
explicit and saying "unsigned int".
Next several of them will need to be replaced with something else.
GCC 15 gives a warning (-Wunterminated-string-initialization) if you
initialize an unsigned char array from a string constant such that the
terminating null character isn't included. Bedstead does this in most
rows of the glyphs array, which is quite noisy. I've chosen to work
around this by making the array one byte larger. That doesn't
actually affect the size of the struct on systems that align struct
fields, so the major loss is that now we might not get warnings if we
overflow by one byte.
There are several other ways this problem could be solved. One could
disable the warning entirely, but that would remove a valuable warning
from the rest of the program. We currently disable two other warnings
for the sake of the glyphs array, but working around them would
require ugly changes on every line of the array.
Probably the ideal approach would be to tag the "data" field with
"[[gnu::nonstring]]". That would not only suppress the warning but
also enable warnings if the array was ever passed to a function
expecting a null-terminated string. However, I think Bedstead is
currently written in plain ISO C99, while attributes like that were
only standardised in C23. I'm not averse to moving to a newer
standard, but C23 is a but _too_ new right now. I'm also a little
reluctant to rely on the implementation-defined behaviour of
particular compilers, which is why I'm not using "#pragma GCC
diagnostic".
I don't think it's appropriate to use 'name' string 0 (copyright
notice) for something that isn't a copyright notice. Perhaps I should
have something other than a URL that explains Bedstead's copyright
situation, but that field isn't it.
We now have a manufacturer, vendor URL, licensing URL, and sample text.
I've added an anchor to the Web page so to make the licensing URL more
useful.
Most of these are displayed by Firefox when listing the fonts used on a
page, so they seem like a good idea.
The ones that aren't separately encoded provided a clear indication of
how the numbered stem parts are meant to relate to the named ones, so
there weren't actually many decisions to make.
This is essentially all of them apart from the W and M pieces. There
turn out to be obvious places to have the diagonals cross character-cell
boundaries such that they should all join up. Whether this gives and
aesthetically tolerable outcome, I'm not so sure.
The W and M pieces are a bit confusing, because they're meant to span
two character cells vertically, but the obvious design doesn't.
This batch are the ones that can be implemented using the ordinary
box-drawing characters (and probably should have been unified with
them by Unicode).
Because in Bedstead the cell boundaries of 8-cell mosaic glyphs are a
superset of those for 6-cell mosaic glyphs, each of the existing
6-cell glyphs has an identical 8-cell glyph whose middle two rows of
cells are identical. Thus, these 8-cell glyphs can be aliases for the
corresponding 6-cell glyph. I've implemented this as a macro called
A() that can be mixed in with the existing O() macros in the section
of the glyphs table that generates U+1CD00..U+1CDE5, aliasing them to
characters in U+1FB00..U+1FB3B. That makes the table even more
confusing, but at least it's compact.
These are the ones scattered across Unicode and not in the main
U+1CD00..U+1CDE5 block that weren't already present. They're aliased to
the corresponding 6-cell characters.
These were mostly generated from UnicodeData.txt with a dodgy Perl
one-liner and an Emacs keyboard macro. The dodgy one-liner was (wrapped
onto more lines):
grep "BLOCK OCTANT" ~/Downloads/UnicodeData.txt |
perl -pe '/OCTANT-(\d+)/; $i=""; map{vec($i,$_-1,1)=1}split(//,$1);
$_=sprintf("%02X",ord($i))." $_";'
Now I need to find the characters elsewhere in Unicode that correspond
with the gaps in the table.
This follows the pattern of the 6-cell and 4-cell versions, but without
separated mode because Unicode doesn't have that. This required making
the bitmap data into an unsigned char array to allow for using all eight
bits.
The cell boundaries are chosen so that they line up with existing 6-cell
and 4-cell boundaries. So we have row heights of [3,2,2,3], which is
maybe less pretty than [3,2,3,2], but is more in keeping with the
existing mosaics. Indeed, it means that the existing 4-cell and 6-cell
contiguous characters could be expressed in 8-cell terms if I wanted to.
Before, the diagonal parts were the same as in the capital O. But that
was already a bit square, and the shapes one would draw with the box
drawing characters will generally be bigger. So now I've cut a bit more
off the corners. This means that arcs that join to the right need the
recent change to add JOIN_R in order to join up properly.
With this change, if you try to draw a circle with them, you get an
octagon with side lengths 2, 2.8, 6 instead of 4, 1.4, 8, which I think
is an improvement.
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.