context-2021-compactfonts.tex /size: 17 Kb    last modification: 2021-10-28 13:50
1% language=us
2
3\usemodule[present-boring,abbreviations-logos]
4
5
6\definehighlight[nb][style=bold,color=middlegray,define=no]
7
8\definecolor[maincolor][g=.3]
9
10\startdocument
11  [title={COMPACT FONTS},
12   banner={a different approach to scaling},
13   location={context\enspace {\bf 2021}\enspace meeting}]
14
15\starttitle[title=How \TEX\ uses fonts]
16
17\startitemize
18    \startitem
19        In a \TEX\ engine there is a 1-to-1 mapping from characters in the input
20        to a slot in a font.
21    \stopitem
22    \startitem
23        Combinations of characters can be mapped onto one shape: ligatures.
24    \stopitem
25    \startitem
26        Hyphenation is (also) controlled by the input encoding of a font which
27        imposes some limitations.
28    \stopitem
29    \startitem
30        In the typeset result characters (glyphs) can be (re)positioned relatively: kerns.
31    \stopitem
32    \startitem
33        This all happens in a very interwoven way (e.g. inside the par builder).
34    \stopitem
35\stopitemize
36
37\stoptitle
38
39\starttitle[title=How traditional \TEX\ sees fonts]
40
41\startitemize
42    \startitem
43        A font is just a (binary) blob of data with information where characters
44        have a width, height, depth and italic correction.
45    \stopitem
46    \startitem
47        The engine only needs the dimensions and when the same font is used with a
48        different scale a copy with scaled dimensions is used.
49    \stopitem
50    \startitem
51        There can be recipes for ligatures and (more complex) so called math extensible
52        shapes (like arrows, wide accents, fences and radicals)
53    \stopitem
54    \startitem
55        There are pairwise specification for kerning.
56    \stopitem
57    \startitem
58        A handful of font parameters is provided in order to control for instance spacing.
59    \stopitem
60    \startitem
61        Virtual fonts are just normal fonts but they have recipes for the backend to
62        construct shapes: \TEX\ uses the normal metric file, the backend also the virtual
63        specification file.
64    \stopitem
65\stopitemize
66
67\blank[2*big]
68
69An example of a definition and usage:
70
71\starttyping
72\font\cs somename [somescale]  test {\cs test} test
73\stoptyping
74
75\stoptitle
76
77\starttitle[title=\UNICODE\ engines]
78
79\startitemize
80    \startitem
81        There are no fundamental differences between a traditional engine and an
82        \UNICODE\ aware one with respect to what \TEX\ needs from fonts:
83        dimensions.
84    \stopitem
85    \startitem
86        There can be more than 256 characters in a font.
87    \stopitem
88    \startitem
89        Some mechanisms have to be present for applying font features (like ligaturing and
90        kerning).
91    \stopitem
92    \startitem
93        In \LUATEX\ hyphenation, ligaturing and kerning are clearly separate steps.
94    \stopitem
95    \startitem
96        In \LUATEX\ callbacks can do lots of things with fonts and characters.
97    \stopitem
98    \startitem
99        Math fonts are handled differently and there is more info that comes from the font.
100    \stopitem
101    \startitem
102        In \LUATEX\ features like expansion are implemented differently, i.e.\ no
103        copies of fonts are made and applied expansion travels with the glyphs.
104    \stopitem
105\stopitemize
106
107\stoptitle
108
109\starttitle[title=Overhead]
110
111\startitemize
112    \startitem
113        In all engines scales copies are used. For traditional \TEX\ a copy is cheap, but a
114        font that supports more of \UNICODE\ cna be quite large.
115    \stopitem
116    \startitem
117        Different feature sets in principle make for a different font (this can be different
118        per macro package).
119    \stopitem
120    \startitem
121        Every math scale needs three font instances: text, script and scriptscript.
122    \stopitem
123    \startitem
124        In \CONTEXT\ lots of sharing takes place and a lot of low level
125        optimizations happens (memory, performance). We always made sure (already
126        in \MKII) that the font system was not the bottleneck.
127    \stopitem
128    \startitem
129        In most cases font definitions are dynamic, and we delay initialization
130        as much as possible.
131    \stopitem
132    \startitem
133        In \MKIV\ font features can be dynamic which saves a lot of memory at the
134        cost of some extra processing overhead.
135    \stopitem
136\stopitemize
137
138\stoptitle
139
140\starttitle[title=Design sizes]
141
142\startitemize
143    \startitem
144        A macro package's font handling is complicated by design sizes. The low level
145        code can look complex too.
146    \stopitem
147    \startitem
148        There are hardly any fonts that come in design sizes (basically only Computer
149        Modern) so we need to support that.
150    \stopitem
151    \startitem
152        Design sizes make sense for math fonts where very small characters and
153        symbols are used in scripts.
154    \stopitem
155    \startitem
156        In \OPENTYPE\ fonts smaller math design sizes are part of the font (that
157        then gets loaded three times with different \type {ssty} settings).
158    \stopitem
159\stopitemize
160
161\startlinecorrection
162\dontleavehmode\scale[frame=on,height=5ex]{$\textstyle         2$}\quad
163\dontleavehmode\scale[frame=on,height=5ex]{$\scriptstyle       2$}\quad
164\dontleavehmode\scale[frame=on,height=5ex]{$\scriptscriptstyle 2$}\quad\quad
165\dontleavehmode\scale[frame=on,height=2ex]{$\textstyle         2$}\quad
166\dontleavehmode\scale[frame=on,height=2ex]{$\scriptstyle       2$}\quad
167\dontleavehmode\scale[frame=on,height=2ex]{$\scriptscriptstyle 2$}\quad\quad
168\dontleavehmode\scale[frame=on,width=4em]{\colored[r=.6,a=1,t=.5]{$\textstyle         2$}}\hskip-4em
169\dontleavehmode\scale[frame=on,width=4em]{\colored[g=.6,a=1,t=.5]{$\scriptstyle       2$}}\hskip-4em
170\dontleavehmode\scale[frame=on,width=4em]{\colored[b=.6,a=1,t=.5]{$\scriptscriptstyle 2$}}\quad\quad
171\dontleavehmode{$\textstyle         2$}\quad
172\dontleavehmode{$\scriptstyle       2$}\quad
173\dontleavehmode{$\scriptscriptstyle 2$}\quad
174\stoplinecorrection
175
176\stoptitle
177
178\starttitle[title=The system]
179
180\startitemize
181    \startitem
182        Each bodyfont size (often a few are defined) has regular, bold, italic,
183        bold italic, slanted, bold slanted, etc. There can be unscaled instances
184        (design size) or scaled ones.
185    \stopitem
186    \startitem
187        Within a bodyfont size we have size variants: smaller {\tx x} and {\tx xx},
188        larger {\tfa a}, {\tfb b}, {\tfc c} and {\tfd d}.
189    \stopitem
190    \startitem
191        In \MKII\ we inherit smallcap and oldstyle setups but in \MKIV\ one can either
192        do that dynamic or define an additional bodyfont instance.
193    \stopitem
194    \startitem
195        A document can use a mix of fonts mixed setup, so there is a namespace
196        used per family.
197    \stopitem
198    \startitem
199        In \OPENTYPE\ symbols are more naturally part of a font, as are emoji and
200        colored shapes.
201    \stopitem
202    \startitem
203        Lack of variants can result in artificially slanted of boldened fonts (more
204        advanced in \MKIV). Variable fonts are not special, but demand some work
205        when loading and embedding.
206    \stopitem
207    \startitem
208        Runtime virtual fonts are part of \MKIV\ as are fallback shapes.
209    \stopitem
210    \startitem
211        Languages and scripts can introduce an extra dimension to operate on.
212    \stopitem
213    \startitem
214        Math is greatly simplified by the fact that families are part of a font.
215    \stopitem
216    \startitem
217        Bold math fonts are provided by the boldening feature.
218    \stopitem
219\stopitemize
220
221\stoptitle
222
223\starttitle[title={Practice}]
224
225\startitemize
226    \startitem
227        Due to optimizations the actual number of loaded instances is normally
228        small but there are exceptions.
229    \stopitem
230    \startitem
231        The \LUAMETATEX\ manual has 158 instances most of which are math (six per
232        used bodyfont for math plus a regular: Lucida, Pagella, Latin Modern,
233        Dejavu, Cambria).
234    \stopitem
235    \startitem
236        The final \PDF\ file has 21 embedded fonts (subsets).
237    \stopitem
238    \startitem
239        The fact that different sizes each have an instance and that for math
240        we need three per size plus one for r2l, while the only difference
241        is scale, makes one think of other solutions.
242    \stopitem
243    \startitem
244        Using duplicates of huge \CJK\ fonts makes it even more noticeable.
245    \stopitem
246\stopitemize
247
248But there is a way out!
249
250\stoptitle
251
252\starttitle[title=Glyph scaling]
253
254We can scale glyphs in three ways:
255
256\startbuffer
257\definedfont[lmroman10-regular*default]%
258test {\glyphxscale 2500 test} test
259test {\glyphyscale 2500 test} test
260test {\glyphscale  2500 test} test
261\stopbuffer
262
263\typebuffer {\getbuffer}
264
265We do need to honor grouping:
266
267\startbuffer
268\definedfont[lmroman10-regular*default]%
269e{\glyphxscale 2500 ff}icient
270ef{\glyphxscale 2500 f}icient
271ef{\glyphxscale 2500 fi}cient
272e{\glyphxscale 2500 ffi}cient
273\stopbuffer
274
275\typebuffer {\getbuffer}
276
277These scales can also be part of a font definition so we can do with less
278instances.
279
280\stoptitle
281
282\starttitle[title=Implications]
283
284\startitemize
285    \startitem
286        The text processing part of the engine has to scale on the fly (e.g.\
287        when dimensions are needed in paragraph building and (box) packing.
288    \stopitem
289    \startitem
290        Font processing (features) already distinguishes per instance but now also
291        has to differentiate by (upto three) scales (we use the same font id
292        for scaled instances).
293    \stopitem
294    \startitem
295        The math machinery has to check for smaller sizes and also scale
296        dimensions on the fly.
297    \stopitem
298    \startitem
299        For math that means two times scaling: the main scale (like glyph scale) plus
300        the relative scaling of script and scriptscript.
301    \stopitem
302    \startitem
303        When they are used font dimensions and math parameters are to be scaled as are
304        rules in some math extensibles.
305    \stopitem
306    \startitem
307        This all has to be done efficiently so that there is no significant drop in
308        performance.
309    \stopitem
310    \startitem
311        But quite a bit less memory is used and loading time has become less too.
312    \stopitem
313\stopitemize
314
315Some day this will become default (which means a sentimental process of dropping
316ancient code):
317
318\starttyping
319\enableexperiments[fonts.compact]
320\stoptyping
321
322\stoptitle
323
324\starttitle[title=Details]
325
326The tricks shown on this page and following pages have been in place and tested
327for a while now. Because \TEX\ uses integers a scale value of 1000 means 1.000,
328as in other mechanisms:
329
330\startbuffer
331\definedfont[lmroman10-regular*default]%
332test {\glyphscale 2500 test} test
333\stopbuffer
334
335\typebuffer {\getbuffer}
336
337% \glyphtextscale
338% \glyphscriptscale
339% \glyphscriptscriptscale
340
341\page
342
343The font definition mechanism supports horizontal and vertical scaling:
344
345\startbuffer
346\definefont[FooA][Serif*default @ 12pt 1800 500]
347\definefont[FooB][Serif*default @ 12pt 0.85 0.4]
348\definefont[FooC][Serif*default @ 12pt]
349
350There is also a new command:
351
352\definetweakedfont[runwider] [xscale=1.5]
353\definetweakedfont[runtaller][yscale=2.5,xscale=.8,yoffset=-.2ex]
354
355{\FooA test test \runwider test test \runtaller test test}\par
356{\FooB test test \runwider test test \runtaller test test}\par
357{\FooC test test \runwider test test \runtaller test test}\par
358\stopbuffer
359
360\typebuffer
361
362\getbuffer
363
364\page
365
366Tweaking also works in math:
367
368\startbuffer
369\definetweakedfont[squeezed][xscale=0.9]
370\definetweakedfont[squoozed][xscale=0.7]
371
372\startlines
373$a = b^2 + \sqrt{c}$
374{\squeezed $a = b^2 + \sqrt{c}$}
375{\squoozed $a = b^2 + \sqrt{c}$}
376{$\squoozed a = b^2 + \sqrt{c}$}
377{$\scriptstyle a = b^2 + \sqrt{c}$}
378\stoplines
379\stopbuffer
380
381\typebuffer
382
383\getbuffer
384
385\page
386
387\startbuffer
388\startcombination[3*1]
389    {\bTABLE
390        \bTR \bTD foo \eTD \bTD[style=\squeezed] $x = 1$ \eTD \eTR
391        \bTR \bTD oof \eTD \bTD[style=\squeezed] $x = 2$ \eTD \eTR
392     \eTABLE} {local}
393    {\bTABLE[style=\squeezed]
394        \bTR \bTD $x = 1$ \eTD \bTD  $x = 3$ \eTD \eTR
395        \bTR \bTD $x = 2$ \eTD \bTD  $x = 4$ \eTD \eTR
396     \eTABLE} {global}
397    {\bTABLE[style=\squeezed\squeezed\squeezed\squeezed]
398        \bTR \bTD $x = 1$ \eTD \bTD  $x = 3$ \eTD \eTR
399        \bTR \bTD $x = 2$ \eTD \bTD  $x = 4$ \eTD \eTR
400     \eTABLE} {multiple}
401\stopcombination
402\stopbuffer
403
404\typebuffer
405
406\startlinecorrection
407\getbuffer
408\stoplinecorrection
409
410\page
411
412Tweaking can be combined with styles:
413
414\startbuffer
415\definetweakedfont[MyLargerFontA][scale=2000,style=bold]
416test {\MyLargerFontA test} test
417\stopbuffer
418
419\typebuffer
420
421\getbuffer
422
423\page
424
425We can use negative scale values:
426
427\startbuffer
428\bTABLE[align=middle]
429  \bTR
430    \bTD a{\glyphxscale  1000 \glyphyscale  1000 bc}d \eTD
431    \bTD a{\glyphxscale  1000 \glyphyscale -1000 bc}d \eTD
432    \bTD a{\glyphxscale -1000 \glyphyscale -1000 bc}d \eTD
433    \bTD a{\glyphxscale -1000 \glyphyscale  1000 bc}d \eTD
434  \eTR
435  \bTR
436    \bTD \tttf +1000 +1000 \eTD
437    \bTD \tttf +1000 -1000 \eTD
438    \bTD \tttf -1000 -1000 \eTD
439    \bTD \tttf -1000 +1000 \eTD
440  \eTR
441\eTABLE
442\stopbuffer
443
444\typebuffer
445
446\startlinecorrection
447\getbuffer
448\stoplinecorrection
449
450\page
451
452There are more glyph properties:
453
454\startbuffer
455\ruledhbox{
456    \ruledhbox{\glyph yoffset 1ex options 0 123} % left curly brace
457    \ruledhbox{\glyph xoffset .5em yoffset 1ex options "C0 123}
458    \ruledhbox{oeps{\glyphyoffset 1ex \glyphxscale 800
459                    \glyphyscale\glyphxscale oeps}oeps}
460}
461\stopbuffer
462
463\typebuffer \scale[width=\textwidth]{\getbuffer}
464
465\page
466
467Glyph scales are internal counter values, like any other:
468
469\startbuffer
470\samplefile{jojomayer}
471{\glyphyoffset .8ex
472 \glyphxscale 700 \glyphyscale\glyphxscale
473 \samplefile{jojomayer}}
474{\glyphyscale\numexpr3*\glyphxscale/2\relax
475 \samplefile{jojomayer}}
476{\glyphyoffset -.2ex
477 \glyphxscale 500 \glyphyscale\glyphxscale
478 \samplefile{jojomayer}}
479\samplefile{jojomayer}
480\stopbuffer
481
482\typebuffer
483
484\getbuffer
485
486\page
487
488There is a helper for real (float) scales:
489
490\startbuffer
4911200 : \the\numericscale1200
4921.20 : \the\numericscale1.200
493\stopbuffer
494
495\typebuffer
496
497These lines produce the same integer:
498
499\startlines\tttf
500\getbuffer
501\stoplines
502
503\page
504
505You can do this but it's not always predictable (depends on outer scales too):
506
507\startbuffer[definition]
508\def\UnKernedTeX
509  {T%
510   {\glyph xoffset -.2ex yoffset -.4ex `E}%
511   {\glyph xoffset -.4ex options "60 `X}}
512\stopbuffer
513
514\startbuffer[example]
515We use \UnKernedTeX\ and {\bf \UnKernedTeX} and {\bs \UnKernedTeX}:
516the slanted version could use some more left shifting of the E.
517\stopbuffer
518
519\typebuffer[definition,example]
520
521\startnarrower
522    \getbuffer[definition,example]
523\stopnarrower
524
525Marks and cursive features can interfere, so this is an alternative:
526
527\startbuffer[definition]
528\def\UnKernedTeX
529  {T\glyph left .2ex raise -.4ex `E\glyph left .2ex `X\relax}
530\stopbuffer
531
532\typebuffer[definition]
533
534\startnarrower
535    \getbuffer[definition,example]
536\stopnarrower
537
538\page
539
540Yet another glyph option:
541
542\starttyping
543\multiply\glyphscale by 2 <{\darkgray \glyph                      `M}>
544\multiply\glyphscale by 2 <{\darkgray \glyph raise 3pt            `M}>
545\multiply\glyphscale by 2 <{\darkgray \glyph raise -3pt           `M}>
546\multiply\glyphscale by 2 <{\darkgray \glyph left  3pt            `M}>
547\multiply\glyphscale by 2 <{\darkgray \glyph           right  2pt `M}>
548\multiply\glyphscale by 2 <{\darkgray \glyph left  3pt right  2pt `M}>
549\multiply\glyphscale by 2 <{\darkgray \glyph left -3pt            `M}>
550\multiply\glyphscale by 2 <{\darkgray \glyph           right -2pt `M}>
551\multiply\glyphscale by 2 <{\darkgray \glyph left -3pt right -2pt `M}>
552\stoptyping
553
554\startlinecorrection
555\bTABLE[align=middle,width=.33\textwidth]
556    \bTR
557        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph                      `M}>\eTD
558        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph raise 3pt            `M}>\eTD
559        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph raise -3pt           `M}>\eTD
560    \eTR
561    \bTR[frame=off]
562        \bTD \tttf            \eTD
563        \bTD \tttf raise  3pt \eTD
564        \bTD \tttf raise -3pt \eTD
565    \eTR
566    \bTR
567        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph left  3pt            `M}>\eTD
568        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph           right  2pt `M}>\eTD
569        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph left  3pt right  2pt `M}>\eTD
570    \eTR
571    \bTR[frame=off]
572        \bTD \tttf left  3pt           \eTD
573        \bTD \tttf           right  2pt\eTD
574        \bTD \tttf left  3pt right  2pt\eTD
575    \eTR
576    \bTR
577        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph left -3pt            `M}>\eTD
578        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph           right -2pt `M}>\eTD
579        \bTD \showglyphs \multiply\glyphscale by 2 <{\darkgray \glyph left -3pt right -2pt `M}>\eTD
580    \eTR
581    \bTR[frame=off]
582        \bTD \tttf left -3pt            \eTD
583        \bTD \tttf           right -2pt \eTD
584        \bTD \tttf left -3pt right -2pt \eTD
585    \eTR
586\eTABLE
587\stoplinecorrection
588
589\page
590
591A larger example:
592
593\startbuffer
594\glyphscale 4000
595\vl\glyph                        `M\vl\quad
596\vl\glyph raise  .2em            `M\vl\quad
597\vl\glyph left   .3em            `M\vl\quad
598\vl\glyph             right  .2em`M\vl\quad
599\vl\glyph left  -.2em right -.2em`M\vl\quad
600\vl\glyph raise -.2em right  .4em`M\vl
601\stopbuffer
602
603\typebuffer
604
605{\getbuffer}
606
607\stoptitle
608
609\stopdocument
610