summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/fonts/fonts/fonts-modes.tex
blob: 95cb957328f8ff96e897e46b0ed84df6d1f0f952 (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
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
% language=uk

\definefontfeature
  [otftracker-husayni]
  [analyze=yes,mode=node,language=dflt,script=arab,
   ccmp=yes,init=yes,medi=yes,fina=yes,
   rlig=yes,tlig=yes,anum=yes,calt=yes,salt=yes,
   ss01=yes,ss03=yes,ss10=yes,ss12=yes,ss15=yes,
   ss16=yes,ss19=yes,ss24=yes,ss25=yes,ss26=yes,
   ss27=yes,ss31=yes,ss34=yes,ss35=yes,ss36=yes,
   ss37=yes,ss38=yes,ss41=yes,ss42=yes,ss43=yes,
   ss60=yes,js16=yes,
   kern=yes,curs=yes,mark=yes,mkmk=yes]

\startbuffer[nodechart:1a]

    \switchtobodyfont[6pt]

    \definecolor[nodechart:glyph][maincolor]

    \hboxtoFLOWchart[dummy]{\definedfont[Normal*none]\language0 test BLAtest}

    \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]

\stopbuffer

\startbuffer[nodechart:1b]

    \switchtobodyfont[6pt]

    \definecolor[nodechart:glyph][maincolor]

    \hboxtoFLOWchart[dummy]{test BLAtest}

    \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]

\stopbuffer

\startbuffer[nodechart:2a]

    \switchtobodyfont[6pt]

    \definecolor[nodechart:glyph][maincolor]

    \hboxtoFLOWchart[dummy]{affiliation}

    \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]

\stopbuffer

\startbuffer[nodechart:2b]

    \switchtobodyfont[6pt]

    \definecolor[nodechart:glyph][maincolor]

    \hboxtoFLOWchart[dummy]{abc\discretionary{d}{e}{f}ghi}

    \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]

\stopbuffer

\startbuffer[nodechart:2c]

    \switchtobodyfont[6pt]

    \definecolor[nodechart:glyph][maincolor]

    \hboxtoFLOWchart[dummy]{\nl effe fijn fietsen}

    \FLOWchart[dummy][width=12em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]

\stopbuffer

\startbuffer[nodechart:3a]

    \switchtobodyfont[6pt]

    \definecolor[nodechart:glyph][maincolor]

    \hboxtoFLOWchart[dummy]{\tttf\righttoleft فَخَا}

    \FLOWchart[dummy][width=12em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]

\stopbuffer

\startbuffer[nodechart:3b]

    \switchtobodyfont[6pt]

    \definecolor[nodechart:glyph][maincolor]

    \hboxtoFLOWchart[dummy]{{\definedfont[name:husayni*otftracker-husayni at 6pt]\righttoleft فَخَا}}

    \FLOWchart[dummy][width=12em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]

\stopbuffer

\startcomponent fonts-modes

\environment fonts-environment

\startchapter[title=Modes][color=darkgreen]

\startsection[title=Introduction]

We use the term modes for classifying the several ways characters are turned into
glyphs. When a font is defined, a set of features can be associated and one of
them is the mode.

\starttabulate[|l|p|]
\NC none \NC Characters are just mapped onto glyphs and no substitution or
             positioning takes place. \NC \NR
\NC base \NC The routines built into the engine are used. For many Latin fonts
             this is a rather useable and efficient method. \NC \NR
\NC node \NC Here alternative routines written in \LUA\ are used. This mode is
             needed for more complex scripts as well as more advanced features
             that demand some analysis. \NC \NR
\NC auto \NC This mode will determine the most suitable mode for the given
             feature set. \NC \NR
\stoptabulate

When we talk about features, we refer to more than only features provided by
fonts as \CONTEXT\ adds some of its own. In the following section each of these
modes is discussed. Before we do so a short introduction to font tables that we
use is given.

\stopsection

\startsection[title=The font table]

The internal representation of a font in \CONTEXT\ is such that we can
conveniently access data that is needed in the mentioned modes. When a font is
used for the first time, or when it has changed, it is read in its most raw form.
After some cleanup and normalization the font gets cached when it is a \TYPEONE\
or \OPENTYPE\ font. This is done in a rather efficient way. A next time the
cached copy is used.

