Configuring a bunch of fonts in the initial set() call doesn't work

Issue #34 closed
Steve Johnson
created an issue

I'm doing something a bit unusual. I downloaded several variants of Google's Noto font with the intention of using foreign language fonts for interesting-looking characters.

I tried to load them all with a config like this:

log.level=trace;
mono font: fonts/NotoMono-Regular.ttf, size=16;
armenian font: fonts/NotoSansArmenian-Regular.ttf, size=16;
avestan font: fonts/NotoSansAvestan-Regular.ttf, size=16;
balinese font: fonts/NotoSansBalinese-Regular.ttf, size=16;
bamum font: fonts/NotoSansBamum-Regular.ttf, size=16;
batak font: fonts/NotoSansBatak-Regular.ttf, size=16;
brahmi font: fonts/NotoSansBrahmi-Regular.ttf, size=16;
buginese font: fonts/NotoSansBuginese-Regular.ttf, size=16;
canadianaboriginal font: fonts/NotoSansCanadianAboriginal-Regular.ttf, size=16;
carian font: fonts/NotoSansCarian-Regular.ttf, size=16;
cypriot font: fonts/NotoSansCypriot-Regular.ttf, size=16;
glagolitic font: fonts/NotoSansGlagolitic-Regular.ttf, size=16;
imperialaramaic font: fonts/NotoSansImperialAramaic-Regular.ttf, size=16;
inscriptionalparthian font: fonts/NotoSansInscriptionalParthian-Regular.ttf, size=16;
kayahli font: fonts/NotoSansKayahLi-Regular.ttf, size=16;
lepcha font: fonts/NotoSansLepcha-Regular.ttf, size=16;
linearb font: fonts/NotoSansLinearB-Regular.ttf, size=16;
meeteimayek font: fonts/NotoSansMeeteiMayek-Regular.ttf, size=16;
nko font: fonts/NotoSansNKo-Regular.ttf, size=16;
olchiki font: fonts/NotoSansOlChiki-Regular.ttf, size=16;
oldsoutharabian font: fonts/NotoSansOldSouthArabian-Regular.ttf, size=16;
oldturkic font: fonts/NotoSansOldTurkic-Regular.ttf, size=16;
oriya font: fonts/NotoSansOriya-Regular.ttf, size=16;
oriyaui font: fonts/NotoSansOriyaUI-Regular.ttf, size=16;
phagspa font: fonts/NotoSansPhagsPa-Regular.ttf, size=16;
shavian font: fonts/NotoSansShavian-Regular.ttf, size=16;
symbols font: fonts/NotoSansSymbols-Regular.ttf, size=16;
syriaceastern font: fonts/NotoSansSyriacEastern-Regular.ttf, size=16;
tifinagh font: fonts/NotoSansTifinagh-Regular.ttf, size=16;
ugaritic font: fonts/NotoSansUgaritic-Regular.ttf, size=16;

But when I try to use one of the special characters, it's just displayed as the unknown-character box.

terminal.printf(2, 1, "[font=mono]Hello, [color=white]world! [font=brahmi]" + chr(69636))

Why might this be? For reference, I see from the Python bindings that the underlying C function is terminal_print_ext32.

My example is public, so feel free to clone it and try for yourself:

https://github.com/irskep/beepboop/tree/blt-bug-demo <- note the non-master branch

Comments (11)

  1. Alexander Malinin repo owner

    Related: from an API standpoint, it seems weird to me that you can set an 'alternate font' from print() but not for put().

    This is mostly because alternative fonts were not a part of the initial API design: alternative fonts are more about regular text output while terminal_put is more about fast tile/sprite output. You do not really need to load the whole font codespace if you only need a few tiles from it, select tiles may be pin-pointedly loaded to some Private Use codepoints (this is what reverse codepage of TrueType fonts is for, though it is not really intuitive).

    Simply allowing to specify a font by its name in the terminal_put will make put as slow as print (or maybe 'as fast as print' =) these functions are quite fast by themselves but put is clearly does less work). This may be overcome by addressing the font by some id, but there is no id for the fonts in the API.

    Maybe it is possible to make fonts objects (making things up just to get the feel of it):

    terminal.set('brahmi font: brahmi.ttf, size=16')
    brahmi = Font('brahmi')   # Retrieve a reference to the existing font
    terminal.put(brahmi, x, y, 0x11004)
    buginese = Font('buginese.ttf, size=16')  # New unnamed font, addressable only through this variable
    carian = Font('carian: carian.ttf, size=16')  # New named font, addressable by print
    

    Though fonts and tilesets relationship is not straightforward (a font is the separate Unicode codespace as well as the special tileset within this codespace) so it probably won't be this easy. Also, fonts/tilesets currently do not translate well to the objects because most of their properties should be configured at once.

  2. Steve Johnson reporter

    The workaround works! I'll leave it to you to update the issue title to be more accurate.

    I sort of see what you mean about performance, though I must admit I still don't really understand TrueType vs bitmap and how that all works. It sounds like ultimately I should just use TrueType for development and then make a tileset for release for performance if I want to use glyphs from several fonts as game characters.

  3. Alexander Malinin repo owner

    Closely related to this is specifying multiple font tilesets for a single font codespace.

    In the library each font represents a font face, not a font tileset. Each font has its own 'A', its own U+2588, etc. Essentially each font is a separate Unicode codespace. This means a single font (in terms of library) can easily contain several font tilesets (in terms of files/images) which provide different codepoints: one provides tiles for the main Latin character set, another one for the Brahmi language, etc. Because all those Noto font files are actually one font.

    This particular case may be solved quite easily by allowing to specify a list of files as the font resource, e. g.

    noto-sans font: fonts/NotoSans*.ttf, size=16
    

    It is fairly easy and there are .ttc font collection files which are very similar, so I will implement that.

    The problem lies with multiple font files of different origin, e. g. UbuntuMono + FontAwesome which is a pretty fair combination. Or DejaVu + some CJK font. Or even some bitmap font + truetype font. You can't set them up as a single entity. Different fonts has different options and even similar ones can't be easily combined. Unless I'm doing something wrong, there are some truetype fonts with different metrics for different faces (so that mono and regular do not match in size for the same font height). And it pretty impossible to combine bitmap and truetype fonts options. This means they have to be configured separately.

    And for that overlapping collection to operate reliably you have to somehow specify a priority (in the example with DejaVu + CJK you want to use DejaVu latin characters, not the fairly ugly versions from the eastern font), accounting for these sub fonts being added and removed all the time.

    Sadly I can't come up with any sensible configuration mechanic for it.

  4. Log in to comment