% language=us runpath=texruns:manuals/evenmore

\environment evenmore-style

\useMPlibrary[threesix]

\startcomponent evenmore-threesix

\startchapter[title={ThreeSix, Don Knuths first colorfont?}]

In the process of reaching completion and perfection Don Knuth occasionally posts
links to upcoming parts of the TAOCP series on his web pages. Now, I admit that
much is way beyond me but I do understand (and like) the graphics and I know that
Don uses \METAPOST. The next example code is just a proof of concept but might
eventually become a decent module (with helpers) for making (runtime) fonts.
After all, we need to adapt to current developments and \TEX ies always are
willing to adapt and experiment. This chapter was written at the same time as
the previous one on \TYPETHREE\ fonts so you might want to read that first.

The font explored here is \type {FONT36}, used in \quotation {A potpourri of
puzzles} and flagged as \quotation {a special font designed for dissection
puzzles} (in fascicle 9b for Volume 4). Playing with and visualizing for me often
works better than formulas, which then distracts me from the original purpose,
but let's have a closer look anyway.

\startlinecorrection
    \scale[width=\textwidth]{\DEKFontA 1234567890} \vskip1ex
    \scale[width=\textwidth]{\DEKFontA ABC{\red DE}FGHIJ{\red K}LM} \vskip1ex
    \scale[width=\textwidth]{\DEKFontA NOPQRSTUVWXYZ}
\stoplinecorrection

The font has a fixed maximum height of 8~quantities. There is no depth in the
characters. Some characters are wider. In this example we use a tight bounding
box. In \CONTEXT\ speak this font is just a regular font but with a special
feature enabled.

\starttyping
\definefontfeature
  [fontthreesix]
  [default]
  [metapost=fontthreesix]

\definefont[DEKFontA][Serif*fontthreesix]
\stoptyping

After this the \type {\DEKFontA} command will set this font as current font. The
definition mentions \type {Serif} as font name. In \CONTEXT\ this name will
resolve in the currently defined Serif, so when your document uses Latin Modern
that will be the one. The \type {fontthreesix} will make this instance use that
feature set, and the feature definition has the defaults as parent (so we get
kerning, ligatures, etc.) but as extra feature also \type {metapost}. This means
that the new glyphs that are about to be defined will actually be injected in the
\type {Serif}! We will replace characters in that instance. So, the following:

\startbuffer[taocp]
This font is used in \quotation {The Art Of Computer Programming} by
Don Knuth, not in volume~1, 2 or~3, but in number~4!
\stopbuffer

\typebuffer[taocp]

comes out as:

\startnarrower
\DEKFontA \getbuffer[taocp]
\stopnarrower

But that doesn't look too good, so we will tweak the font a bit:

\starttyping
\definefontfeature
  [fontthreesix-color]
  [default]
  [metapost={category=fontthreesix,spread=.1}]

\definefont[DEKFontD][Serif*fontthreesix]
\stoptyping

The \type {spread} (multiplied by the font unit, which is 12 basepoints here)
will add a bit more spacing around the blob:

\startnarrower
\DEKFontD \getbuffer[taocp]
\stopnarrower

Now, keep in mind that we're talking of a real font here. You can cut and paste
these characters. It's just the default uppercase Latin alphabet plus digits.

Before we go and look at some of the code needed to render this, a few more
examples will be given.

\startlinecorrection
    \scale[width=\textwidth]{\DEKFontB 1234567890}    \vskip4pt
    \scale[width=\textwidth]{\DEKFontB ABCDEFGHIJKLM} \vskip4pt
    \scale[width=\textwidth]{\DEKFontB NOPQRSTUVWXYZ}
\stoplinecorrection

In the above example we not only use color, but also a different shape and random
colors (that is: random per \TEX\ job). The feature definition for this is:

\starttyping
\definefontfeature
  [fontthreesix-color]
  [default]
  [metapost={%
    category=fontthreesix,shape=diamond,%
    color=random,pen=fancy,spread=.1%
  }]
\stoptyping

Possible shapes are \type {circle}, \type {diamond} and \type {square} and
instead of a random color one can give a known color name. Using transparency
makes no sense in this font.

A nice usage for this font are initials: % 4 for lm

\startbuffer
\setupinitial[font=Serif*fontthreesix-initial sa 5]
{\DEKFontB \placeinitial \input zapf\par}
\stopbuffer

\typebuffer

The initial feature is defined as:

\starttyping
\definefontfeature
  [fontthreesix-initial]
  [metapost={category=fontthreesix,color=random,shape=circle}]
\stoptyping

We use this in quoting Hermann Zapf, one that for sure is very applicable in
a case like this:

\startnarrower
\getbuffer
\stopnarrower

Some combinations of sub|-|features are shown in \in {figure} [threesix:dek]. We
blow up the diamond with fancy pen example in \in {figure} [threesix:tex]. Alas,
the \TEX\ logo doesn't look that good in such a font. Using it for acronyms is
not a good idea anyway, but maybe you can figure out \in {figure}
[threesix:taocp].

% todo penx peny penr

\definefontfeature
  [fontthreesix-circle]
  [metapost={category=fontthreesix,shape=circle,color=random}]
\definefontfeature
  [fontthreesix-square]
  [metapost={category=fontthreesix,shape=square,color=random}]
\definefontfeature
  [fontthreesix-diamond]
  [metapost={category=fontthreesix,shape=diamond,color=random}]
\definefontfeature
  [fontthreesix-circle-pen]
  [metapost={category=fontthreesix,shape=circle,color=random,pen=fancy}]
\definefontfeature
  [fontthreesix-square-pen]
  [metapost={category=fontthreesix,shape=square,color=random,pen=fancy}]
\definefontfeature
  [fontthreesix-diamond-pen]
  [metapost={category=fontthreesix,shape=diamond,color=random,pen=fancy}]
\definefontfeature
  [fontthreesix-circle-random]
  [metapost={category=fontthreesix,random=yes,shape=circle,color=random}]
\definefontfeature
  [fontthreesix-square-random]
  [metapost={category=fontthreesix,random=yes,shape=square,color=random}]
\definefontfeature
  [fontthreesix-diamond-random]
  [metapost={category=fontthreesix,random=yes,shape=diamond,color=random}]

\definefontfeature
  [fontthreesix-circle-random-spread]
  [metapost={category=fontthreesix,random=yes,shape=circle,color=random,spread=.1}]

\startplacefigure[reference=threesix:dek]
    \startcombination[3*3]
        {\scale[width=.3\textwidth]{\definedfont        [Serif*fontthreesix-circle]D\kern1pt E\kern 1ptK}} {\type{shape=circle}}
        {\scale[width=.3\textwidth]{\definedfont        [Serif*fontthreesix-square]D\kern1pt E\kern 1ptK}} {\type{shape=square}}
        {\scale[width=.3\textwidth]{\definedfont       [Serif*fontthreesix-diamond]D\kern1pt E\kern 1ptK}} {\type{shape=diamond}}
        {\scale[width=.3\textwidth]{\definedfont    [Serif*fontthreesix-circle-pen]D\kern1pt E\kern 1ptK}} {\type{shape=circle,pen=fancy}}
        {\scale[width=.3\textwidth]{\definedfont    [Serif*fontthreesix-square-pen]D\kern1pt E\kern 1ptK}} {\type{shape=square,pen=fancy}}
        {\scale[width=.3\textwidth]{\definedfont   [Serif*fontthreesix-diamond-pen]D\kern1pt E\kern 1ptK}} {\type{shape=diamond,pen=fancy}}
        {\scale[width=.3\textwidth]{\definedfont [Serif*fontthreesix-circle-random]D\kern1pt E\kern 1ptK}} {\type{shape=circle,random=yes}}
        {\scale[width=.3\textwidth]{\definedfont [Serif*fontthreesix-square-random]D\kern1pt E\kern 1ptK}} {\type{shape=square,random=yes}}
        {\scale[width=.3\textwidth]{\definedfont[Serif*fontthreesix-diamond-random]D\kern1pt E\kern 1ptK}} {\type{shape=diamond,random=yes}}
    \stopcombination
\stopplacefigure

\startplacefigure[reference=threesix:tex]
\scale[width=\textwidth]{\definedfont[Serif*fontthreesix-diamond-pen]T\lower.5ex\hbox spread .1em{\hss E\hss}X}
\stopplacefigure

\startplacefigure[reference=threesix:taocp]
\scale[width=\textwidth]{\definedfont[Serif*fontthreesix-circle-random-spread]TAOCP}
\stopplacefigure

You can quit reading now or expose yourself to how this is coded. We use a
combination of \LUA\ and \METAPOST, but different solutions are possible. The
shapes are entered (or course) with zeros and ones.