The normalized table is shared among instances of a font. This means that when a
font is used at a different scale, or when a different feature set is used, the
font gets loaded only once and its data is shared when possible. In \in {figure}
[fig:tfm-loading] we have visualized the process. Say that you ask for font \type
{whatever} at \type {12pt} using featureset \type {smallcaps}. In low level code
this boils down to:

\starttyping
\font\MySmallCaps=whatever*smallcaps at 12pt
\stoptyping

In \CONTEXT\ we have overloaded the font loader so \LUA\ code takes care of the
loading. Basically there is a function hooked into \LUATEX's font definer (the
\type {\font} primitive) that returns a table and from that on \LUATEX\ will
create its internal representation that is identified by a number, the so called
font id. So, in fact the \type {\Whatever} command is a reference to a font id, a
positive number. When this font is already loaded, \CONTEXT\ will reuse the id
and pas that one.

\startFLOWchart[loading]
    \startFLOWcell \name {tfm  1} \location {2,1} \text {raw        tfm} \connection [bt]{tfm 2}  \stopFLOWcell
    \startFLOWcell \name {tfm  2} \location {2,2} \text {normalized tfm} \connection [rl]{tfm 3}  \stopFLOWcell
    \startFLOWcell \name {tfm  3} \location {4,2} \text {featured   tfm} \connection[+rl]{tfm 5a}
                                                                         \connection [rl]{tfm 5b}
                                                                         \connection[-rl]{tfm 5c} \stopFLOWcell

    \startFLOWcell \name {tfm 5a} \location {5,1} \text {scaled     tfm} \connection[r+t]{tfm}    \stopFLOWcell
    \startFLOWcell \name {tfm 5b} \location {5,2} \text {scaled     tfm} \connection [rt]{tfm}    \stopFLOWcell
    \startFLOWcell \name {tfm 5c} \location {5,3} \text {scaled     tfm} \connection[r-t]{tfm}    \stopFLOWcell

    \startFLOWcell \name {afm  1} \location {2,4} \text {raw        afm} \connection [bt]{afm 2}  \stopFLOWcell
    \startFLOWcell \name {afm  2} \location {2,5} \text {normalized afm} \connection [rl]{afm 3}  \stopFLOWcell
    \startFLOWcell \name {afm  3} \location {3,5} \text {cached     afm} \connection[+rl]{afm 4a}
                                                                         \connection [rl]{afm 4b} \stopFLOWcell
    \startFLOWcell \name {afm 4a} \location {4,4} \text {featured   afm} \connection [rl]{afm 5a} \stopFLOWcell
    \startFLOWcell \name {afm 4b} \location {4,5} \text {featured   afm} \connection [rl]{afm 5b}
                                                                         \connection[-rl]{afm 5c} \stopFLOWcell
    \startFLOWcell \name {afm 5a} \location {5,4} \text {scaled     afm} \connection[r+l]{tfm}    \stopFLOWcell
    \startFLOWcell \name {afm 5b} \location {5,5} \text {scaled     afm} \connection [rl]{tfm}    \stopFLOWcell
    \startFLOWcell \name {afm 5c} \location {5,6} \text {scaled     afm} \connection[r-l]{tfm}    \stopFLOWcell

    \startFLOWcell \name {otf  1} \location {2,7} \text {raw        otf} \connection [bt]{otf 2}  \stopFLOWcell
    \startFLOWcell \name {otf  2} \location {2,8} \text {normalized otf} \connection [rl]{otf 3}  \stopFLOWcell
    \startFLOWcell \name {otf  3} \location {3,8} \text {cached     otf} \connection[+rl]{otf 4a}
                                                                         \connection [rl]{otf 4b} \stopFLOWcell
    \startFLOWcell \name {otf 4a} \location {4,7} \text {featured   otf} \connection [rl]{otf 5a} \stopFLOWcell
    \startFLOWcell \name {otf 4b} \location {4,8} \text {featured   otf} \connection [rl]{otf 5b}
                                                                         \connection[-rl]{otf 5c} \stopFLOWcell
    \startFLOWcell \name {otf 5a} \location {5,7} \text {scaled     otf} \connection[r-b]{tfm}    \stopFLOWcell
    \startFLOWcell \name {otf 5b} \location {5,8} \text {scaled     otf} \connection [rb]{tfm}    \stopFLOWcell
    \startFLOWcell \name {otf 5c} \location {5,9} \text {scaled     otf} \connection[r+b]{tfm}    \stopFLOWcell

    \startFLOWcell \name {tfm}    \location {6,5} \text {engine tfm} \stopFLOWcell
