summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/onandon/onandon-variable.tex
blob: c73196cef62f5de5f2d76f6f3a5bbe19ddf1dbe6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
% language=uk

% todo: callback: stream, llx, lly, urx, ury, wd, lsb
% add glyphs runtime
% create whole cff so that we can go from mp

\startcomponent onandon-variable

\environment onandon-environment

\startchapter[title=Variable fonts]

\startsubject[title=Introduction]

History shows the tendency to recycle ideas. Often quite some effort is made by
historians to figure out what really happened, not just long ago, when nothing
was written down and we have to do with stories or pictures at most, but also in
recent times. Descriptions can be conflicting, puzzling, incomplete, partially
lost, biased, \unknown

Just as language was invented (or evolved) several times, so were scripts. The
same might be true for rendering scripts on a medium. Semaphores came and went
within decades and how many people know now that they existed and that encryption
was involved? Are the old printing presses truly the old ones, or are older
examples simply gone? One of the nice aspects of the internet is that one can now
more easily discover similar solutions for the same problem, but with a different
(and independent) origin.

So, how about this \quotation {new big thing} in font technology: variable fonts.
In this case, history shows that it's not that new. For most \TEX\ users the
names \METAFONT\ and \METAPOST\ will ring bells. They have a very well documented
history so there is not much left to speculation. There are articles, books,
pictures, examples, sources, and more around for decades. So, the ability to
change the appearance of a glyph in a font depending on some parameters is not
new. What probably {\em is} new is that creating variable fonts is done in the
natural environment where fonts are designed: an interactive program. The
\METAFONT\ toolkit demands quite some insight in programming shapes in such a way
that one can change look and feel depending on parameters. There are not that
many meta fonts made and one reason is that making them requires a certain mind-
and skill set. On the other hand, faster computers, interactive programs,
evolving web technologies, where rea|l|-time rendering and therefore more or less
real-time tweaking of fonts is a realistic option, all play a role in acceptance.

But do interactive font design programs make this easier? You still need to be
able to translate ideas into usable beautiful fonts. Taking the common shapes of
glyphs, defining extremes and letting a program calculate some interpolations
will not always bring good results. It's like morphing a picture of your baby's
face into yours of old age (or that of your grandparent): not all intermediate
results will look great. It's good to notice that variable fonts are a revival of
existing techniques and ideas used in, for instance, multiple master fonts. The
details might matter even more as they can now be exaggerated when some
transformation is applied.

There is currently (March 2017) not much information about these fonts so what I
say next may be partially wrong or at least different from what is intended. The
perspective will be one from a \TEX\ user and coder. Whatever you think of them,
these fonts will be out there and for sure there will be nice examples
circulating soon. And so, when I ran into a few experimental fonts, with
\POSTSCRIPT\ and \TRUETYPE\ outlines, I decided to have a look at what is inside.
After all, because it's visual, it's also fun to play with. Let's stress that at
the moment of this writing I only have a few simple fonts available, fonts that
are designed for testing and not usage. Some recommended tables were missing and
no complex \OPENTYPE\ features are used in these fonts.

\stopsubject

\startsubject[title=The specification]

I'm not that good at reading specifications, first of all because I quickly fall
asleep with such documents, but most of all because I prefer reading other stuff
(I do have lots of books waiting to be read). I'm also someone who has to play
with something in order to understand it: trial and error is my modus operandi.
Eventually it's my intended usage that drives the interface and that is when
everything comes together.

Exploring this technology comes down to: locate a font, get the \OPENTYPE\ 1.8
specification from the \MICROSOFT\ website, and try to figure out what is in the
font. When I had a rough idea the next step was to get to the shapes and see if I
could manipulate them. Of course it helped that in \CONTEXT\ we already can load
fonts and play with shapes (using \METAPOST). I didn't have to install and learn
other programs. Once I could render them, in this case by creating a virtual font
with inline \PDF\ literals, a next step was to apply variation. Then came the
first experiments with a possible user interface. Seeing more variation then
drove the exploration of additional properties needed for typesetting, like
features.

