evenmore-fonts.tex /size: 28 Kb    last modification: 2021-10-28 13:50
1% language=us runpath=texruns:manuals/evenmore
2
3\environment evenmore-style
4
5\disabledirectives[fonts.svg.cached]
6
7% \usemodule[scite]
8% \usemodule[article-basic]
9% \usemodule[abbreviations-logos]
10
11\startcomponent evenmore-fonts
12
13\startchapter[title=Modern Type 3 fonts]
14
15Support for \TYPETHREE\ fonts has been on my agenda for a couple of years now.
16Here I will take a look at them from the perspective of \LUAMETATEX. \footnote
17{This chapter appeared in \TUGBOAT\ 40:3. Thanks to Karl Berry for corrections.}
18The reason is that they might be useful for embedding (for instance) runtime
19graphics (such as symbols) in an efficient way. In \TEX\ systems \TYPETHREE\
20fonts are normally used for bitmap fonts, the \PK\ output that comes via
21\METAFONT. Where for instance \TYPEONE\ fonts are defined using a set of font
22specific rendering operators, a \TYPETHREE\ font can contain arbitrary code, in
23\PDF\ files these are \PDF\ (graphic and text) operators.
24
25A program like \LUATEX\ supports embedding of several font formats natively. A
26quick summary of relevant formats is the following: \footnote {Technically one
27can embed anything in the \PDF\ file.}
28
29\startitemize[headintext][headstyle=bold]
30\starthead {\TYPEONE:}
31    these are outline fonts using \type {cff} descriptions, a compact format for
32    storing outlines. Normally up to 256 characters are accessible but a font can
33    have many more (as Latin Modern and \TEX\ Gyre demonstrate).
34\stophead
35\starthead {\OPENTYPE:}
36    these also use the \type {cff} format. As with \TYPEONE\ the outlines are
37    mostly cubic Bezier curves. Because there is no bounding box data stored in
38    the format the engine has to pseudo|-|render the glyphs to get that
39    information. When embedding a subset the backend code has to flatten the
40    subroutine calls, which is another reason the \type {cff} blob has to be
41    disassembled.
42\stophead
43\starthead {\TRUETYPE:}
44    these use the \type {ttf} format which uses quadratic B|-|splines. The font
45    can have a separate kerning table and stores information about the bounding
46    box (which is then used by \TEX\ to get the right heights and depths of
47    glyphs). Of course those details never make it into the \PDF\ file as such.
48\stophead
49\starthead {\TYPETHREE:}
50    as mentioned this format is (traditionally) used to store bitmap fonts but as
51    we will see it can do more. It is actually the easiest format to deal with.
52\stophead
53\stopitemize
54
55In \LUATEX\ any font can be a \quotation {wide} font, therefore in \CONTEXT\ a
56\TYPEONE\ font is not treated differently than an \OPENTYPE\ font. The \LUATEX\
57backend can even disguise a \TYPEONE\ font as an \OPENTYPE\ font. In the end, as
58not that much information ends up in the \PDF\ file, the differences are not that
59large for the first three types. The content of a \TYPETHREE\ font is less
60predictable but even then it can have for instance a \type {ToUnicode} vector so
61it has no real disadvantages in, say, accessibility. In \CONTEXT\ \LMTX, which
62uses \LUAMETATEX\ without any backend, all is dealt with in \LUA: loading,
63tweaking, applying and embedding.
64
65The difference between \OPENTYPE\ and \TRUETYPE\ is mostly in the kind of curves
66and specific data tables. Both formats are nowadays covered by the \OPENTYPE\
67specification. If you Google for the difference between these formats you can
68easily end up with rather bad (or even nonsense) descriptions. The best
69references are \typ {https://en.wikipedia.org/wiki/Bézier_curve} and the
70ever|-|improving \typ {https://docs.microsoft.com/en-us/typography} website.
71
72Support for so|-|called variable fonts is mostly demanding of the front|-|end
73because in the backend it is just an instance of an \OPENTYPE\ or \TRUETYPE\ font
74being embedded. In this case the instance is generated by the \CONTEXT\ font
75machinery which interprets the \type {cff} and \type {ttf} binary formats in
76doing~so. This feature is not widely used but has been present from the moment
77these fonts showed up.
78
79\TYPETHREE\ fonts don't have a particularly good reputation, which is mainly due
80to the fact that viewers pay less attention in displaying them, at least that was
81the case in the past. If they describe outlines, then all is okay, apart from the
82fact that there is no anti|-|aliasing or hinting but on modern computers that is
83hardly an issue. For bitmaps the quality depends on the resolution and
84traditionally \TEX\ bitmap fonts are generated for a specific device, but if you
85use a decent resolution (say 1200 dpi) then all should be okay. The main drawback
86is that viewers will render such a font and cache the (then available) bitmap
87which in some cases can have a speed penalty.
88
89Using \TYPETHREE\ fonts in a \PDF\ backend is not something new. Already in the
90\PDFTEX\ era we were playing with so|-|called \PDF\ glyph containers. In practice
91that worked okay but not so much for \METAPOST\ output from \METAFONT\ fonts. As
92a side note: it might actually work better now that in \METAFUN\ we have some
93extensions for rendering the kind of paths used in fonts. But glyph containers
94were dropped long ago already and \TYPETHREE\ was limited to traditional \TEX\
95bitmap inclusion. However, in \LUAMETATEX\ it is easier to mess around with fonts
96because we no longer need to worry about side effects of patching font related
97inclusion (embedding) for other macro packages. All is now under \LUA\ control:
98there is no backend included and therefore no awareness of something built|-|in
99as \TYPETHREE.
100
101So, as a prelude to the 2019 \CONTEXT\ meeting, I picked up this thread and
102turned some earlier experiments into production code. Originally I meant to
103provide support for \METAPOST\ graphics but that is still locked in experiments.
104I do have an idea for its interface, now that we have more control over user
105interfaces in \METAFUN.
106
107In addition to \quote {just graphics} there is another candidate for \TYPETHREE\
108fonts \emdash\ extensions to \OPENTYPE\ fonts:
109
110\startitemize[packed,n]
111\startitem Color fonts where stacked glyphs are used (a nice method). \stopitem
112\startitem Fonts where \SVG\ images are used. \stopitem
113\startitem Fonts that come with bitmap representations in \PNG\ format. \stopitem
114\stopitemize
115
116It will be no surprise that we're talking of emoji fonts here although the second
117category is now also used for regular text fonts. When these fonts showed up
118support for them was not that hard to implement and (as often) we could make
119\TEX\ be among the first to support them in print (often such fonts are meant for
120the web).
121
122For category one, the stacked shapes, the approach was to define a virtual font
123where glyphs are flushed while backtracking over the width in order to get the
124overlay. Of course color directives have to be injected too. The whole lot is
125wrapped in a container that tells a \PDF\ handler what character actually is
126represented. Due to the way virtual fonts work, every reference to a character
127results in the same sequence of glyph references, (negative) kern operations and
128color directives plus the wrapper in the page stream. This is not really an issue
129for emoji because these are seldom used and even then in small quantities. But it
130can explode a \PDF\ page stream for a color text font. All happens at runtime and
131because we use virtual fonts, the commands are assembled beforehand for each
132glyph.
133
134For the second category, \SVG\ images, we used a different approach. Each symbol
135was converted to \PDF\ using Inkscape and cached for later use. Instead of
136injecting a glyph reference, a reference to a so|-|called \type {XForm} is
137injected, again with a wrapper to indicate what character we deal with. Here the
138overhead is not that large but still present as we need the so|-|called \quote
139{actual text} wrapper.
140
141The third category is done in a similar way but this time we use GraphicsMagick
142to convert the images beforehand. The drawbacks are the same.
143
144In \CONTEXT\ \LMTX\ a different approach is followed. The \PDF\ stream that
145stacks the glyphs of category one makes a perfect stream for a \TYPETHREE\
146character. Apart from some juggling to relate a \TYPETHREE\ font to an \OPENTYPE\
147font, the page stream just contains references to glyphs (with the proper related
148\UNICODE\ slot). The overhead is minimal.
149
150For the second category \CONTEXT\ \LMTX\ uses its built|-|in \SVG\ converter. The
151\XML\ code of the shape is converted to (surprise): \METAPOST. We could go
152directly to \PDF\ but the \METAPOST\ route is cheap and we can then get support
153for color spaces, transformations, efficient paths and high quality all for free.
154It also opens up the possibility for future manipulations. The \TYPETHREE\ font
155eventually has a sequence of drawing operations, mixed with transformations and
156color switches, but only once. Most of the embedded code is shared with the other
157categories (a plug|-|in model is used).
158
159The third category follows a similar route but this time we use the built|-|in
160\PNG\ inclusion code. Just like the other categories, the page stream only
161contains references to glyphs.
162
163It was interesting to find that most of the time related to the inclusion went
164into figuring out why viewers don't like these fonts. For instance, in Acrobat
165there needs to be a glyph at index zero and all viewers seem to be able to handle
166at most 255 additional characters in a font. But once that, and a few more
167tricks, had become clear, it worked out quite well. It also helps to set the font
168bounding box to all zero values so that no rendering optimizations kick in. Also,
169some dimensions can are best used consistently. With \SVG\ there were some issues
170with reference points and bounding boxes but these could be dealt with. A later
171implementation followed a slightly different route anyway.
172
173The implementation is reasonably efficient because most work is delayed till a
174glyph (shape) is actually injected (and most shapes in these fonts aren't used at
175all). The viewers that I have installed, Acrobat Reader, Acrobat X, and the
176mupdf|-|based Sumatra\PDF\ viewer can all handle the current implementation.
177
178An example of a category one font is \MICROSOFT's \type {seguiemj}. I have no
179clue about the result in the future because some of these emoji fonts change
180every now and then, depending also on social developments. This is a category one
181font which not only has emoji symbols but also normal glyphs:
182
183\startbuffer[1a]
184\definefontfeature[colored][default][colr=yes]
185\definefont[TestA][file:seguiemj.ttf*colored]
186\definesymbol[bug1][\getglyphdirect{file:seguiemj.ttf*colored} {\char"1F41C}]
187\definesymbol[bug2][\getglyphdirect{file:seguiemj.ttf*colored} {\char"1F41B}]
188\stopbuffer
189
190\typebuffer[1a][option=TEX] \getbuffer[1a]
191
192The example below demonstrates this by showing the graphic glyph surrounded by
193the \type {x} from the emoji font, and from a regular text font.
194
195\startbuffer[1b]
196{\TestA x\char"1F41C x\char"1F41B x}%
197\quad
198{x\symbol[bug1]x\symbol[bug2]x}%
199\quad
200{\showglyphs x\symbol[bug1]x\symbol[bug2]x}%
201\stopbuffer
202
203\typebuffer[1b][option=TEX]
204
205\startlinecorrection
206\scale[width=\textwidth]{\getbuffer[1b]}
207\stoplinecorrection
208
209In this mix we don't use a \TYPETHREE\ font for the characters that don't need
210stacked (colorful) glyphs, which is more efficient. So the \type {x} characters
211are references to a regular (embedded) \OPENTYPE\ font.
212
213The next example comes from a manual and demonstrates that we can (still)
214manipulate colors as we wish.
215
216\startbuffer[1c]
217\definecolor[emoji-red]   [r=.4]
218\definecolor[emoji-blue]  [b=.4]
219\definecolor[emoji-green] [g=.4]
220\definecolor[emoji-yellow][r=.4,g=.5]
221\definecolor[emoji-gray]  [s=1,t=.5,a=1]
222
223\definefontcolorpalette
224  [emoji-red]
225  [emoji-red,emoji-gray]
226
227\definefontcolorpalette
228  [emoji-green]
229  [emoji-green,emoji-gray]
230
231\definefontcolorpalette
232  [emoji-blue]
233  [emoji-blue,emoji-gray]
234
235\definefontcolorpalette
236  [emoji-yellow]
237  [emoji-yellow,emoji-gray]
238
239\definefontfeature[seguiemj-r][default][ccmp=yes,dist=yes,colr=emoji-red]
240\definefontfeature[seguiemj-g][default][ccmp=yes,dist=yes,colr=emoji-green]
241\definefontfeature[seguiemj-b][default][ccmp=yes,dist=yes,colr=emoji-blue]
242\definefontfeature[seguiemj-y][default][ccmp=yes,dist=yes,colr=emoji-yellow]
243
244\definefont[MyColoredEmojiR][seguiemj*seguiemj-r]
245\definefont[MyColoredEmojiG][seguiemj*seguiemj-g]
246\definefont[MyColoredEmojiB][seguiemj*seguiemj-b]
247\definefont[MyColoredEmojiY][seguiemj*seguiemj-y]
248\stopbuffer
249
250\typebuffer[1c][option=TEX] \getbuffer[1c]
251
252\startbuffer[1d]
253\MyColoredEmojiR\resolvedemoji{man}\resolvedemoji{woman}%
254\MyColoredEmojiG\resolvedemoji{man}\resolvedemoji{woman}%
255\MyColoredEmojiB\resolvedemoji{man}\resolvedemoji{woman}%
256\MyColoredEmojiY\resolvedemoji{man}\resolvedemoji{woman}%
257\stopbuffer
258
259\startlinecorrection
260    \scale[width=\textwidth]{\getbuffer[1d]}
261\stoplinecorrection
262
263Let's look in more detail at the woman emoji. On the left we see the default
264colors, and on the right we see our own:
265
266\definefontfeature[seguiemj][default][ccmp=yes,dist=yes,colr=yes]
267\definefont[MyColoredEmojiD][seguiemj*seguiemj]
268
269\startlinecorrection
270\scale[height=2cm]
271  {\MyColoredEmojiD\resolvedemoji{woman}%
272   \MyColoredEmojiR\resolvedemoji{woman}}
273\stoplinecorrection
274
275The multi|-|color variant in \CONTEXT\ \MKIV\ ends up as follows in the page
276stream:
277
278\starttyping
279/Span << /ActualText <feffD83DDC69> >> BDC
280q
2810.000 g
282BT
283/F8 11.955168 Tf
2841 0 0 1 0 2.51596 Tm [<045B>]TJ
2850.557 0.337 0.180 rg
2861 0 0 1 0 2.51596 Tm [<045C>]TJ
2871.000 0.784 0.239 rg
2881 0 0 1 0 2.51596 Tm [<045D>]TJ
2890.000 g
2901 0 0 1 0 2.51596 Tm [<045E>]TJ
2910.969 0.537 0.290 rg
2921 0 0 1 0 2.51596 Tm [<045F>]TJ
2930.941 0.227 0.090 rg
2941 0 0 1 0 2.51596 Tm [<0460>]TJ
295ET
296Q
297EMC
298\stoptyping
299
300and the reddish one becomes:
301
302\starttyping[option=PDF]
303/Span << /ActualText <feffD83DDC69> >> BDC
304q
3050.400 0 0 rg 0.400 0 0 RG
306BT
307/F8 11.955168 Tf
3081 0 0 1 0 2.51596 Tm [<045B>]TJ
3091 g 1 G /Tr1 gs
3101 0 0 1 0 2.51596 Tm [<045C>1373<045D>1373<045E>1373<045F>1373<0460>]TJ
311ET
312Q
313EMC
314\stoptyping
315
316Each time this shape is typeset these sequences are injected. In \CONTEXT\ \LMTX\
317we get this in the page stream:
318
319\starttyping[option=PDF]
320BT
321/F2 11.955168 Tf
3221 0 0 1 0 2.515956 Tm [<C8>] TJ
323ET
324\stoptyping
325
326This time the composed shape ends up in the \TYPETHREE\ character procedure. In
327the colorful case (reformatted because it actually is a one|-|liner):
328
329\starttyping[option=PDF]
3302812 0 d0
3310.000 g              BT /V8 1 Tf [<045B>] TJ ET
3320.557 0.337 0.180 rg BT /V8 1 Tf [<045C>] TJ ET
3331.000 0.784 0.239 rg BT /V8 1 Tf [<045D>] TJ ET
3340.000 g              BT /V8 1 Tf [<045E>] TJ ET
3350.969 0.537 0.290 rg BT /V8 1 Tf [<045F>] TJ ET
3360.941 0.227 0.090 rg BT /V8 1 Tf [<0460>] TJ ET
337\stoptyping
338
339and in the reddish case (where we have a gray transparent color):
340
341\starttyping[option=PDF]
3422812 0 d0
3430.400 0 0 rg 0.400 0 0 RG
344BT /V8 1 Tf [<045B>] TJ ET
3451 g 1 G /Tr1 gs
346BT /V8 1 Tf [<045C>] TJ ET
347BT /V8 1 Tf [<045D>] TJ ET
348BT /V8 1 Tf [<045E>] TJ ET
349BT /V8 1 Tf [<045F>] TJ ET
350BT /V8 1 Tf [<0460>] TJ ET
351\stoptyping
352
353but this time we only get these verbose compositions once in the \PDF\ file. We
354could optimize the last variant by a sequence of indices and negative kerns but
355it hardly pays off. There is no need for \type {ActualText} here because we have
356an entry in the \type {ToUnicode} vector:
357
358\starttyping[option=PDF]
359<C8> <D83DDC69>
360\stoptyping
361
362To be clear, the \type {/V8} is a sort of local reference to a font which can
363have an \type {/F8} counterpart elsewhere. These \TYPETHREE\ fonts have their own
364resource references and I found it more clear to use a different prefix in that
365case. If we only use a few characters of this kind, of course the overhead of
366extra fonts has a penalty but as soon we refer to more characters we gain a lot.
367
368When we have \SVG\ fonts, the gain is a bit less. The \PDF\ resulting from the
369\METAPOST\ run can of course be large but they are included only once. In \MKIV\
370these would be (shared) so|-|called \type {XForm}s. In the page stream we then
371see a simple reference to such an \type {XForm} but again wrapped into an \type
372{ActualText}. In \LMTX\ we get just a reference to a \TYPETHREE\ character plus
373of course an extra font.
374
375The \typ {emojionecolor-svginot} font is somewhat problematic (although maybe in
376the meantime it has become obsolete). As usual with new functionality,
377specifications are not always available or complete (especially when they are
378application specs turned into standards). This is also true with for instance
379\SVG\ fonts. The current documentation on the \MICROSOFT\ website is reasonable
380and explains how to deal with the viewport but when I first implemented support
381for \SVG\ it was more trial and error. The original implementation in \CONTEXT\
382used Inkscape to generate \PDF\ files with a tight bounding box and mix that with
383information from the font (in \MKIV\ and the generic loader we still use this
384method). This results in a reasonable placement for emoji (that often sit on top
385of the baseline) but not for characters. More accurate treatment, using the
386origin and bounding box, fail for graphics with bad viewports and strange
387transform attributes. Now one can of course argue that I read the specs wrong,
388but inconsistencies are hard to deal with. Even worse is that successive versions
389of a font can demand different hacks. (I would not be surprised if some programs
390have built|-|in heuristics for some fonts that apply fixes.) Here is an example:
391
392\starttyping
393<svg transform="translate(0 -1788) scale(2.048)" viewBox="0 0 64 64" ...>
394    <path d="... all within the viewBox ..." ... />
395</svg>
396\stoptyping
397
398It is no problem to scale up the image to normal dimensions, often 1000, or 2048
399but I've also seen 512. The 2.048 suggests a 2048 unit approach, as does the 1788
400shift. Now, we could scale up all dimensions by 1000/64 and then multiply by
4012.048 and eventually shift over 1788, but why not scale the 1788 by 2.048 or
402scale 64 by 2.048? Even if we can read the standard to suit this specification
403it's just a bit too messy for my taste. In fact I tried all reasonable
404combinations and didn't (yet) get the right result. In that case it's easier to
405just discard the font. If a user complains that it (kind of) worked in the past,
406a counter|-|argument can be that other (more recent) fonts don't work otherwise.
407In the end we ended up with an option: when the \type {svg} feature value is
408\type {fixdepth} the vertical position will be fixed.
409
410\startbuffer[2a]
411\definefontfeature[whatever][default][color=yes,svg=fixdepth]
412\definefont[TestB][file:emojionecolor-svginot.ttf*whatever]
413\stopbuffer
414
415\typebuffer[2a][option=TEX] \getbuffer[2a]
416
417\startbuffer[2b]
418x{\TestB \char"1F41C \char"1F41B}x
419\stopbuffer
420
421\startlinecorrection
422    \scale[height=1cm]{\getbuffer[2b]}
423\stoplinecorrection
424
425The newer \type {emojionecolor} font doesn't need this because it has a \type
426{viewBox} of \type {0 54.4 64 64} which fixes the baseline.
427
428\startbuffer[2c]
429\definefontfeature[whatever][default][color=yes,svg=yes]
430\definefont[TestB][file:emojionecolor.otf*whatever]
431\stopbuffer
432
433\typebuffer[2c][option=TEX] \getbuffer[2c]
434
435\startlinecorrection
436    \scale[height=1cm]{\getbuffer[2b]}
437\stoplinecorrection
438
439Another example of a pitfall is running into category one glyphs made from
440several pieces that all have the same color. If that color is black, one starts
441to wonder what is wrong. In the end the \CONTEXT\ code was doing the right thing
442after all, and I would not be surprised if that glyph gets colors in an update of
443the font. For that reason it makes no sense to include them as examples here.
444After all, we can hardly complain about free fonts (and I'm also guilty of
445imposing bugs on users). By the way, for the font referred to here (\type
446{twemojimozilla}), another pitfall was that all shapes in my copy had a zero
447bounding box which means that although a width is specified, rendering in
448documents can give weird side effects. This can be corrected by the \type
449{dimensions} feature that forces the ascender and descender values to be used.
450
451\startbuffer[3a]
452\definefontfeature[colored:x][default][colr=yes]
453\definefontfeature[colored:y][default][colr=yes,dimensions={1,max,max}]
454\definefont[TestC][file:twemojimozilla.ttf*colored:x]
455\definefont[TestD][file:twemojimozilla.ttf*colored:y]
456\stopbuffer
457
458\typebuffer[3a][option=TEX] \getbuffer[3a]
459
460\startbuffer[3b]
461{\TestC\char 128028}\quad{\showglyphs\TestC\char 128028}\quad
462{\TestD\char 128028}\quad{\showglyphs\TestD\char 128028}
463\stopbuffer
464
465\startlinecorrection
466    \scale[height=2cm]{\getbuffer[3b]}
467\stoplinecorrection
468
469An example of a \PNG|-|enhanced font is the \type {applecoloremoji} font. The
470bitmaps are relatively large for the quality they provide and some look like
471scans.
472
473\startbuffer[4a]
474\definefontfeature[sbix][default][sbix=yes]
475\definefont[TestE][file:applecoloremoji.ttc*sbix at 10bp]
476\stopbuffer
477
478\typebuffer[4a][option=TEX] \getbuffer[4a]
479
480\startbuffer[4b]
481\red \TestE \char 35 \char 9203 \char 9202
482\stopbuffer
483
484\startlinecorrection
485    \scale[height=1cm]{\getbuffer[4b]}
486\stoplinecorrection
487
488As mentioned above, there are fonts that color characters other than emoji. We
489give two examples (sometimes fonts are mentioned on the \CONTEXT\ mailing list).
490
491\startbuffer[5a]
492\definefontfeature
493  [whatever]
494  [default,color:svg]
495  [script=latn,
496   language=dflt]
497
498\definefont[TestF][file:Abelone-FREE.otf*whatever          @ 13bp]
499\definefont[TestG][file:Gilbert-ColorBoldPreview5*whatever @ 13bp]
500\definefont[TestH][file:ColorTube-Regular*whatever         @ 13bp]
501\stopbuffer
502
503\typebuffer[5a][option=TEX] \getbuffer[5a]
504
505Of course one can wonder about the readability of these fonts and unless one used
506random colors (which bloats the file immensely) it might become boring, but
507typically such fonts are only meant for special purposes.
508
509\startbuffer[5b]
510    {\TestF\setupinterlinespace[0.7]\input zapf \par}
511\stopbuffer
512
513\startbuffer[5c]
514    {\TestG\setupinterlinespace     \input zapf \par}
515\stopbuffer
516
517\startbuffer[5d]
518    {\TestH\setupinterlinespace[0.7]\input zapf \par}
519\stopbuffer
520
521\start \setupalign[tolerant] \getbuffer[5b] \stop
522
523The previous font is the largest and as a consequence also puts some strain on
524the viewer, especially when zooming in. But, because viewers cache \TYPETHREE\
525shapes it's a one|-|time penalty.
526
527\start \setupalign[tolerant] \getbuffer[5c] \stop
528
529This font is rather lightweight. Contrary to what one might expect, there is no
530transparency used (but of course we do support that when needed).
531
532\start \setupalign[tolerant] \getbuffer[5d] \stop
533
534This third example is again rather lightweight. Such fonts normally have a rather
535limited repertoire although there are some accented characters included. But they
536are not really meant for novels anyway. If you look closely you will also notice
537that some characters are missing and kerning is suboptimal.
538
539I considered testing some more fonts but when trying to download some interesting
540looking ones I got a popup asking me for my email address in order to subscribe
541me to something: a definite no|-|go.
542
543%\section{\SVG\ to MetaPost}
544
545I already mentioned that we have a built|-|in converter that goes from \SVG\ to
546\METAPOST. Although this article deals with fonts, the following code
547demonstrates that we can also access such graphics in \METAFUN\ itself. The nice
548thing is that because we get pictures, they can be manipulated.
549
550\startbuffer
551\startMPcode{doublefun}
552    picture p ; p := lmt_svg [ filename = "mozilla-svg-001.svg" ] ;
553    numeric w ; w := bbwidth(p) ;
554    draw p ;
555    draw p xscaled -1 shifted (2.5*w,0);
556    draw p rotatedaround(center p,45) shifted (3.0*w,0) ;
557    draw image (
558        for i within p : if filled i :
559            draw pathpart i withcolor green ;
560        fi endfor ;
561    ) shifted (4.5*w,0);
562    draw image (
563        for i within p : if filled i :
564            fill pathpart i withcolor red withtransparency (1,.25) ;
565        fi endfor ;
566    ) shifted (6*w,0);
567\stopMPcode
568\stopbuffer
569
570\typebuffer[option=TEX]
571
572This graphic is a copy from a glyph from an emoji font, so we have plenty of such
573images to play with. The above manipulations result in:
574
575\startlinecorrection
576    \getbuffer
577\stoplinecorrection
578
579Now that we're working with \METAPOST\ we may as well see if we can also load a
580specific glyph, and indeed this is possible.
581
582\startbuffer[1]
583\startMPcode{doublefun}
584    picture lb, rb ;
585    lb := lmt_svg [ fontname = "Gilbert-ColorBoldPreview5", unicode = 123 ] ;
586    rb := lmt_svg [ fontname = "Gilbert-ColorBoldPreview5", unicode = 125 ] ;
587    numeric dx ; dx := 1.25 * bbwidth(lb) ;
588    draw lb ;
589    draw rb shifted (dx,0) ;
590    pickup pencircle scaled 2mm ;
591    for i within lb :
592        draw lmt_arrow [
593            path        = pathpart i,
594            pen         = "auto",
595            alternative = "curved",
596            penscale    = 8
597        ]
598            shifted (3dx,0)
599            withcolor "darkblue"
600            withtransparency (1,.5)
601        ;
602    endfor ;
603    for i within rb :
604        draw lmt_arrow [
605            path        = pathpart i,
606            pen         = "auto",
607            alternative = "curved",
608            penscale    = 8
609        ]
610            shifted (4dx,0)
611            withcolor "darkred"
612            withtransparency (1,.5)
613        ;
614    endfor ;
615\stopMPcode
616\stopbuffer
617
618% Ok, I should make a macro ...
619
620\startbuffer[2]
621\startMPcode{doublefun}
622    picture lb, rb ;
623    lb := lmt_svg [ fontname = "Gilbert-ColorBoldPreview5", unicode = 42 ] ;
624    rb := lmt_svg [ fontname = "Gilbert-ColorBoldPreview5", unicode = 64 ] ;
625    numeric dx ; dx := 1.25 * bbwidth(lb) ;
626    draw lb ;
627    draw rb shifted (dx,0) ;
628    pickup pencircle scaled 2mm ;
629    for i within lb :
630        draw lmt_arrow [
631            path        = pathpart i,
632            pen         = "auto",
633            alternative = "curved",
634            penscale    = 6
635        ]
636            shifted (3.5dx,0)
637            withcolor "darkgreen"
638            withtransparency (1,.5)
639        ;
640    endfor ;
641    for i within rb :
642        draw lmt_arrow [
643            path        = pathpart i,
644            pen         = "auto",
645            alternative = "curved",
646            penscale    = 6
647        ]
648            shifted (4.5dx,0)
649            withcolor "darkyellow"
650            withtransparency (1,.5)
651        ;
652    endfor ;
653\stopMPcode
654\stopbuffer
655
656\typebuffer[1][option=TEX]
657
658Here we first load two character shapes from a font. The \UNICODE\ slots (which
659here are the same as the \ASCII\ slots) might look familiar: they indicate the
660curly brace characters. We get two pictures and use the \type {within} loop to
661run over the paths within these shapes. Each shape is made from three curves. As
662a bonus a few more characters are shown.
663
664\startlinecorrection
665    \dontleavehmode
666    \scale[height=3cm]{\getbuffer[1]}%
667    \quad\quad\quad\quad
668    \scale[height=3cm]{\getbuffer[2]}
669\stoplinecorrection
670
671It is not hard to imagine that a collection of such graphics could be made into a
672font (at runtime). One only needs to find the motivation. Of course one can
673always use a font editor (or Inkscape) and tweak there, which probably makes more
674sense, but sometimes a bit of \METAPOST\ hackery is a nice distraction. Editing
675the \SVG\ code directly is not that much fun. The overall structure often doesn't
676look that bad (apart from often rather redundant grouping):
677
678\starttyping[option=XML]
679<svg xmlns="http://www.w3.org/2000/svg">
680    <path fill="#d87512" d="..."/>
681    <g fill="#bc600d">
682        <path d="..."/>
683    </g>
684    <g fill="#d87512">
685        <path d="..."/>
686        <path d="..."/>
687    </g>
688    <g fill="#bc600d">
689        <path d="..."/>
690    </g>
691    ...
692</svg>
693\stoptyping
694
695In addition to \type {path}s there can be \type {line}, \type {circle} and
696similar elements but often fonts just use the \type {path} element. This element
697has a \type {d} attribute that holds a sequence of one character commands that
698each can be followed by numbers. Here are the start characters of four such
699attributes:
700
701\starttyping
702M11.585 43.742s.387 1.248.104 3.05c0 0 2.045-.466 1.898-2.27 ...
703M53.33 39.37c0-4.484-35.622-4.484-35.622 0 0 10.16.05 ...
704M42.645 56.04c1.688 2.02 9.275.043 10.504-2.28 5.01-9.482-.006 ...
705M54.2 41.496s-.336 4.246-4.657 9.573c0 0 4.38-1.7 5.808-4.3 ...
706\stoptyping
707
708Indeed, numbers can be pasted together, also with the operators, which doesn't
709help with seeing at a glance what happens. Probably the best reference can be
710found at \typ {https://developer.mozilla.org/en-US/docs/Web/SVG} where it is
711explained that a path can have move, line, curve, arc and other operators, as
712well use absolute and relative coordinates. How that works is for another
713article.
714
715How would the \TEX\ world look like today if Don Knuth had made \METAFONT\
716support colors? Of course one can argue that it is a bitmap font generator, but
717in our case using high resolution bitmaps might even work out better. In the
718example above the first text fragment uses a font that is very inefficient: it
719overlays many circles in different colors with slight displacements. Here a
720bitmap font would not only give similar effects but probably also be more
721efficient in terms of storage as well as rendering. The \METAPOST\ successor does
722support color and with \MPLIB\ in \LUATEX\ we can keep up quite well \unknown\ as
723hopefully has been demonstrated here.
724
725
726% It's no fun messing with these things that survive only for short time before
727% being replaced by the next hyped fashion. Typical work than one needs to be paid
728% for but never is.
729
730\stopchapter
731
732\stopcomponent
733