\stopFLOWchart

\startplacefigure [location=here,reference=fig:tfm-loading,title={Defining a font.}]
    \FLOWchart[loading][dx=.75\bodyfontsize,dy=.5\bodyfontsize,width=6\bodyfontsize,offset=0pt,x=2]
\stopplacefigure

The first step is loading the font (or using the cached copy). From that a copy
is made that has some additional data concerning the features set and from that a
scaled copy is constructed. These copies share as much data as possible to keep
the memory footprint as small as possible. The table that is passed to \LUATEX\
gets cleaned up afterwards. In practice the \TFM\ loader only kicks in for
creating virtual math fonts. The \AFM\ reader is used for \TYPEONE\ fonts and as
there is no free upgrade path from \TYPEONE\ to \OPENTYPE\ for commercial fonts,
that one will get used for older fonts. Of course most loading is done by the
\OTF\ reader(s).

\appendixdata{\in[fonts:trackers:tables]}

The data in the final \TFM\ table is organized in subtables. The biggest ones are
the \type {characters} and \type {descriptions} tables that have information
about each glyph. Later we will see more of that. There are a few additional
tables of which we show two: \type {properties} and \type {parameters}. For the
current font the first one has the following entries:

\showfontproperties

The \type {parameters} table has variables that have been (re)assigned in the
process. A period in the key indicates that we are dealing with a subtable, for
instance \type {expansion}.

\showfontparameters

To give you an impression of what we are dealing with, the positional features
are shown next:

\showfontpositionings

The substitution features of the current font are as follows:

\showfontsubstitutions

This is clearly an \OPENTYPE\ font. Normally there are a default
script and default language supported. If this is not the case you
need to provide them as part of the featureset, otherwise there
will be no features applied.

\stopsection

\startsection[title=Base mode]

We talk of base mode processing when the font machinery is used that is built in
\LUATEX. So what does this traditional mechanism provide?

Before we discuss this, a somewhat simplified model of how \TEX\ works has to be
given. Say that we have the following input:

\starttyping
\def\bla{BLA}
test \bla test
\stoptyping

This input gets translated into tokens and those tokens are either processed
later or they become something else directly. Take the first line. Characters in
the input have a so called catcode property that determines how the parser
tokenized them. Effectively we therefore get something like this:

\starttyping
<command def>
<command bla>
<begingroup>
<character B>
<character L>
<character A>
<endgroup>
\stoptyping

and finally in the hash table there will be an entry for \type {bla} that has the
meaning \type {BLA} expressed in three characters.

The second line refers to \type {\bla} and in the process this macro gets
expanded, so we get:

\starttyping
<character t>
<character e>
<character s>
<character t>
<space>
<character B>
<character L>
<character A>
<character t>
<character e>
<character s>
<character t>
\stoptyping

Because the parser gobbles spaces after a macro name, there is no space before
the second \type {test}. In practice there will be no intermediate list like
this, because as soon as possible \TEX\ will add something to a so called node
list. When the moment is there, this list will be passed to the typesetting
routine that constructs a horizontal list. Later this list can be converted into
a horizontal box or broken into lines when it concerns a paragraph.

In traditional \TEX\ characters are stored into char nodes and the builder turns
them into glyph nodes. In \LUATEX\ they start out as glyph nodes and the subtype
number will flag them as glyphs. Any value larger than 255 is a signal that the
list has been processed. The previous example leads to the list shown in \in
{figure} [nodechart:1a].

\startplacefigure[title={The text \quote {\typ {test BLAtest}} converted to nodes.},reference=nodechart:1a]
    \getbuffer[nodechart:1a]
\stopplacefigure

Here we have turned off inter|-|character kerning and hyphenation. When we turn
that on, we get a slightly more complex list, as shown in \in {figure}
[nodechart:1b]. Hyphenation points are represented by discretionary nodes and
these have pointers to a pre break, post break and replacement text.