The main extension to the data packaged in a font file concerns the (to be
discussed) axis along which variable fonts operate and deltas to be applied to
coordinates. The \type {gdef} table has been extended and contains information
that is used in \type {gpos} features. There are new \type {hvar}, \type {vvar}
and \type {mvar} tables that influence the horizontal, vertical and general font
dimensions. The \type {gvar} table is used for \TRUETYPE\ variants, while the
\type {cff2} table replaces the \type {cff} table for \OPENTYPE\ \POSTSCRIPT\
outlines. The \type {avar} and \type {stat} tables contain some
meta|-|information about the axes of variations.

It must be said that because this is new technology the information in the
standard is not always easy to understand. The fact that we have two rendering
techniques, \POSTSCRIPT\ \type {cff} and \TRUETYPE\ \type {ttf}, also means that
we have different information and perspectives. But this situation is not much
different from \OPENTYPE\ standards a few years ago: it takes time but in the end
I will get there. And, after all, users also complain about the lack of
documentation for \CONTEXT, so who am I to complain? In fact, it will be those
\CONTEXT\ users who will provide feedback and make the implementation better in
the~end.

\stopsubject

\startsubject[title=Loading]

Before we discuss some details, it will be useful to summarize what the font
loader does when a user requests a font at a certain size and with specific
features enabled. When a font is used the first time, its binary format is
converted into a form that makes it suitable for use within \CONTEXT\ and
therefore \LUATEX. This conversion involves collecting properties of the font as
a whole (official names, general dimensions like x-height and em-width, etc.), of
glyphs (dimensions, \UNICODE\ properties, optional math properties), and all
kinds of information that relates to (contextual) replacements of glyphs (small
caps, oldstyle, scripts like Arabic) and positioning (kerning, anchoring marks,
etc.). In the \CONTEXT\ font loader this conversion is done in \LUA.

The result is stored in a condensed format in a cache and the next time the font
is needed it loads in an instant. In the cached version the dimensions are
untouched, so a font at different sizes has just one copy in the cache. Often a
font is needed at several sizes and for each size we create a copy with scaled
glyph dimensions. The feature-related dimensions (kerning, anchoring, etc.)\ are
shared and scaled when needed. This happens when sequences of characters in the
node list get converted into sequences of glyphs. We could do the same with glyph
dimensions but one reason for having a scaled copy is that this copy can also
contain virtual glyphs and these have to be scaled beforehand. In practice there
are several layers of caching in order to keep the memory footprint within
reasonable bounds. \footnote {In retrospect one can wonder if that makes sense;
just look at how much memory a browser uses when it has been open for some time.
In the beginning of \LUATEX\ users wondered about caching fonts, but again, just
look at what amounts browsers cache: it gets pretty close to the average amount
of writes that a \SSD\ can handle per day within its guarantee.}

When the font is actually used, interaction between characters is resolved using
the feature|-|related information. When for instance two characters need to be
kerned, a lookup results in the injection of a kern, scaled from general
dimensions to the current size of the font.

When the outlines of glyphs are needed in \METAFUN\ the font is also converted
from its binary form to something in \LUA, but this time we filter the shapes.
For a \type {cff} this comes down to interpreting the \type {charstrings} and
reducing the complexity to \type {moveto}, \type {lineto} and \type {curveto}
operators. In the process subroutines are inlined. The result is something that
\METAPOST\ is happy with but that also can be turned into a piece of a \PDF.

We now come to what a variable font actually is: a basic design which is
transformed along one or more axes. A simple example is wider shapes:

\startlinecorrection
\startMPcode
for i=1 upto 4 :
    fill fullsquare xyscaled (i*.5cm,1cm) shifted (i*2.5*cm,0) withcolor "darkgray";
    fill fullcircle xyscaled (2.5mm,2.5mm) shifted (i*2.5*cm,0) withcolor "lightgray" ;