\starttyping
\startluacode
local font36 = {
    ["0"] = "00111100 01111110 11000011 11000011 11000011 ...",
    ["1"] = "00011100 11111100 11101100 00001100 00001100 ...",
    .....
    ["D"] = "11111100 11100010 01100011 01100011 01100011 ...",
    ["E"] = "1111111 1110001 0110101 0111100 0110100 0110001 ...",
    .....
    ["K"] = "11101110 11100100 01101000 01110000 01111000 ...",
    .....
}
\stopluacode
\stoptyping

We also use \LUA\ to register this font. The actual code looks slightly different
because it uses some helpers from the \CONTEXT\ \LUA\ libraries. We remap the
bits pattern onto \METAPOST\ macro calls.

\starttyping
\startluacode
local replace = {
    ["0"] = "N;",
    ["1"] = "Y;",
    [" "] = "L;",
}

function MP.registerthreesix(name)
    fonts.dropins.registerglyphs {
        name     = name,
        units    = 12,
        usecolor = true,
    }
    for u, v in table.sortedhash(font36) do
        local ny     = 8
        local nx     = (#v - ny + 1) // ny
        local height = ny * 1.1 - 0.1
        local width  = nx * 1.1 - 0.1
        local code   = string.gsub(v,".",replace)
        fonts.dropins.registerglyph {
            category = name,
            unicode  = utf.byte(u),
            width    = width,
            height   = height,
            code     = string.format("ThreeSix(%s);",code),
        }
    end
end

MP.registerthreesix("fontthreesix")
\stopluacode
\stoptyping

So, after this the font \type {fontthreesix} is known to the system but we still
need to provide \METAPOST\ code to generate it. The glyphs themselves are now
just sequences of \type {N}, \type {Y} and \type {L} with some wrapper code
around it. The definitions are put in the \type {MP} namespace simply because a
first version initialized in \METAPOST, and there could create variants, but in
the end I settled on the parameter interface at the \TEX\ end.

The next definition looks a bit complex but normally such a macro is
stepwise constructed. Notice how we can query the sub features. In order to make
that possible the regular \METAFUN\ parameter handling code is used. We just push
the sub|-|features into to \type {mpsfont} namespace.

\starttyping
\startMPcalculation{simplefun}

def InitializeThreeSix =
    save Y, N, L, S ; save dx, dy, nx, ny ; save currentpen ;
    save shape, fillcolor, mypen, random, spread, hoffset ;
    string shape, fillcolor, mypen ; boolean random ;
    pen currentpen ;
    dx :=   11/10 ;
    dy := - 11/10 ;
    nx := - dx ;
    ny :=   0 ;
    shape      := getparameterdefault "mpsfont" "shape" "circle" ;
    random     := hasoption           "mpsfont" "random" "true" ;
    fillcolor  := getparameterdefault "mpsfont" "color" "" ;
    mypen      := getparameterdefault "mpsfont" "pen" "" ;
    spread     := getparameterdefault "mpsfont" "spread" 0 ;
    hoffset    := 12 * spread / 2 ;
    currentpen := pencircle
        if mypen = "fancy" :
            xscaled 1/20 yscaled 2/20 rotated 45
        else :
            scaled 1/20
        fi ;
    if shape == "square" :
        def S =
            unitsquare if random : randomized 1/10 fi
            shifted (nx,ny)
        enddef ;
    elseif shape = "diamond" :
        def S =
            unitdiamond if random : randomized 1/10 fi
            shifted (nx,ny)
        enddef ;
    else :
        def S =
            unitcircle if random : randomizedcontrols 1/20 fi
            shifted (nx,ny)
        enddef ;
    fi ;
    def N =
        nx := nx + dx ;
        draw S ;
    enddef ;
    if fillcolor = "random" :
        def Y =
            nx := nx + dx ;
            fillup S withcolor white randomized (2/3,2/3,2/3) ;
        enddef ;
    elseif fillcolor = "" :
        def Y =
            nx := nx + dx ;
            fillup S ;
        enddef ;
    else :
        def Y =
            nx := nx + dx ;
            fillup S withcolor fillcolor ;
        enddef ;
    fi ;
    def L =
        nx := - dx ;
        ny := ny + dy ;
    enddef ;
enddef ;

vardef ThreeSix (text code) =
    InitializeThreeSix ; % todo: once per instance run
    draw image (code) shifted (hoffset,-ny) ;
enddef ;

\stopMPcalculation
\stoptyping

This code is not that efficient in the sense that there's quite some
\METAPOST|-|\LUA|-|\METAPOST\ traffic going on, for instance each parameter check
involves this, but in practice performance is quite okay, certainly for such a
small font. There will be an initializer option some day soon. The \type
{simplefun} is a reference to an \MPLIB\ instance that does load \METAFUN\ but
only the modules that make no sense for this kind of usage. It also enforces
double mode. The calculations wrapper just executes the code and does not place
some (otherwise empty) graphic.

% After playing with the font I see the beauty of the descriptions in the
% pre|-|fascicle 9b but I still feel pretty stupid. Lucky for me there are
% exercises like 999, tagged as \quote {for dummies}, so I'm not alone.

Those who have seen (and|/|or read) \quotation {Concrete Mathematics} will have
noticed the use of inline images, like dice. Dice are also used in \quotation
{pre-fascicle 5a} (I need a few more lives to grasp that, so I stick to the
images for now!). So, to compensate the somewhat complex code above, I will show
how to accomplish that. This time we do all in \METAPOST:

\startMPcalculation{simplefun}

def DiceFrame =
    pickup pencircle scaled 1/2 ;
    draw unitsquare scaled 8 ;
    pickup pencircle scaled 3/2 ;
enddef ;

vardef DiceOne =
    DiceFrame ;
    draw (4,4) ;
enddef ;
vardef DiceTwoA =
    DiceFrame ;
    draw (2,6) ; draw (6,2) ;
enddef ;
vardef DiceTwoB =
    DiceFrame ;
    draw (6,6) ; draw (2,2) ;
enddef ;
vardef DiceTwo =
    if hasoption "mpsfont" "option" "reverse" :
        DiceTwoB
    else :
        DiceTwoA
    fi ;
enddef ;
vardef DiceThreeA =
    DiceFrame ;
    draw (2,6) ; draw (4,4) ; draw (6,2) ;
enddef ;
vardef DiceThreeB =
    DiceFrame ;
    draw (6,6) ; draw (4,4) ; draw (2,2) ;
enddef ;
vardef DiceThree =
    if hasoption "mpsfont" "option" "reverse" :
        DiceThreeB
    else :
        DiceThreeA
    fi ;
enddef ;
vardef DiceFour =
    DiceFrame ;
    draw (2,6) ; draw (6,6) ; draw (2,2) ; draw (6,2) ;
enddef ;
vardef DiceFive =
    DiceFrame ;
    draw (2,6) ; draw (6,6) ; draw (4,4) ; draw (2,2) ; draw (6,2) ;
enddef ;
vardef DiceSix =
    DiceFrame ;
    draw (2,6) ; draw (6,6) ; draw (2,4) ; draw (6,4) ; draw (2,2) ; draw (6,2) ;
enddef ;

vardef DiceBad =
    pickup pencircle scaled 1/2 ;
    draw unitsquare scaled 8 ;
    draw (1,7) -- (7,1) ; draw (1,1) -- (7,7) ;
enddef ;

lmt_registerglyphs [
    name     = "dice",
    units    = 12,
    width    = 8,
    height   = 8,
    depth    = 0,
    usecolor = true,
] ;

lmt_registerglyph [ category = "dice", unicode = "0x2680", code = "DiceOne;" ] ;
lmt_registerglyph [ category = "dice", unicode = "0x2681", code = "DiceTwo;" ] ;
lmt_registerglyph [ category = "dice", unicode = "0x2682", code = "DiceThree;" ] ;
lmt_registerglyph [ category = "dice", unicode = "0x2683", code = "DiceFour;" ] ;
lmt_registerglyph [ category = "dice", unicode = "0x2684", code = "DiceFive;" ] ;
lmt_registerglyph [ category = "dice", unicode = "0x2685", code = "DiceSix;" ] ;

lmt_registerglyph [ category = "dice", private = "invaliddice", code = "DiceBad;" ] ;

\stopMPcalculation

This is not that hard to follow. We define some shapes first. These could have
been assigned to the \type {code} parameter directly but this is nicer. Next we
register the font itself and after that we set glyphs. We also set the official
\UNICODE\ slots. So, copying a dice can either result in a digit or in a
\UNICODE\ slot for a dice. In the example below we switch to a color which
demonstrates that our dice can be colored at the \TEX\ end. It's either that or
coloring at the \METAPOST\ end as both demand a different kind of \TYPETHREE\
embedding trickery.

We actually predefine three features. The digits one will map regular digit in
the input to dice. We accomplish that via a font feature:

\startbuffer
\startluacode
fonts.handlers.otf.addfeature("dice:digits", {
    type      = "substitution",
    order     = { "dice:digits" },
    nocheck   = true,
    data      = {
        [0x30] = "invaliddice",
        [0x31] = 0x2680,
        [0x32] = 0x2681,
        [0x33] = 0x2682,
        [0x34] = 0x2683,
        [0x35] = 0x2684,
        [0x36] = 0x2685,
        [0x37] = "invaliddice",
        [0x38] = "invaliddice",
        [0x39] = "invaliddice",
    },
} )
\stopluacode
\stopbuffer

\typebuffer \getbuffer

This kind of trickery is part of the font machinery used in \CONTEXT\ and permits
runtime adaption of fonts, so we just use the same mechanism. The \type {nocheck}
is needed to avoid this feature not kicking in due to lack of (at the time of
checking) yet undefined dice.

\startbuffer
\definefontfeature
  [dice:normal]
  [default]
  [metapost={category=dice}]
\definefontfeature
  [dice:reverse]
  [default]
  [metapost={category=dice,option=reverse}]
\definefontfeature
  [dice:digits]
  [dice:digits=yes]

\definefont[DiceN] [Serif*dice:normal]
\definefont[DiceD] [Serif*dice:normal,dice:digits]
\definefont[DiceR] [Serif*dice:reverse,dice:digits]

{\DiceD Does 1 it 4 work? And {\darkgreen 3} too?} {\DiceR And how about
{\darkred 3} then? But 8 should sort of fail!}
\stopbuffer

\typebuffer \getbuffer

The six digits and \UNICODE\ characters come out the same:

\startbuffer
\red  \DiceD \dostepwiserecurse   {`1}   {`6}{1}{\char#1\quad}%
\blue \DiceN \dostepwiserecurse{"2680}{"2685}{1}{\char#1\quad}%
\stopbuffer

\typebuffer

\startlinecorrection
    \scale[width=\textwidth]{\getbuffer\unskip}
\stoplinecorrection

It is tempting to implement for instance~7 as two dice (a one to multi mapping in
\OPENTYPE\ speak) but then one has to decide what combination is taken. One can
also implement ligatures so that for instance 12 results in two six dice. But I
think that's over the top and only showing \TEX\ muscles. It is anyway not that
hard to do as we have an interface for that already.

So why not do the dominos as well? Because there are so many dominos we predefine
the shapes and then register the lot in a loop. We have horizontal and vertical
variants. Being lazy I just made two helpers while one could have done but with
some rotation and shifting of the horizontal one. The loop could be a macro but
we don't save much code that way.

\startbuffer
\startMPcalculation{simplefun}

picture Dominos[] ;

Dominos[0] := image() ;
Dominos[1] := image(draw(4,4);) ;
Dominos[2] := image(draw(2,6);draw(6,2););
Dominos[3] := image(draw(2,6);draw(4,4);draw(6,2););
Dominos[4] := image(draw(2,6);draw(6,6);draw(2,2);draw(6,2););
Dominos[5] := image(draw(2,6);draw(6,6);draw(4,4);draw(2,2);draw(6,2););
Dominos[6] := image(draw(2,6);draw(4,6);draw(6,6);draw(2,2);draw(4,2);draw(6,2););

lmt_registerglyphs [
    name     = "dominos",
    units    = 12,
    width    = 16,
    height   = 8,
    depth    = 0,
    usecolor = true,
] ;

def DrawDominoH(expr a, b) =
    draw image (
        pickup pencircle scaled 1/2 ;
        if (getparameterdefault "mpsfont" "color" "") = "black" :
            fillup unitsquare xyscaled (16,8) ;
            draw (8,.5) -- (8,7.5) withcolor white ;
            pickup pencircle scaled 3/2 ;
            draw Dominos[a]
                withpen currentpen
                withcolor white ;
            draw Dominos[b] shifted (8,0)
                withpen currentpen
                withcolor white ;
        else :
            draw unitsquare xyscaled (16,8) ;
            draw (8,0) -- (8,8) ;
            pickup pencircle scaled 3/2 ;
            draw Dominos[a]
                withpen currentpen ;
            draw Dominos[b] shifted (8,0)
                withpen currentpen ;
        fi ;
    ) ;
enddef ;

def DrawDominoV(expr a, b) = % is H rotated and shifted
    draw image (
        pickup pencircle scaled 1/2 ;
        if (getparameterdefault "mpsfont" "color" "") = "black" :
            fillup unitsquare xyscaled (8,16) ;
            draw (.5,8) -- (7.5,8) withcolor white ;
            pickup pencircle scaled 3/2 ;
            draw Dominos[a] rotatedaround(center Dominos[a],90)
                withpen currentpen
                withcolor white  ;
            draw Dominos[b] rotatedaround(center Dominos[b],90) shifted (0,8)
                withpen currentpen
                withcolor white  ;
        else :
            draw unitsquare xyscaled (8,16) ;
            draw (0,8) -- (8,8) ;
            pickup pencircle scaled 3/2 ;
            draw Dominos[a] rotatedaround(center Dominos[a],90)
                withpen currentpen ;
            draw Dominos[b] rotatedaround(center Dominos[b],90) shifted (0,8)
                withpen currentpen ;
        fi ;
    ) ;
enddef ;

begingroup
    save unicode ; numeric unicode ; unicode := 127025 ; % 1F031

    for i=0 upto 6 :
        for j=0 upto 6 :
            lmt_registerglyph [
                category = "dominos",
                unicode  = unicode,
                code     = "DrawDominoH(" & decimal i & "," & decimal j & ");",
                width    = 16,
                height   = 8,
            ] ;
            unicode := unicode + 1 ;
        endfor ;
    endfor ;

    save unicode ; numeric unicode ; unicode := 127075 ;

    for i=0 upto 6 :
        for j=0 upto 6 :
            lmt_registerglyph [
                category = "dominos",
                unicode  = unicode,
                code     = "DrawDominoV(" & decimal i & "," & decimal j & ");",
                width    = 8,
                height   = 16,
            ] ;
            unicode := unicode + 1 ;
        endfor ;
    endfor ;
endgroup ;

\stopMPcalculation
\stopbuffer

\typebuffer \getbuffer

Again we predefine a couple of features:

\startbuffer
\definefontfeature
  [dominos:white]
  [default]
  [metapost={category=dominos}]

\definefontfeature
  [dominos:black]
  [default]
  [metapost={category=dominos,color=black}]

\definefontfeature
  [dominos:digits]
  [dominos:digits=yes]
\stopbuffer

\typebuffer \getbuffer

This last feature is yet to be defined. We could deal with the invalid dominos
with some substitution trickery but let's keep it simple.

\startbuffer
\startluacode
local ligatures = { }
local unicode   = 127025

for i=0x30,0x36 do
    for j=0x30,0x36 do
        ligatures[unicode] = { i, j }
        unicode = unicode + 1 ;
    end
end

fonts.handlers.otf.addfeature("dominos:digits", {
    type      = "ligature",
    order     = { "dominos:digits" },
    nocheck   = true,
    data      = ligatures,
} )
\stopluacode
\stopbuffer

\typebuffer \getbuffer

That leaves showing an example. We define a few fonts and again we just extend
the Serif:

\startbuffer
\definefont[DominoW][Serif*dominos:white]
\definefont[DominoB][Serif*dominos:black]
\definefont[DominoD][Serif*dominos:white,dominos:digits]
\stopbuffer

\typebuffer \getbuffer

The example is:

\startbuffer
\DominoW
    \char"1F043\quad 🀱\quad
    \char"1F052\quad 🀲\quad
    \char"1F038\quad 🀳\quad
    \darkgreen\char"1F049\quad \char"1F07B\quad
\DominoB
    \char"1F087\quad
    \char"1F088\quad
    \char"1F089\quad
\DominoD
    \darkred 12\quad56\quad64
\stopbuffer

\typebuffer

Watch the ligatures in action:

\startlinecorrection
    \scale[width=\textwidth]{\getbuffer\unskip}
\stoplinecorrection

To what extent the usage of symbols like dice and dominos as characters in the
mentioned book are responsible for them being in \UNICODE, I don't know. Now with
all these emoji showing up one can wonder about graphics in such a standard
anyway. But for sure, even after more than three decades, Don still makes nice
fonts.

A treasure of tiny graphics can be found in \quotation {pre-fascicle 5c} and many
are in color! In fact, it has dominos too. It must have been a lot of fun writing
this! I'm thinking of turning the pentominoes into a font where a \type {GPOS}
feature can deal with the inter|-|pentomino kerning (which mighty work out okay
for example~36. The windmill dominos also make a nice example for a font where
ligatures will boil down to the base form and the (one or more) blades are laid
over. It's definitely an inspiring read.

\stopchapter

\stoptext