\startplacefigure[title={The text \quote {\typ {test BLAtest}} converted to nodes, hyphenated and kerned.},reference=nodechart:1b]
    \getbuffer[nodechart:1b]
\stopplacefigure

In addition to hyphenation and kerning we can have ligatures. The list in \in
{figure} [nodechart:2a] shows that we get a reference to a ligature in the glyph
node but that the components are still known. This figure also demonstrates that
the ligature is build in steps.

\startplacefigure[title={The rendering of the word \quote {\typ {affiliation}}.},reference=nodechart:2a]
    \getbuffer[nodechart:2a]
\stopplacefigure

% \appendixdata{\in[nodes:discretionaries]}

If we insert an explicit \type {\discretionary} command, we see in
\in {figure} [nodechart:2b] that we get three variants. In \in
{figure} [nodechart:2c] we render some Dutch words and these have
quite some ligatures.

\startplacefigure[title={The rendering of the bogus word \quote {\typ {abcghi}} with an
        explicit discretionary added.},reference=nodechart:2b]
    \getbuffer[nodechart:2b]
\stopplacefigure

\startplacefigure[title={The rendering of the Dutch words \quote { \typ{effe fijn fietsen}}.},reference=nodechart:2c]
    \getbuffer[nodechart:2c]
\stopplacefigure

So, we have hyphenation, ligature building and kerning and to some extent these
mechanisms hook into each other. This process is driven by information stored in
the font and rules related to the language. The hyphenation happens first, so the
builder just sees discretionary nodes and needs to act properly on them. Although
languages play an important role in formatting the text, for the moment we can
forget about that. This leaves the font.

As we already mentioned in a previous chapter, in \CONTEXT\ we use \UNICODE\
internally. This also means that fonts are organized this way. By default the
glyph representation of a \UNICODE\ character sits in the same slot in the glyph
table. All additional glyphs, like ligatures or alternates are pushed in the
private unicode space. This is why in the lists shown in the figures the
ligatures have a private \UNICODE\ number.

The basic mode of operation in the builder in \LUATEX\ is as follows:

\startitemize[packed]
\startitem hyphenate the node list \stopitem
\startitem build ligatures \stopitem
\startitem inject kerns \stopitem
\startitem optionally break into lines \stopitem
\stopitemize

In traditional \TEX\ the first step is not that independent. There hyphenation
takes place when the text is broken into lines, and only in places that are
candidate for such a break. In \LUATEX\ the whole text is hyphenated. This has
the advantage that the steps are clearly separated and that no complex
reconstruction and re|-|hyphenation has to take place. The speed penalty can be
neglected and the extra memory overhead is small compared to what is needed
anyway.

In base mode the raw font data is read in and from that only basic information is
used to construct the \TFM\ table: dimensions, ligatures and kerns. In a node
list, all glyph ranges that refer to such a font get the standard ligature and
kern routines applied, but only if the subtype is still less than 256. This check
on subtype prevents duplicate processing that might happen as a side effect of
for instance unboxing some material in a yet to be typeset text.

Given that the majority of what \TEX\ has to deal with is relatively simple latin
script, base mode processing is rather convenient and efficient. It is also the
reference point of other kinds of processing. The most simple way to force base
mode is the following:

\starttyping
\definefontfeature[basemode][mode=base,kern=yes,liga=yes]

\definefont[MyTitleFont][SerifBold*basemode at 12pt]
\stoptyping

Here \type {\MyTitleFont} will be a bold serif with ligatures and kerns applied.
However, as an \OPENTYPE\ font can have many features, the following definitions
are also valid:

\starttyping
\definefontfeature[basemode-o][mode=base,kern=yes,onum=yes,liga=yes]
\definefontfeature[basemode-s][mode=base,kern=yes,smcp=yes]
\stoptyping

The \TFM\ constructor will filter the right information from the font data and
construct a proper table based on these specifications. But you need to keep in
mind that when for instance old style numerals or small caps are activated, that
their rendering (the glyph) will always be used. So, for instance \type {3} and
\type {A} keep their \UNICODE\ points but as part of their specification they
will get an index pointing to the oldstyle or small caps variant and the
dimensions of that shape will be used.