endfor ;
\stopMPcode
\stoplinecorrection

We can also go taller and retain the width:

\startlinecorrection
\startMPcode
for i=1 upto 4 :
    fill fullsquare xyscaled (1cm,i*.5cm) shifted (i*2.5*cm,0) withcolor "darkgray";
    fill fullcircle xyscaled (2.5mm,2.5mm) shifted (i*2.5*cm,0) withcolor "lightgray" ;
endfor ;
\stopMPcode
\stoplinecorrection

Here we have a linear scaling but glyphs are not normally done that way. There
are font collections out there with lots of intermediate variants (say from light
to heavy) and it's more profitable to sell each variant independently. However,
there is often some logic behind it, probably supported by programs that
designers use, so why not build that logic into the font and have one file that
represents many intermediate forms. In fact, once we have multiple axes, even
when the designer has clear ideas of the intended usage, nothing will prevent
users from tinkering with the axis properties in ways that will fulfil their
demands but hurt the designers eyes. We will not discuss that dilemma here.

When a variable font follows the route described above, we face a problem. When
you load a \TRUETYPE\ font it will just work. The glyphs are packaged in the same
format as static fonts. However, a variable font has axes and on each axis a
value can be set. Each axis has a minimum, maximum and default. It can be that
the default instance also assumes some transformations are applied. The standard
recommends adding tables to describe these things but the fonts that I played
with each lacked such tables. So that leaves some guesswork. But still, just
loading a \TRUETYPE\ font gives some sort of outcome, although the dimensions
(widths) might be weird due to lack of a (default) axis being applied.

An \OPENTYPE\ font with \POSTSCRIPT\ outlines is different: the internal \type
{cff} format has been upgraded to \type {cff2} which on the one hand is less
complicated but on the other hand has a few new operators \emdash\ which results
in programs that have not been adapted complaining or simply quitting on them.

One could argue that a font is just a resource and that one only has to pass it
along but that's not what works well in practice. Take \LUATEX. We can of course
load the font and apply axis vales so that we can process the document as we
normally do. But at some point we have to create a \PDF. We can simply embed the
\TRUETYPE\ files but no axis values are applied. This is because, even if we add
the relevant information, there is no way in current \PDF\ formats to deal with
it. For that, we should be able to pass all relevant axis|-|related information
as well as specify what values to use along these axes. And for \TRUETYPE\ fonts
this information is not part of the shape description so then we in fact need to
filter and pass more. An \OPENTYPE\ \POSTSCRIPT\ font is much cleaner because
there we have the information needed to transform the shape mostly in the glyph
description. There we only need to carry some extra information on how to apply
these so|-|called blend values. The region|/|axis model used there only demands
passing a relatively simple table (stripped down to what we need). But, as said
above, \type {cff2} is not backward-compatible so a viewer will (currently)
simply not show anything.

Recalling how we load fonts, how does that translate with variable changes? If we
have two characters with glyphs that get transformed and that have a kern between
them, the kern may or may not transform. So, when we choose values on an axis,
then not only glyph properties change but also relations. We no longer can share
positional information and scale afterwards because each instance can have
different values to start with. We could carry all that information around and
apply it at runtime but because we're typesetting documents with a static design
it's more convenient to just apply it once and create an instance. We can use the
same caching as mentioned before but each chosen instance (provided by the font
or made up by user specifications) is kept in the cache. As a consequence, using
a variable font has no overhead, apart from initial caching.

So, having dealt with that, how do we proceed? Processing a font is not different
from what we already had. However, I would not be surprised if users are not
always satisfied with, for instance, kerning, because in such fonts a lot of care
has to be given to this by the designer. Of course I can imagine that programs
used to create fonts deal with this, but even then, there is a visual aspect to
it too. The good news is that in \CONTEXT\ we can manipulate features so in
theory one can create a so|-|called font goodie file for a specific instance.

