fonts-modes.tex /size: 33 Kb    last modification: 2021-10-28 13:50
1% language=us runpath=texruns:manuals/fonts
2
3\definefontfeature
4  [otftracker-husayni]
5  [analyze=yes,mode=node,language=dflt,script=arab,
6   ccmp=yes,init=yes,medi=yes,fina=yes,
7   rlig=yes,tlig=yes,anum=yes,calt=yes,salt=yes,
8   ss01=yes,ss03=yes,ss10=yes,ss12=yes,ss15=yes,
9   ss16=yes,ss19=yes,ss24=yes,ss25=yes,ss26=yes,
10   ss27=yes,ss31=yes,ss34=yes,ss35=yes,ss36=yes,
11   ss37=yes,ss38=yes,ss41=yes,ss42=yes,ss43=yes,
12   ss60=yes,js16=yes,
13   kern=yes,curs=yes,mark=yes,mkmk=yes]
14
15\startbuffer[nodechart:1a]
16
17    \switchtobodyfont[6pt]
18
19    \definecolor[nodechart:glyph][maincolor]
20
21    \hboxtoFLOWchart[dummy]{\definedfont[Normal*none]\language0 test BLAtest}
22
23    \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]
24
25\stopbuffer
26
27\startbuffer[nodechart:1b]
28
29    \switchtobodyfont[6pt]
30
31    \definecolor[nodechart:glyph][maincolor]
32
33    \hboxtoFLOWchart[dummy]{test BLAtest}
34
35    \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]
36
37\stopbuffer
38
39\startbuffer[nodechart:2a]
40
41    \switchtobodyfont[6pt]
42
43    \definecolor[nodechart:glyph][maincolor]
44
45    \hboxtoFLOWchart[dummy]{affiliation}
46
47    \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]
48
49\stopbuffer
50
51\startbuffer[nodechart:2b]
52
53    \switchtobodyfont[6pt]
54
55    \definecolor[nodechart:glyph][maincolor]
56
57    \hboxtoFLOWchart[dummy]{abc\discretionary{d}{e}{f}ghi}
58
59    \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]
60
61\stopbuffer
62
63\startbuffer[nodechart:2c]
64
65    \switchtobodyfont[6pt]
66
67    \definecolor[nodechart:glyph][maincolor]
68
69    \hboxtoFLOWchart[dummy]{\nl effe fijn fietsen}
70
71    \FLOWchart[dummy][width=12em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]
72
73\stopbuffer
74
75\startbuffer[nodechart:3a]
76
77    \switchtobodyfont[6pt]
78
79    \definecolor[nodechart:glyph][maincolor]
80
81    \hboxtoFLOWchart[dummy]{\tttf\righttoleft فَخَا}
82
83    \FLOWchart[dummy][width=12em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]
84
85\stopbuffer
86
87\startbuffer[nodechart:3b]
88
89    \switchtobodyfont[6pt]
90
91    \definecolor[nodechart:glyph][maincolor]
92
93    \hboxtoFLOWchart[dummy]{{\definedfont[name:husayni*otftracker-husayni at 6pt]\righttoleft فَخَا}}
94
95    \FLOWchart[dummy][width=12em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes]
96
97\stopbuffer
98
99\startcomponent fonts-modes
100
101\environment fonts-environment
102
103\startchapter[title=Modes][color=darkgreen]
104
105\startsection[title=Introduction]
106
107We use the term modes for classifying the several ways characters are turned into
108glyphs. When a font is defined, a set of features can be associated and one of
109them is the mode.
110
111\starttabulate[|l|p|]
112\NC none \NC Characters are just mapped onto glyphs and no substitution or
113             positioning takes place. \NC \NR
114\NC base \NC The routines built into the engine are used. For many Latin fonts
115             this is a rather useable and efficient method. \NC \NR
116\NC node \NC Here alternative routines written in \LUA\ are used. This mode is
117             needed for more complex scripts as well as more advanced features
118             that demand some analysis. \NC \NR
119\NC auto \NC This mode will determine the most suitable mode for the given
120             feature set. \NC \NR
121\stoptabulate
122
123When we talk about features, we refer to more than only features provided by
124fonts as \CONTEXT\ adds some of its own. In the following section each of these
125modes is discussed. Before we do so a short introduction to font tables that we
126use is given.
127
128\stopsection
129
130\startsection[title=The font table]
131
132The internal representation of a font in \CONTEXT\ is such that we can
133conveniently access data that is needed in the mentioned modes. When a font is
134used for the first time, or when it has changed, it is read in its most raw form.
135After some cleanup and normalization the font gets cached when it is a \TYPEONE\
136or \OPENTYPE\ font. This is done in a rather efficient way. A next time the
137cached copy is used.
138
139The normalized table is shared among instances of a font. This means that when a
140font is used at a different scale, or when a different feature set is used, the
141font gets loaded only once and its data is shared when possible. In \in {figure}
142[fig:tfm-loading] we have visualized the process. Say that you ask for font \type
143{whatever} at \type {12pt} using featureset \type {smallcaps}. In low level code
144this boils down to:
145
146\starttyping
147\font\MySmallCaps=whatever*smallcaps at 12pt
148\stoptyping
149
150In \CONTEXT\ we have overloaded the font loader so \LUA\ code takes care of the
151loading. Basically there is a function hooked into \LUATEX's font definer (the
152\type {\font} primitive) that returns a table and from that on \LUATEX\ will
153create its internal representation that is identified by a number, the so called
154font id. So, in fact the \type {\Whatever} command is a reference to a font id, a
155positive number. When this font is already loaded, \CONTEXT\ will reuse the id
156and pas that one.
157
158\startFLOWchart[loading]
159    \startFLOWcell \name {tfm  1} \location {2,1} \text {raw        tfm} \connection [bt]{tfm 2}  \stopFLOWcell
160    \startFLOWcell \name {tfm  2} \location {2,2} \text {normalized tfm} \connection [rl]{tfm 3}  \stopFLOWcell
161    \startFLOWcell \name {tfm  3} \location {4,2} \text {featured   tfm} \connection[+rl]{tfm 5a}
162                                                                         \connection [rl]{tfm 5b}
163                                                                         \connection[-rl]{tfm 5c} \stopFLOWcell
164
165    \startFLOWcell \name {tfm 5a} \location {5,1} \text {scaled     tfm} \connection[r+t]{tfm}    \stopFLOWcell
166    \startFLOWcell \name {tfm 5b} \location {5,2} \text {scaled     tfm} \connection [rt]{tfm}    \stopFLOWcell
167    \startFLOWcell \name {tfm 5c} \location {5,3} \text {scaled     tfm} \connection[r-t]{tfm}    \stopFLOWcell
168
169    \startFLOWcell \name {afm  1} \location {2,4} \text {raw        afm} \connection [bt]{afm 2}  \stopFLOWcell
170    \startFLOWcell \name {afm  2} \location {2,5} \text {normalized afm} \connection [rl]{afm 3}  \stopFLOWcell
171    \startFLOWcell \name {afm  3} \location {3,5} \text {cached     afm} \connection[+rl]{afm 4a}
172                                                                         \connection [rl]{afm 4b} \stopFLOWcell
173    \startFLOWcell \name {afm 4a} \location {4,4} \text {featured   afm} \connection [rl]{afm 5a} \stopFLOWcell
174    \startFLOWcell \name {afm 4b} \location {4,5} \text {featured   afm} \connection [rl]{afm 5b}
175                                                                         \connection[-rl]{afm 5c} \stopFLOWcell
176    \startFLOWcell \name {afm 5a} \location {5,4} \text {scaled     afm} \connection[r+l]{tfm}    \stopFLOWcell
177    \startFLOWcell \name {afm 5b} \location {5,5} \text {scaled     afm} \connection [rl]{tfm}    \stopFLOWcell
178    \startFLOWcell \name {afm 5c} \location {5,6} \text {scaled     afm} \connection[r-l]{tfm}    \stopFLOWcell
179
180    \startFLOWcell \name {otf  1} \location {2,7} \text {raw        otf} \connection [bt]{otf 2}  \stopFLOWcell
181    \startFLOWcell \name {otf  2} \location {2,8} \text {normalized otf} \connection [rl]{otf 3}  \stopFLOWcell
182    \startFLOWcell \name {otf  3} \location {3,8} \text {cached     otf} \connection[+rl]{otf 4a}
183                                                                         \connection [rl]{otf 4b} \stopFLOWcell
184    \startFLOWcell \name {otf 4a} \location {4,7} \text {featured   otf} \connection [rl]{otf 5a} \stopFLOWcell
185    \startFLOWcell \name {otf 4b} \location {4,8} \text {featured   otf} \connection [rl]{otf 5b}
186                                                                         \connection[-rl]{otf 5c} \stopFLOWcell
187    \startFLOWcell \name {otf 5a} \location {5,7} \text {scaled     otf} \connection[r-b]{tfm}    \stopFLOWcell
188    \startFLOWcell \name {otf 5b} \location {5,8} \text {scaled     otf} \connection [rb]{tfm}    \stopFLOWcell
189    \startFLOWcell \name {otf 5c} \location {5,9} \text {scaled     otf} \connection[r+b]{tfm}    \stopFLOWcell
190
191    \startFLOWcell \name {tfm}    \location {6,5} \text {engine tfm} \stopFLOWcell
192\stopFLOWchart
193
194\startplacefigure [location=here,reference=fig:tfm-loading,title={Defining a font.}]
195    \FLOWchart[loading][dx=.75\bodyfontsize,dy=.5\bodyfontsize,width=6\bodyfontsize,offset=0pt,x=2]
196\stopplacefigure
197
198The first step is loading the font (or using the cached copy). From that a copy
199is made that has some additional data concerning the features set and from that a
200scaled copy is constructed. These copies share as much data as possible to keep
201the memory footprint as small as possible. The table that is passed to \LUATEX\
202gets cleaned up afterwards. In practice the \TFM\ loader only kicks in for
203creating virtual math fonts. The \AFM\ reader is used for \TYPEONE\ fonts and as
204there is no free upgrade path from \TYPEONE\ to \OPENTYPE\ for commercial fonts,
205that one will get used for older fonts. Of course most loading is done by the
206\OTF\ reader(s).
207
208\appendixdata{\in[fonts:trackers:tables]}
209
210The data in the final \TFM\ table is organized in subtables. The biggest ones are
211the \type {characters} and \type {descriptions} tables that have information
212about each glyph. Later we will see more of that. There are a few additional
213tables of which we show two: \type {properties} and \type {parameters}. For the
214current font the first one has the following entries:
215
216\showfontproperties
217
218The \type {parameters} table has variables that have been (re)assigned in the
219process. A period in the key indicates that we are dealing with a subtable, for
220instance \type {expansion}.
221
222\showfontparameters
223
224To give you an impression of what we are dealing with, the positional features
225are shown next:
226
227\showfontpositionings
228
229The substitution features of the current font are as follows:
230
231\showfontsubstitutions
232
233This is clearly an \OPENTYPE\ font. Normally there are a default
234script and default language supported. If this is not the case you
235need to provide them as part of the featureset, otherwise there
236will be no features applied.
237
238\stopsection
239
240\startsection[title=Base mode]
241
242We talk of base mode processing when the font machinery is used that is built in
243\LUATEX. So what does this traditional mechanism provide?
244
245Before we discuss this, a somewhat simplified model of how \TEX\ works has to be
246given. Say that we have the following input:
247
248\starttyping
249\def\bla{BLA}
250test \bla test
251\stoptyping
252
253This input gets translated into tokens and those tokens are either processed
254later or they become something else directly. Take the first line. Characters in
255the input have a so called catcode property that determines how the parser
256tokenized them. Effectively we therefore get something like this:
257
258\starttyping
259<command def>
260<command bla>
261<begingroup>
262<character B>
263<character L>
264<character A>
265<endgroup>
266\stoptyping
267
268and finally in the hash table there will be an entry for \type {bla} that has the
269meaning \type {BLA} expressed in three characters.
270
271The second line refers to \type {\bla} and in the process this macro gets
272expanded, so we get:
273
274\starttyping
275<character t>
276<character e>
277<character s>
278<character t>
279<space>
280<character B>
281<character L>
282<character A>
283<character t>
284<character e>
285<character s>
286<character t>
287\stoptyping
288
289Because the parser gobbles spaces after a macro name, there is no space before
290the second \type {test}. In practice there will be no intermediate list like
291this, because as soon as possible \TEX\ will add something to a so called node
292list. When the moment is there, this list will be passed to the typesetting
293routine that constructs a horizontal list. Later this list can be converted into
294a horizontal box or broken into lines when it concerns a paragraph.
295
296In traditional \TEX\ characters are stored into char nodes and the builder turns
297them into glyph nodes. In \LUATEX\ they start out as glyph nodes and the subtype
298number will flag them as glyphs. Any value larger than 255 is a signal that the
299list has been processed. The previous example leads to the list shown in \in
300{figure} [nodechart:1a].
301
302\startplacefigure[title={The text \quote {\typ {test BLAtest}} converted to nodes.},reference=nodechart:1a]
303    \getbuffer[nodechart:1a]
304\stopplacefigure
305
306Here we have turned off inter|-|character kerning and hyphenation. When we turn
307that on, we get a slightly more complex list, as shown in \in {figure}
308[nodechart:1b]. Hyphenation points are represented by discretionary nodes and
309these have pointers to a pre break, post break and replacement text.
310
311\startplacefigure[title={The text \quote {\typ {test BLAtest}} converted to nodes, hyphenated and kerned.},reference=nodechart:1b]
312    \getbuffer[nodechart:1b]
313\stopplacefigure
314
315In addition to hyphenation and kerning we can have ligatures. The list in \in
316{figure} [nodechart:2a] shows that we get a reference to a ligature in the glyph
317node but that the components are still known. This figure also demonstrates that
318the ligature is build in steps.
319
320\startplacefigure[title={The rendering of the word \quote {\typ {affiliation}}.},reference=nodechart:2a]
321    \getbuffer[nodechart:2a]
322\stopplacefigure
323
324% \appendixdata{\in[nodes:discretionaries]}
325
326If we insert an explicit \type {\discretionary} command, we see in
327\in {figure} [nodechart:2b] that we get three variants. In \in
328{figure} [nodechart:2c] we render some Dutch words and these have
329quite some ligatures.
330
331\startplacefigure[title={The rendering of the bogus word \quote {\typ {abcghi}} with an
332        explicit discretionary added.},reference=nodechart:2b]
333    \getbuffer[nodechart:2b]
334\stopplacefigure
335
336\startplacefigure[title={The rendering of the Dutch words \quote { \typ{effe fijn fietsen}}.},reference=nodechart:2c]
337    \getbuffer[nodechart:2c]
338\stopplacefigure
339
340So, we have hyphenation, ligature building and kerning and to some extent these
341mechanisms hook into each other. This process is driven by information stored in
342the font and rules related to the language. The hyphenation happens first, so the
343builder just sees discretionary nodes and needs to act properly on them. Although
344languages play an important role in formatting the text, for the moment we can
345forget about that. This leaves the font.
346
347As we already mentioned in a previous chapter, in \CONTEXT\ we use \UNICODE\
348internally. This also means that fonts are organized this way. By default the
349glyph representation of a \UNICODE\ character sits in the same slot in the glyph
350table. All additional glyphs, like ligatures or alternates are pushed in the
351private unicode space. This is why in the lists shown in the figures the
352ligatures have a private \UNICODE\ number.
353
354The basic mode of operation in the builder in \LUATEX\ is as follows:
355
356\startitemize[packed]
357\startitem hyphenate the node list \stopitem
358\startitem build ligatures \stopitem
359\startitem inject kerns \stopitem
360\startitem optionally break into lines \stopitem
361\stopitemize
362
363In traditional \TEX\ the first step is not that independent. There hyphenation
364takes place when the text is broken into lines, and only in places that are
365candidate for such a break. In \LUATEX\ the whole text is hyphenated. This has
366the advantage that the steps are clearly separated and that no complex
367reconstruction and re|-|hyphenation has to take place. The speed penalty can be
368neglected and the extra memory overhead is small compared to what is needed
369anyway.
370
371In base mode the raw font data is read in and from that only basic information is
372used to construct the \TFM\ table: dimensions, ligatures and kerns. In a node
373list, all glyph ranges that refer to such a font get the standard ligature and
374kern routines applied, but only if the subtype is still less than 256. This check
375on subtype prevents duplicate processing that might happen as a side effect of
376for instance unboxing some material in a yet to be typeset text.
377
378Given that the majority of what \TEX\ has to deal with is relatively simple latin
379script, base mode processing is rather convenient and efficient. It is also the
380reference point of other kinds of processing. The most simple way to force base
381mode is the following:
382
383\starttyping
384\definefontfeature[basemode][mode=base,kern=yes,liga=yes]
385
386\definefont[MyTitleFont][SerifBold*basemode at 12pt]
387\stoptyping
388
389Here \type {\MyTitleFont} will be a bold serif with ligatures and kerns applied.
390However, as an \OPENTYPE\ font can have many features, the following definitions
391are also valid:
392
393\starttyping
394\definefontfeature[basemode-o][mode=base,kern=yes,onum=yes,liga=yes]
395\definefontfeature[basemode-s][mode=base,kern=yes,smcp=yes]
396\stoptyping
397
398The \TFM\ constructor will filter the right information from the font data and
399construct a proper table based on these specifications. But you need to keep in
400mind that when for instance old style numerals or small caps are activated, that
401their rendering (the glyph) will always be used. So, for instance \type {3} and
402\type {A} keep their \UNICODE\ points but as part of their specification they
403will get an index pointing to the oldstyle or small caps variant and the
404dimensions of that shape will be used.
405
406\stopsection
407
408\startsection[title=Node mode]
409
410Node mode is by far the most interesting of the modes. When enabled we only pass
411a few properties of glyphs to the engine: the width, height and depth and
412optionally protrusion, expansion factors as well as some extra \CONTEXT\ specific
413quantities. So there is no kerning and no ligature building done by the engine.
414Instead we do this in \LUA\ by walking over the node list and checking if some
415action is needed.
416
417\appendixdata{\in[fonts:trackers:features]}
418
419The default feature set enables kerning and ligature building for default and/or
420Latin scripts and the default language. Being a relative simple feature,
421ligatures don't take much action. Next we show a trace of a ligature replacement.
422
423\blank
424\showotfcomposition{name:dejavuserif*default at 24pt}{1}{affiliation}
425\blank
426
427Be warned that this \type {f f i} sequence not always becomes a ligature.
428Actually this is one area where tradition is quite visible: for some reason most
429fonts do have these f|-|related ligatures but lack others. These ligatures even
430have code points in \UNICODE\ which is quite debatable. Just as there are fonts
431with hardly any kerns (like Lucida) there are fonts that follow a different route
432to improve the look and feel of neighbouring glyphs, like Cambria:
433
434\blank
435\showotfcomposition{name:cambria*default at 24pt}{1}{affiliation}
436\blank
437
438Instead of representing multiple characters by one glyph the designer has decided
439to replace the \type {f} by a slightly narrower one so that the dot of the \type
440{i} stays loose.
441
442An example where much more is involved is the following. The Husayni font that is
443used for typesetting Arabic is built upon a solid but complex \OPENTYPE\
444foundation and can only be dealt with in node mode. When the \LUATEX\ project
445started we assumed that more power in the engine was needed to accomplish this,
446but so far the results with standard \OPENTYPE\ functionality are quite good.
447\CONTEXT\ has an additional paragraph optimizer that can apply additional
448features to get even better results but discussing this falls beyond this
449chapter. A trace of just one Arabic word is much longer than the previously shown
450traces.
451
452\blank
453\showotfcomposition{name:husayni*otftracker-husayni at 48pt}{-1}{فَخَا}
454\blank
455
456What we see here is a stepwise substitution process, sometimes based on a
457contextual analysis, followed by positioning. The coloring concerns the outcome
458of the analysis which in this case flags initial, final, medial and isolated
459characters.
460
461The starting point of this Arabic word is visualized in \in {figure}
462[nodechart:3a] and as expected we see no discretionary nodes here. The result as
463seen in \in {figure} [nodechart:3b] has (interestingly) no kerns as all
464replacements happen via offsets in the glyph node.
465
466\startplacefigure[title={The Arabic input \quote {\tttf\righttoleft فَخَا} before rendering.},reference=nodechart:3a]
467    \getbuffer[nodechart:3a]
468\stopplacefigure
469
470\startplacefigure[title={The Arabic input \quote {\tttf\righttoleft فَخَا} after rendering.},reference=nodechart:3b]
471    \getbuffer[nodechart:3b]
472\stopplacefigure
473
474\stopsection
475
476\startsection[title=Auto mode]
477
478Base mode is lean and mean and relatively fast while node mode is more powerful
479and slower. So how do you know what to choose? The safest bet is to use node mode
480for everything. In \CONTEXT\ however, we also have the so called auto mode. In that
481case there is some analysis going on that chooses between base mode and node mode
482depending on the boundary conditions of script and language and there are specific
483demands in terms of feature processing. So, auto mode will resolve to base or
484node mode.
485
486\stopsection
487
488\startsection[title=None mode]
489
490Sometimes no features have to be applied at all. A good example is verbatim.
491There you don't want ligatures, kerning or fancy substitutions. Contrary to what
492you might expect, monospaced fonts can have such features. Some might actually
493make sense, like rendering zeros. However, you cannot assume such a feature to be
494present so this is an example of where some more knowledge about a particular
495font is needed. This is what Latin Modern provides.
496
497\starttabulate[|l|l|l|]
498\NC \type{none} \NC typewriter \NC \ruledhbox{\maincolor\DemoNoneLT1234567890} \NC \NR
499\NC \type{zero} \NC typewriter \NC \ruledhbox{\maincolor\DemoZeroLT1234567890} \NC \NR
500\NC \type{none} \NC regular    \NC \ruledhbox{\maincolor\DemoNoneLM1234567890} \NC \NR
501\NC \type{zero} \NC regular    \NC \ruledhbox{\maincolor\DemoZeroLM1234567890} \NC \NR
502\stoptabulate
503
504Normally using mode none for situations that need to be predictable is quite
505okay.
506
507\stopsection
508
509\startsection[title=Dynamics]
510
511Sometimes you want to enable or disable a specific feature only for a specific
512span of text. Defining a font for only this occasion is overkill, especially when
513for instance features are used to fine|-|tune the typography as happens in the
514Oriental \TEX\ project, which is related to \LUATEX. Instead of defining yet
515another font instance we can therefore enable and disable specific features. For
516this it is not needed to know the current font and its size. \footnote {Dynamics
517are a \CONTEXT\ specific feature and is not available in the generic version of
518the font code. There are several reasons for this: it complicates the code, it
519assumes the \CONTEXT\ feature definition mechanism to be used, and it is somewhat
520slower as some extra analysis has to be done.}
521
522Dynamics are a special case of node mode and you don't need to set it up when
523defining a font. In fact, a font defined in base mode can also be dynamic. We
524show some simple examples of applying dynamic features.
525
526% First we define two feature sets, one for ligatures and one for oldstyle. As in
527% our example we want to start fresh we also define a simple set with only kerning
528% enabled. In a next chapter we will see more of how featuresets are defined.
529%
530% \startbuffer
531% \definefontfeature[l][script=latn,liga=yes]
532% \definefontfeature[o][script=latn,onum=yes]
533% \definefontfeature[k][script=latn,kern=yes]
534%
535% \definefont[LOKfont][file:lmroman10-regular*k]
536% \stopbuffer
537%
538% \typebuffer \getbuffer
539
540% \startbuffer[demo]
541% {\LOKfont fiets 123          fiets 123          fiets 123}\par
542% {\LOKfont fiets 123 \addff{l}fiets 123 \addff{o}fiets 123}\par
543% {\LOKfont fiets 123 \addff{o}fiets 123 \addff{l}fiets 123}\par
544% {\LOKfont fiets 123 \addfs{l}fiets 123 \addfs{o}fiets 123}\par
545% {\LOKfont fiets 123 \addfs{o}fiets 123 \addfs{l}fiets 123}\par
546% {\LOKfont fiets 123 \addfs{l}fiets 123 \subfs{l}fiets 123}\par
547% {\LOKfont fiets 123 \addfs{o}fiets 123 \subfs{o}fiets 123}\par
548% \stopbuffer
549%
550% We use the following test line:
551%
552% \typebuffer
553%
554% In the first line we do nothing but in the following lines we add features to the
555% font (replacing existing ones), we add features to the current set (nothing gets
556% replaced) and finally we remove some from the set. The typeset result is shown in
557% \in {figure} [fig:modes:dynamics].
558%
559% \placefigure
560%   [here]
561%   [fig:modes:dynamics]
562%   {Selectively applying ligatures and oldstyle numerals using dynamic features in
563%    Latin Modern Roman.}
564%   {\color[maincolor]{\externalfigure[demo.buffer][width=.75\textwidth]}}
565%
566% Although for reasons of symmetry we have a few more commands, in practice only
567% the following make sense, and even the first one is mostly of interest or
568% testing.
569%
570% \starttabulate[|l|l|]
571% \NC \type {\addff} \NC set a feature to be the one applied   \NC \NR
572% \NC \type {\addfs} \NC add a feature to current set          \NC \NR
573% \NC \type {\subfs} \NC remove a feature from the current set \NC \NR
574% \stoptabulate
575%
576% Keep in mind that the given feature set can set a combination of
577% features. Also be aware of the fact that these commands don't
578% accumulate: the last one is applied.
579
580% A more sophisticated dynamic feature mechanism is the following. This
581% time we do stack up features. We can add, subtract or even replace
582% feature sets.
583
584Let's first define some feature sets:
585
586\startbuffer
587\definefontfeature[f:smallcaps][smcp=yes]
588\definefontfeature[f:nocaps]   [smcp=no]
589\definefontfeature[f:oldstyle] [onum=yes]
590\definefontfeature[f:newstyle] [onum=no]
591\stopbuffer
592
593\typebuffer \getbuffer
594
595We can add and subtract these features from the current feature set
596that is bound to the current font.
597
598\startbuffer
599\switchtobodyfont[pagella]    123 normal
600\addfeature     {f:oldstyle}  123 oldstyle
601\addfeature     {f:smallcaps} 123 olstyle smallcaps
602\subtractfeature{f:oldstyle}  123 smallcaps
603\subtractfeature{f:smallcaps} 123 normal
604\stopbuffer
605
606\typebuffer
607
608Here we choose a font that has oldstyle numerals as well as small caps: pagella.
609
610\blank \start \getbuffer \stop \blank
611
612The following does the same, but only uses addition:
613
614\startbuffer
615\switchtobodyfont[pagella] 123 normal
616\addfeature{f:oldstyle}    123 oldstyle
617\addfeature{f:smallcaps}   123 olstyle smallcaps
618\addfeature{f:newstyle}    123 smallcaps
619\addfeature{f:nocaps}      123 normal
620\stopbuffer
621
622\typebuffer
623
624You can also completely replace a feature set. Of course the set is only
625forgotten inside the current group.
626
627\startbuffer
628\switchtobodyfont[pagella]   123 normal
629\addfeature    {f:oldstyle}  123 oldstyle
630\addfeature    {f:smallcaps} 123 olstyle smallcaps
631\replacefeature{f:oldstyle}  123 oldstyle
632\replacefeature{f:smallcaps} 123 smallcaps
633\stopbuffer
634
635\typebuffer
636
637and now we get:
638
639\blank \start \getbuffer \stop \blank
640
641You can exercise some control with \type {\resetfeature}:
642
643\startbuffer
644\switchtobodyfont[pagella]   123 normal
645\addfeature    [f:oldstyle]  123 oldstyle
646\addfeature    [f:smallcaps] 123 olstyle smallcaps
647\resetfeature                123 reset
648\addfeature    [f:oldstyle]  123 oldstyle
649\addfeature    [f:smallcaps] 123 olstyle smallcaps
650\stopbuffer
651
652\typebuffer
653
654Watch how we use the \type {[]} variant of the commands. The braced and
655bracketed variants behave the same.
656
657\blank \start \getbuffer \stop \blank
658
659There is also a generic command \type {\feature} that takes two arguments. Below
660we show all calls, with long and short variants:
661
662\starttyping
663\addfeature        [f:mine] \feature [more][f:mine] \feature[+][f:mine]
664\subtractfeature   [f:mine] \feature [less][f:mine] \feature[-][f:mine]
665\replacefeature    [f:mine] \feature  [new][f:mine] \feature[=][f:mine]
666\resetandaddfeature[f:mine] \feature[local][f:mine] \feature[!][f:mine]
667\revivefeature     [f:mine] \feature  [old][f:mine] \feature[>][f:mine]
668\resetfeature               \feature[reset]         \feature[<]
669\stoptyping
670
671Each variant also accepts \type {{}} instead of \type {[]} so that they can
672conveniently be used in square bracket arguments. As a bonus, the following also
673works:
674
675\startbuffer
676\switchtobodyfont[pagella]
677123 normal
678\feature[+][f:smallcaps,f:oldstyle]
679123 SmallCaps and OldStyle
680\stopbuffer
681
682\typebuffer
683
684Here is the proof:
685
686\blank \start \getbuffer \stop \blank
687
688\stopsection
689
690\startsection[title=Discretionaries]
691
692One of the complications in supporting more complex features is that we can have
693discretionary nodes. These are either inserted by the hyphenation engine, or
694explicitly by the user (directly or via macros). In most cases we don't need to
695bother about this. For instance, more demanding scripts like Arabic don't
696hyphenate, languages using the Latin script seldom want ligatures at hyphenation
697points (as they can be compound words) and|/|or avoid confusing hyphenation
698points, so what is left are specific user inserted discretionaries. Add to that,
699that a proper font has not much kerning between lowercase characters and it will
700be clear that we can ignore most of this. Anyway, as we explicitly deal with user
701discretionaries, the next works out okay. Watch how we normally only have
702something special in the replacements text that shows up when no hyphenation is
703needed.
704
705\startbuffer
706\language[nl]
707\definedfont[file:texgyrepagella-regular.otf*default]
708\hsize  1mm vereffenen \par
709\hsize  1mm effe \par
710\hsize  1mm e\discretionary{f-}{f}{ff}e \par
711\hsize 20mm e\discretionary{f-}{f}{ff}e \par
712\smallcaps
713\hsize  1mm vereffenen \par
714\hsize  1mm effe \par
715\hsize  1mm e\discretionary{f-}{f}{ff}e \par
716\hsize 20mm e\discretionary{f-}{f}{ff}e \par
717\stopbuffer
718
719\typebuffer
720
721\blank
722\startcolumns[n=6]
723    \indenting[no]
724    \maincolor
725    \getbuffer
726\stopcolumns
727\blank
728
729In base mode such things are handled by the \TEX\ engine itself and it can deal
730with pretty complex cases. In node mode we use a simplification which in practice
731suffices. We will come back to this in \in {section} [ligatures:hyphenation].
732
733\stopsection
734
735\startsection[title=Efficiency]
736
737The efficiency of the mechanisms described here depends on several factors. It
738will be clear that the larger the font, the more time it will take to load it.
739But what is large? Most \CJK\ fonts are pretty large but also rather simple. A
740font like Zapfino on the other hand covers only latin but comes with many
741alternative shapes and a large set of rules. The Husayni font focusses on Arabic,
742which in itself has not that large an alphabet, but being an advanced script
743font, it has a lot of features and definitely a lot of rules.
744
745In terms of processing it's safe to say that Latin is of average complexity. At
746most you will get some substitutions, like regular numerals being replaced by
747oldstyles, or ligature building, which involves a bit of analysis, and some
748kerning at the end. In base mode the substitutions have no overhead, simply
749because the character table already has references to the substituents and the
750replacement already takes place when defining the font. There ligature building
751and kerning are also fast because of the limited amount of lookups that also are
752already kept with the characters. In node mode however, the lists have to be
753parsed and tables have to be consulted so even Latin processing has some
754overhead: each glyph node is consulted and analyzed (either or not in its
755context), often multiple times. However, the code is rather optimized and we use
756caching of already analyzed data when possible.
757
758A \CJK\ script is somewhat more complex on the one hand, but pretty simple on the
759other. Instead of font based kerning, we need to prevent or encourage breaks
760between certain characters. This information is not in the font and is processed
761otherwise but it does cost some time. The font part however is largely idle as
762there are no features to be applied. Even better, because the glyphs are large
763and the information density is high, the processing time per page is not much
764different from Latin. Base mode is good enough for most \CJK.
765
766The Arabic script is another matter. There we definitely go beyond what base mode
767offers so we always end up in node mode. Also, because there is some analysis
768involved, quite some substitutions and in the end also positioning, these are the
769least efficient fonts in terms of processing time. Of course the fact that we mix
770directions also plays a role. If in the Husayni font you enable 30 features with
771an average of 5 rules per feature, a 300 character paragraph will take 45.000
772actions. \footnote {For a modern machine this amount is no real issue, but as
773each action involves function calls and possibly some garbage collection there
774is some price to pay.} When multiple fonts are combined in a paragraph there will
775be more sweeps over the list and of course the replacements also have to happen.
776
777In a time when the average photo camera produces megabyte pictures it makes no
778sense to whine about the size of a font file. On the other hand as each font
779eventually ends up in memory as a \LUA\ table, it makes sense to optimize that
780bit. This is why fonts are converted into a more efficient intermediate table
781that is cached on disk. This makes loading a font quite fast and due to shared
782tables memory usage rather efficient. Of course a scaled instance has to be
783generated too, but that is acceptable. To some extent loading and defining a font
784also depends on the way the macro package is set up.
785
786When comparing \LUATEX\ with for instance \PDFTEX\ or \XETEX\ you need to take
787into account that in \CONTEXT\ \MKIV\ we tend to use \OPENTYPE\ fonts only so
788there are less fonts loaded than in a more traditional setup. In \CONTEXT\
789startup time of \MKIV\ is less than \MKII\ although overall processing time is
790slower, which is due to \UNICODE\ being used and more functionality being
791provided. On the other hand, immediate \METAPOST\ processing and more clever
792multipass handling wins back time. The impact of fonts on processing time in a
793regular document is therefore not that impressive. In practice a \MKIV\ run can
794be faster than a \MKII\ run, especially when \METAPOST\ is used.
795
796In \CONTEXT\ processing of node lists with respect to fonts is only one of the
797many manipulations of such lists and by now fonts are not really the bottleneck.
798The more not font related features users demand and enable, the less the relative
799impact of font processing becomes.
800
801Also, there are some advanced typographic extras that \LUATEX\ offers, like
802protrusion (think of hanging punctuation) and hz optimization (glyph scaling) and
803these slow down processing quite a lot, and they are not taking place at the
804\LUA\ end at all, but this might change in \MKIV. And, of course, typesetting
805involves more than fonts and other aspects can be way more demanding.
806
807\stopsection
808
809\stopchapter
810
811\stopcomponent
812
813% oldstyle not in math (old school tex)
814% funny tex ligatures
815% features=yes
816% analysis
817% mode=none (tt)
818