\stopsection

\startsection[title=Node mode]

Node mode is by far the most interesting of the modes. When enabled we only pass
a few properties of glyphs to the engine: the width, height and depth and
optionally protrusion, expansion factors as well as some extra \CONTEXT\ specific
quantities. So there is no kerning and no ligature building done by the engine.
Instead we do this in \LUA\ by walking over the node list and checking if some
action is needed.

\appendixdata{\in[fonts:trackers:features]}

The default feature set enables kerning and ligature building for default and/or
Latin scripts and the default language. Being a relative simple feature,
ligatures don't take much action. Next we show a trace of a ligature replacement.

\blank
\showotfcomposition{name:dejavuserif*default at 24pt}{1}{affiliation}
\blank

Be warned that this \type {f f i} sequence not always becomes a ligature.
Actually this is one area where tradition is quite visible: for some reason most
fonts do have these f|-|related ligatures but lack others. These ligatures even
have code points in \UNICODE\ which is quite debatable. Just as there are fonts
with hardly any kerns (like Lucida) there are fonts that follow a different route
to improve the look and feel of neighbouring glyphs, like Cambria:

\blank
\showotfcomposition{name:cambria*default at 24pt}{1}{affiliation}
\blank

Instead of representing multiple characters by one glyph the designer has decided
to replace the \type {f} by a slightly narrower one so that the dot of the \type
{i} stays loose.

An example where much more is involved is the following. The Husayni font that is
used for typesetting Arabic is built upon a solid but complex \OPENTYPE\
foundation and can only be dealt with in node mode. When the \LUATEX\ project
started we assumed that more power in the engine was needed to accomplish this,
but so far the results with standard \OPENTYPE\ functionality are quite good.
\CONTEXT\ has an additional paragraph optimizer that can apply additional
features to get even better results but discussing this falls beyond this
chapter. A trace of just one Arabic word is much longer than the previously shown
traces.

\blank
\showotfcomposition{name:husayni*otftracker-husayni at 48pt}{-1}{فَخَا}
\blank

What we see here is a stepwise substitution process, sometimes based on a
contextual analysis, followed by positioning. The coloring concerns the outcome
of the analysis which in this case flags initial, final, medial and isolated
characters.

The starting point of this Arabic word is visualized in \in {figure}
[nodechart:3a] and as expected we see no discretionary nodes here. The result as
seen in \in {figure} [nodechart:3b] has (interestingly) no kerns as all
replacements happen via offsets in the glyph node.

\startplacefigure[title={The Arabic input \quote {\tttf\righttoleft فَخَا} before rendering.},reference=nodechart:3a]
    \getbuffer[nodechart:3a]
\stopplacefigure

\startplacefigure[title={The Arabic input \quote {\tttf\righttoleft فَخَا} after rendering.},reference=nodechart:3b]
    \getbuffer[nodechart:3b]
\stopplacefigure

\stopsection

\startsection[title=Auto mode]

Base mode is lean and mean and relatively fast while node mode is more powerful
and slower. So how do you know what to choose? The safest bet is to use node mode
for everything. In \CONTEXT\ however, we also have the so called auto mode. In that
case there is some analysis going on that chooses between base mode and node mode
depending on the boundary conditions of script and language and there are specific
demands in terms of feature processing. So, auto mode will resolve to base or
node mode.

\stopsection

\startsection[title=None mode]

Sometimes no features have to be applied at all. A good example is verbatim.
There you don't want ligatures, kerning or fancy substitutions. Contrary to what
you might expect, monospaced fonts can have such features. Some might actually
make sense, like rendering zeros. However, you cannot assume such a feature to be
present so this is an example of where some more knowledge about a particular
font is needed. This is what Latin Modern provides.

\starttabulate[|l|l|l|]
\NC \type{none} \NC typewriter \NC \ruledhbox{\maincolor\DemoNoneLT1234567890} \NC \NR
\NC \type{zero} \NC typewriter \NC \ruledhbox{\maincolor\DemoZeroLT1234567890} \NC \NR
\NC \type{none} \NC regular    \NC \ruledhbox{\maincolor\DemoNoneLM1234567890} \NC \NR
\NC \type{zero} \NC regular    \NC \ruledhbox{\maincolor\DemoZeroLM1234567890} \NC \NR
\stoptabulate