\stopsubject

\startsubject[title=Shapes]

For \OPENTYPE\ \POSTSCRIPT\ shapes we always have to do a dummy rendering in
order to get the right bounding box information. For \TRUETYPE\ this information
is already present but not when we use a variable instance, so I had to do a bit
of coding for that. Here we face a problem. For \TEX\ we need the width, height
and depth of a glyph. Consider the following case:

\startlinecorrection
\startMPcode
path p ; p := fullcircle xysized (3cm,2cm) ;
fill p
    withcolor "lightgray" ;
draw boundingbox currentpicture
    withpen pencircle scaled .5mm
    withcolor "darkgray" ;
setbounds currentpicture to p ;
draw boundingbox currentpicture
    leftenlarged 2mm rightenlarged 5mm ;
\stopMPcode
\stoplinecorrection

The shape has a bounding box that fits the shape. However, its left corner is not
at the origin. So, when we calculate a tight bounding box, we cannot use it for
actually positioning the glyph. We do use it (for horizontal scripts) to get the
height and depth but for the width we depend on an explicit value. In \OPENTYPE\
\POSTSCRIPT\ we have the width available and how the shape is positioned relative
to the origin doesn't much matter. In a \TRUETYPE\ shape a bounding box is part
of the specification, as is the width, but for a variable font one has to use
so-called phantom points to recalculate the width and the test fonts I had were
not suitable for investigating this.

At any rate, once I could generate documents with typeset text using variable
fonts it became time to start thinking about a user interface. A variable font
can have predefined instances but of course a user also wants to mess with axis
values. Take one of the test fonts: Adobe Variable Font Prototype. It has several
instances:

\unexpanded\def\SampleFont#1#2#3%
 {\NC #2
  \NC \definedfont[name:#1#3*default]It looks like this!
      \normalexpanded{\noexpand\NC\currentfontinstancespec}
  \NC \NR}

\starttabulate[|||T|]
\SampleFont {adobevariablefontprototype} {extralight}            {extralight}
\SampleFont {adobevariablefontprototype} {light}                 {light}
\SampleFont {adobevariablefontprototype} {regular}               {regular}
\SampleFont {adobevariablefontprototype} {semibold}              {semibold}
\SampleFont {adobevariablefontprototype} {bold}                  {bold}
\SampleFont {adobevariablefontprototype} {black high contrast}   {blackhighcontrast}
\SampleFont {adobevariablefontprototype} {black medium contrast} {blackmediumcontrast}
\SampleFont {adobevariablefontprototype} {black}                 {black}
\stoptabulate

Such an instance is accessed with:

\starttyping
\definefont
  [MyLightFont]
  [name:adobevariablefontprototypelight*default]
\stoptyping

The Avenir Next variable demo font (currently) provides:

\starttabulate[|||T|]
\SampleFont {avenirnextvariable} {regular}           {regular}
\SampleFont {avenirnextvariable} {medium}            {medium}
\SampleFont {avenirnextvariable} {bold}              {bold}
\SampleFont {avenirnextvariable} {heavy}             {heavy}
\SampleFont {avenirnextvariable} {condensed}         {condensed}
\SampleFont {avenirnextvariable} {medium condensed}  {mediumcondensed}
\SampleFont {avenirnextvariable} {bold condensed}    {boldcondensed}
\SampleFont {avenirnextvariable} {heavy condensed}   {heavycondensed}
\stoptabulate

Before we continue I will show a few examples of variable shapes. Here we use some
\METAFUN\ magic. Just take these definitions for granted.

\startbuffer[a]
\startMPcode
  draw outlinetext.b
    ("\definedfont[name:adobevariablefontprototypeextralight]foo@bar")
    (withcolor "gray")
    (withcolor red withpen pencircle scaled 1/10)
    xsized .45TextWidth ;
\stopMPcode
\stopbuffer

\startbuffer[b]
\startMPcode
  draw outlinetext.b
    ("\definedfont[name:adobevariablefontprototypelight]foo@bar")
    (withcolor "gray")
    (withcolor red withpen pencircle scaled 1/10)
    xsized .45TextWidth ;
\stopMPcode
\stopbuffer

\startbuffer[c]
\startMPcode
  draw outlinetext.b
    ("\definedfont[name:adobevariablefontprototypebold]foo@bar")
    (withcolor "gray")
    (withcolor red withpen pencircle scaled 1/10)
    xsized .45TextWidth ;
\stopMPcode
\stopbuffer

\startbuffer[d]
\startMPcode
  draw outlinetext.b
    ("\definefontfeature[whatever][axis={weight:350}]%
      \definedfont[name:adobevariablefontprototype*whatever]foo@bar")
    (withcolor "gray")
    (withcolor red withpen pencircle scaled 1/10)
    xsized .45TextWidth ;
\stopMPcode
\stopbuffer

\typebuffer[a,b,c,d]

The results are shown in \in {figure} [fig:whatever:1]. What we see here is that
as long as we fill the shape everything will look as expected but using an
outline only won't. The crucial (control) points are moved to different locations
and as a result they can end up inside the shape. Giving up outlines is the price
we evidently need to pay. Of course this is not unique for variable fonts
although in practice static fonts behave better. To some extent we're back to
where we were with \METAFONT\ and (for instance) Computer Modern: because these
originate in bitmaps (and probably use similar design logic) we also can have
overlap and bits and pieces pasted together and no one will notice that. The
first outline variants of Computer Modern also had such artifacts while in the
static Latin Modern successors, outlines were cleaned up.

\startplacefigure[title=Four variants,reference=fig:whatever:1]
    \startcombination[2*2]
        {\getbuffer[a]} {a}
        {\getbuffer[b]} {b}
        {\getbuffer[c]} {d}
        {\getbuffer[d]} {c}
    \stopcombination
\stopplacefigure

The fact that we need to preprocess an instance but only know how to do that when
we have gotten the information about axis values from the font means that the
font handler has to be adapted to keep caching correct. Another definition is:

\starttyping
\definefontfeature
  [lightdefault]
  [default]
  [axis={weight:230,contrast:50}]

\definefont
  [MyLightFont]
  [name:adobevariablefontprototype*lightdefault]
\stoptyping

Here the complication is that where normally features are dealt with after
loading, the axis feature is part of the preparation (and caching). If you want
the virtual font solution you can do this:

\starttyping
\definefontfeature
  [inlinelightdefault]
  [default]
  [axis={weight:230,contrast:50},
   variableshapes=yes]

\definefont
  [MyLightFont]
  [name:adobevariablefontprototype*inlinelightdefault]
\stoptyping

When playing with these fonts it was hard to see if loading was done right. For
instance not all values make sense. It is beyond the scope of this article, but
axes like weight, width, contrast and italic values get applied differently to
so|-|called regions (subspaces). So say that we have an $x$ coordinate with value
$50$. This value can be adapted in, for instance, four subspaces (regions), so we
actually get:

\startformula
    x^\prime = x
             + s_1 \times x_1
             + s_2 \times x_2
             + s_3 \times x_3
             + s_4 \times x_4
\stopformula

The (here) four scale factors $s_n$ are determined by the axis value. Each axis
has some rules about how to map the values $230$ for weight and $50$ for contrast
to such a factor. And each region has its own translation from axis values to
these factors. The deltas $x_1,\dots,x_4$ are provided by the font. For a
\POSTSCRIPT|-|based font we find sequences like:

\starttyping
1 <setvstore>
120 [10 -30 40 -60] 1 <blend> ... <operator>
100 120 [10 -30 40 -60] [30 -10 -30 20] 2 <blend> .. <operator>
\stoptyping

A store refers to a region specification. From there the factors are calculated
using the chosen values on the axis. The deltas are part of the glyphs
specification. Officially there can be multiple region specifications, but how
likely it is that they will be used in real fonts is an open question.

For \TRUETYPE\ fonts the deltas are not in the glyph specification but in a
dedicated \type {gvar} table.

\starttyping
apply x deltas [10 -30 40 -60] to x 120
apply y deltas [30 -10 -30 20] to y 100
\stoptyping

Here the deltas come from tables outside the glyph specification and their
application is triggered by a combination of axis values and regions.

The following two examples use Avenir Next Variable and demonstrate that kerning
is adapted to the variant.

\startbuffer
\definefontfeature
  [default:shaped]
  [default]
  [axis={width:10}]

\definefont
  [SomeFont]
  [file:avenirnextvariable*default:shaped]
\stopbuffer

\typebuffer \getbuffer

\start \showglyphs \showfontkerns \SomeFont \input zapf \wordright{Hermann Zapf}\par \stop

\startbuffer
\definefontfeature
  [default:shaped]
  [default]
  [axis={width:100}]

\definefont
  [SomeFont]
  [file:avenirnextvariable*default:shaped]
\stopbuffer

\typebuffer \getbuffer

\start \showglyphs \showfontkerns \SomeFont \input zapf \wordright{Hermann Zapf}\par \stop

\stopsubject

\startsubject[title=Embedding]

Once we're done typesetting and a \PDF\ file has to be created there are three
possible routes:

\startitemize
    \startitem
        We can embed the shapes as \PDF\ images (inline literal) using virtual
        font technology. We cannot use so|-|called xforms here because we want to
        support color selectively in text.
    \stopitem
    \startitem
        We can wait till the \PDF\ format supports such fonts, which might happen
        but even then we might be stuck for years with viewers getting there. Also
        documents need to get printed, and when printer support might
        arrive is another unknown.
    \stopitem
    \startitem
        We can embed a regular font with shapes that match the chosen values on the
        axis. This solution is way more efficient than the first.
    \stopitem
\stopitemize

Once I could interpret the right information in the font, the first route was the
way to go. A side effect of having a converter for both outline types meant that
it was trivial to create a virtual font at runtime. This option will stay in
\CONTEXT\ as pseudo|-|feature \type {variableshapes}.

When trying to support variable fonts I tried to limit the impact on the backend
code. Also, processing features and such was not touched. The inclusion of the
right shapes is done via a callback that requests the blob to be injected in the
\type {cff} or \type {glyf} table. When implementing this I actually found out
that the \LUATEX\ backend also does some juggling of charstrings, to serve the
purpose of inlining subroutines. In retrospect I could have learned a few tricks
faster by looking at that code but I never realized that it was there. Looking at
the code again, it strikes me that the whole inclusion could be done with \LUA\
code and some day I will give that a try.

\stopsubject

\startsubject[title=Conclusion]

When I first heard about variable fonts I was confident that when they showed up
they could be supported. Of course a specimen was needed to prove this. A first
implementation demonstrates that indeed it's no big deal to let \CONTEXT\ with
\LUATEX\ handle such fonts. Of course we need to fill in some gaps which can be
done once we have complete fonts. And then of course users will demand more
control. In the meantime the helper script that deals with identifying fonts by
name has been extended and the relevant code has been added to the distribution.
At some point the \CONTEXT\ Garden will provide the \LUATEX\ binary that has the
callback.

I end with a warning. On the one hand this technology looks promising but on the
other hand one can easily get lost. Probably most such fonts operate over a
well|-|defined domain of values but even then one should be aware of complex
interactions with features like positioning or replacements. Not all combinations
can be tested. It's probably best to stick to fonts that have all the relevant
tables and don't depend on properties of a specific rendering technology.

Although support is now present in the core of \CONTEXT\ the official release
will happen at the \CONTEXT\ meeting in 2017. By then I hope to have tested more
fonts. Maybe the interface has also been extended by then because after all,
\TEX\ is about control.

\stopsubject

\stopchapter

\stopcomponent