Date: Tue, 17 Jan 2023 19:52:07 -0800
From: Bret Victor
Subject: fonts and styled text
I had been printing captions for the progress report using Pages on the Mac, mostly because I wanted to use Avenir and Realtalk couldn't embed fonts into PDFs.  Yesterday I was roadblocked by a pair of back-to-back bugs in Pages, and in my unquenchable rage I ditched the laptop and updated Realtalk's text and font capabilities.  Further reports forthcoming if I actually succeed in turning Realtalk into a page layout wonderland.


Adding fonts

Here's how to make a non-default font available:

    Wish font face "Avenir" uses font file (Ref "8e8bdd3a55a1b0ea022e25a54a7795e8.ttf").


Thereafter, you can measure and draw with it just like any font.

    Wish (you) is labelled "The worst." with font face "Avenir".


We can't unload fonts, so once you wish for a font, you're stuck with it.

If you want to see all the fonts that are currently available:

    When font face /face/ is available:


The default fonts are in "Base fonts":

    Wish font face "Helvetica"    uses font file (Ref "2ce7bccbe71ea34eeb77b96f72ac56a9.ttf") with required (true).

    Wish font face "Helvetica I"  uses font file (Ref "1abbd4cf2d371faa8e43d4e989a7c492.ttf") with required (true).

    (etc)


("required" ensures that the font is downloaded before we create the rendering context, so there are no missing-font surprises.)


Printing with fonts

Draw on a proof with your new font, then print it or convert to PDF.  It just works.

Nonstandard fonts are embedded in the PDF.  They are not subsetted; the whole font is just dropped in.  They're usually pretty small (e.g. Avenir is 53K).


Rescaled fonts

If you ever noticed that our "Serif" font ("Goudy Bookletter 1911"?!) seemed too small, it's because NanoVG was scaling fonts wrong.  That's been fixed, so Serif (and others) renders at the right height and is correctly printable.  The fix ended up being simple, but only after an overlong descent into the font metrics abyss, where only madness reigns.

(Details for future reference:  unitsPerEm from the font's "head" table is the proper way to scale from glyph units to pixels/inches, but NanoVG was scaling by (ascender - descender) from the "hhea" table.  (ascender - descender) == unitsPerEm for many fonts, but not all of them.  Probably nobody ever noticed because we're the first one to try to get NanoVG's output to match PDF.)


Styled ranges

I need my italics.  We can now draw text with styled ranges.

    Wish (you) draws "text" "The worst." with

        ranges { { start_pos=5, end_pos=9, font_face="Helvetica I", color="yellow" } }.


A range can specify font_face, font_size, and/or color, and they will override the text's base settings.

IMG_695701212.jpeg


Styled markup

Sometimes you want to use markup instead of ranges.

    Wish (you) draws "text" "The <i>worst</i>." with

        markup { i = { font_face="Helvetica I", color="yellow" } }.


You can use whatever HTML-like tags you want, and provide a dictionary from tag name to style.  Tags cannot overlap.  There are default styles for some common tags ("i", "b", "em", "strong").

    local text = "I'd <i>like</i> to <big>tell</big> you <mono>about</mono> my <green>problems</green>."

    local styles = {

        big  ={ font_face="Serif", font_size=0.7, color="pink" },

        mono ={ font_face="Mono B", font_size=0.5, color="orange" },

        green={ color="green", font_face="Helvetica B" }

    }

    Wish (you) draws "text" (text) with width (2.5) font size (0.3) background "blue" markup (styles).    


IMG_695705322.jpeg

If you want to convert from markup to ranges for some reason, you can use the function 

    local text, ranges = text_and_ranges_for_markup(html, styles)