Normally using mode none for situations that need to be predictable is quite
okay.

\stopsection

\startsection[title=Dynamics]

Sometimes you want to enable or disable a specific feature only for a specific
span of text. Defining a font for only this occasion is overkill, especially when
for instance features are used to fine|-|tune the typography as happens in the
Oriental \TEX\ project, which is related to \LUATEX. Instead of defining yet
another font instance we can therefore enable and disable specific features. For
this it is not needed to know the current font and its size. \footnote {Dynamics
are a \CONTEXT\ specific feature and is not available in the generic version of
the font code. There are several reasons for this: it complicates the code, it
assumes the \CONTEXT\ feature definition mechanism to be used, and it is somewhat
slower as some extra analysis has to be done.}

Dynamics are a special case of node mode and you don't need to set it up when
defining a font. In fact, a font defined in base mode can also be dynamic. We
show some simple examples of applying dynamic features.

% First we define two feature sets, one for ligatures and one for oldstyle. As in
% our example we want to start fresh we also define a simple set with only kerning
% enabled. In a next chapter we will see more of how featuresets are defined.
%
% \startbuffer
% \definefontfeature[l][script=latn,liga=yes]
% \definefontfeature[o][script=latn,onum=yes]
% \definefontfeature[k][script=latn,kern=yes]
%
% \definefont[LOKfont][file:lmroman10-regular*k]
% \stopbuffer
%
% \typebuffer \getbuffer

% \startbuffer[demo]
% {\LOKfont fiets 123          fiets 123          fiets 123}\par
% {\LOKfont fiets 123 \addff{l}fiets 123 \addff{o}fiets 123}\par
% {\LOKfont fiets 123 \addff{o}fiets 123 \addff{l}fiets 123}\par
% {\LOKfont fiets 123 \addfs{l}fiets 123 \addfs{o}fiets 123}\par
% {\LOKfont fiets 123 \addfs{o}fiets 123 \addfs{l}fiets 123}\par
% {\LOKfont fiets 123 \addfs{l}fiets 123 \subfs{l}fiets 123}\par
% {\LOKfont fiets 123 \addfs{o}fiets 123 \subfs{o}fiets 123}\par
% \stopbuffer
%
% We use the following test line:
%
% \typebuffer
%
% In the first line we do nothing but in the following lines we add features to the
% font (replacing existing ones), we add features to the current set (nothing gets
% replaced) and finally we remove some from the set. The typeset result is shown in
% \in {figure} [fig:modes:dynamics].
%
% \placefigure
%   [here]
%   [fig:modes:dynamics]
%   {Selectively applying ligatures and oldstyle numerals using dynamic features in
%    Latin Modern Roman.}
%   {\color[maincolor]{\externalfigure[demo.buffer][width=.75\textwidth]}}
%
% Although for reasons of symmetry we have a few more commands, in practice only
% the following make sense, and even the first one is mostly of interest or
% testing.
%
% \starttabulate[|l|l|]
% \NC \type {\addff} \NC set a feature to be the one applied   \NC \NR
% \NC \type {\addfs} \NC add a feature to current set          \NC \NR
% \NC \type {\subfs} \NC remove a feature from the current set \NC \NR
% \stoptabulate
%
% Keep in mind that the given feature set can set a combination of
% features. Also be aware of the fact that these commands don't
% accumulate: the last one is applied.

% A more sophisticated dynamic feature mechanism is the following. This
% time we do stack up features. We can add, subtract or even replace
% feature sets.

Let's first define some feature sets:

\startbuffer
\definefontfeature[f:smallcaps][smcp=yes]
\definefontfeature[f:nocaps]   [smcp=no]
\definefontfeature[f:oldstyle] [onum=yes]
\definefontfeature[f:newstyle] [onum=no]
\stopbuffer

\typebuffer \getbuffer

We can add and subtract these features from the current feature set
that is bound to the current font.

\startbuffer
\switchtobodyfont[pagella]    123 normal
\addfeature     {f:oldstyle}  123 oldstyle
\addfeature     {f:smallcaps} 123 olstyle smallcaps
\subtractfeature{f:oldstyle}  123 smallcaps
\subtractfeature{f:smallcaps} 123 normal
\stopbuffer

\typebuffer

Here we choose a font that has oldstyle numerals as well as small caps: pagella.

\blank \start \getbuffer \stop \blank

The following does the same, but only uses addition:

\startbuffer
\switchtobodyfont[pagella] 123 normal
\addfeature{f:oldstyle}    123 oldstyle
\addfeature{f:smallcaps}   123 olstyle smallcaps
\addfeature{f:newstyle}    123 smallcaps
\addfeature{f:nocaps}      123 normal
\stopbuffer

\typebuffer

You can also completely replace a feature set. Of course the set is only
forgotten inside the current group.

\startbuffer
\switchtobodyfont[pagella]   123 normal
\addfeature    {f:oldstyle}  123 oldstyle
\addfeature    {f:smallcaps} 123 olstyle smallcaps
\replacefeature{f:oldstyle}  123 oldstyle
\replacefeature{f:smallcaps} 123 smallcaps
\stopbuffer

\typebuffer

and now we get:

\blank \start \getbuffer \stop \blank

You can exercise some control with \type {\resetfeature}:

\startbuffer
\switchtobodyfont[pagella]   123 normal
\addfeature    [f:oldstyle]  123 oldstyle
\addfeature    [f:smallcaps] 123 olstyle smallcaps
\resetfeature                123 reset
\addfeature    [f:oldstyle]  123 oldstyle
\addfeature    [f:smallcaps] 123 olstyle smallcaps
\stopbuffer

\typebuffer

Watch how we use the \type {[]} variant of the commands. The braced and
bracketed variants behave the same.

\blank \start \getbuffer \stop \blank

There is also a generic command \type {\feature} that takes two arguments. Below
we show all calls, with long and short variants:

\starttyping
\addfeature        [f:mine] \feature [more][f:mine] \feature[+][f:mine]
\subtractfeature   [f:mine] \feature [less][f:mine] \feature[-][f:mine]
\replacefeature    [f:mine] \feature  [new][f:mine] \feature[=][f:mine]
\resetandaddfeature[f:mine] \feature[local][f:mine] \feature[!][f:mine]
\revivefeature     [f:mine] \feature  [old][f:mine] \feature[>][f:mine]
\resetfeature               \feature[reset]         \feature[<]
\stoptyping

Each variant also accepts \type {{}} instead of \type {[]} so that they can
conveniently be used in square bracket arguments. As a bonus, the following also
works:

\startbuffer
\switchtobodyfont[pagella]
123 normal
\feature[+][f:smallcaps,f:oldstyle]
123 SmallCaps and OldStyle
\stopbuffer

\typebuffer

Here is the proof:

\blank \start \getbuffer \stop \blank

\stopsection

\startsection[title=Discretionaries]

One of the complications in supporting more complex features is that we can have
discretionary nodes. These are either inserted by the hyphenation engine, or
explicitly by the user (directly or via macros). In most cases we don't need to
bother about this. For instance, more demanding scripts like Arabic don't
hyphenate, languages using the Latin script seldom want ligatures at hyphenation
points (as they can be compound words) and|/|or avoid confusing hyphenation
points, so what is left are specific user inserted discretionaries. Add to that,
that a proper font has not much kerning between lowercase characters and it will
be clear that we can ignore most of this. Anyway, as we explicitly deal with user
discretionaries, the next works out okay. Watch how we normally only have
something special in the replacements text that shows up when no hyphenation is
needed.

\startbuffer
\language[nl]
\definedfont[file:texgyrepagella-regular.otf*default]
\hsize  1mm vereffenen \par
\hsize  1mm effe \par
\hsize  1mm e\discretionary{f-}{f}{ff}e \par
\hsize 20mm e\discretionary{f-}{f}{ff}e \par
\smallcaps
\hsize  1mm vereffenen \par
\hsize  1mm effe \par
\hsize  1mm e\discretionary{f-}{f}{ff}e \par
\hsize 20mm e\discretionary{f-}{f}{ff}e \par
\stopbuffer

\typebuffer

\blank
\startcolumns[n=6]
    \indenting[no]
    \maincolor
    \getbuffer
\stopcolumns
\blank

In base mode such things are handled by the \TEX\ engine itself and it can deal
with pretty complex cases. In node mode we use a simplification which in practice
suffices. We will come back to this in \in {section} [ligatures:hyphenation].

\stopsection

\startsection[title=Efficiency]

The efficiency of the mechanisms described here depends on several factors. It
will be clear that the larger the font, the more time it will take to load it.
But what is large? Most \CJK\ fonts are pretty large but also rather simple. A
font like Zapfino on the other hand covers only latin but comes with many
alternative shapes and a large set of rules. The Husayni font focusses on Arabic,
which in itself has not that large an alphabet, but being an advanced script
font, it has a lot of features and definitely a lot of rules.

In terms of processing it's safe to say that Latin is of average complexity. At
most you will get some substitutions, like regular numerals being replaced by
oldstyles, or ligature building, which involves a bit of analysis, and some
kerning at the end. In base mode the substitutions have no overhead, simply
because the character table already has references to the substituents and the
replacement already takes place when defining the font. There ligature building
and kerning are also fast because of the limited amount of lookups that also are
already kept with the characters. In node mode however, the lists have to be
parsed and tables have to be consulted so even Latin processing has some
overhead: each glyph node is consulted and analyzed (either or not in its
context), often multiple times. However, the code is rather optimized and we use
caching of already analyzed data when possible.

A \CJK\ script is somewhat more complex on the one hand, but pretty simple on the
other. Instead of font based kerning, we need to prevent or encourage breaks
between certain characters. This information is not in the font and is processed
otherwise but it does cost some time. The font part however is largely idle as
there are no features to be applied. Even better, because the glyphs are large
and the information density is high, the processing time per page is not much
different from Latin. Base mode is good enough for most \CJK.

The Arabic script is another matter. There we definitely go beyond what base mode
offers so we always end up in node mode. Also, because there is some analysis
involved, quite some substitutions and in the end also positioning, these are the
least efficient fonts in terms of processing time. Of course the fact that we mix
directions also plays a role. If in the Husayni font you enable 30 features with
an average of 5 rules per feature, a 300 character paragraph will take 45.000
actions. \footnote {For a modern machine this amount is no real issue, but as
each action involves function calls and possibly some garbage collection there
is some price to pay.} When multiple fonts are combined in a paragraph there will
be more sweeps over the list and of course the replacements also have to happen.

In a time when the average photo camera produces megabyte pictures it makes no
sense to whine about the size of a font file. On the other hand as each font
eventually ends up in memory as a \LUA\ table, it makes sense to optimize that
bit. This is why fonts are converted into a more efficient intermediate table
that is cached on disk. This makes loading a font quite fast and due to shared
tables memory usage rather efficient. Of course a scaled instance has to be
generated too, but that is acceptable. To some extent loading and defining a font
also depends on the way the macro package is set up.

When comparing \LUATEX\ with for instance \PDFTEX\ or \XETEX\ you need to take
into account that in \CONTEXT\ \MKIV\ we tend to use \OPENTYPE\ fonts only so
there are less fonts loaded than in a more traditional setup. In \CONTEXT\
startup time of \MKIV\ is less than \MKII\ although overall processing time is
slower, which is due to \UNICODE\ being used and more functionality being
provided. On the other hand, immediate \METAPOST\ processing and more clever
multipass handling wins back time. The impact of fonts on processing time in a
regular document is therefore not that impressive. In practice a \MKIV\ run can
be faster than a \MKII\ run, especially when \METAPOST\ is used.

In \CONTEXT\ processing of node lists with respect to fonts is only one of the
many manipulations of such lists and by now fonts are not really the bottleneck.
The more not font related features users demand and enable, the less the relative
impact of font processing becomes.

Also, there are some advanced typographic extras that \LUATEX\ offers, like
protrusion (think of hanging punctuation) and hz optimization (glyph scaling) and
these slow down processing quite a lot, and they are not taking place at the
\LUA\ end at all, but this might change in \MKIV. And, of course, typesetting
involves more than fonts and other aspects can be way more demanding.

\stopsection

\stopchapter

\stopcomponent

% oldstyle not in math (old school tex)
% funny tex ligatures
% features=yes
% analysis
% mode=none (tt)