mk-fallback.tex /size: 6453 b    last modification: 2023-12-21 09:43
1% language=us
2
3\startcomponent mk-fallback
4
5\environment mk-environment
6
7\chapter {Virtual Reality}
8
9When a font lacks glyphs we can add new ones by making the font
10virtual. A virtual font has virtual glyphs: instead of a reference
11to a slot in the current font, such a glyph refers to a slot in
12another font, or it combines several glyphs into one, or it just
13contains code that ends up in the result (for instance a sequence
14of \PDF\ commands that describes the shape). For \TEX\ a character
15and its dimensions are what matters and what ends up in the result
16is mostly a matter for the backend. In \LUATEX\ the backend is
17integrated but even then during the typesetting process only the
18characteristics of a glyph are used and not the shape.
19
20In \CONTEXT\ we have a feature called \quote {compose} which
21extends the font with extra characters and constructs its
22representation from those of other characters.
23
24\starttyping
25\definefontfeature
26  [composes]
27  [kern=yes,ligatures=yes,compose=yes]
28\stoptyping
29
30When this feature is applied, \CONTEXT\ will try to fill in the
31gaps in the \UNICODE\ vector of the font based on for instance
32(de)composition information. Of course this has some limitations.
33For instance \OPENTYPE\ fonts can ships with features, like
34smallcaps. Currently we ignore this property when we add composed
35characters. Technically it is no big deal to add variants but we
36simply didn't do it yet at the time of this writing. After all,
37such fallbacks can best be avoided by using proper fonts.
38
39Our \CONTEXT\ \MKIV\ wishlist mentions a mechanism for combining
40fonts into one font. For this we can use virtual fonts and the
41machinery for that is in available in \LUA\ code. However such a
42mechanism will be used for more drastic completion of a font than
43the compose feature. For instance, often Chinese fonts lack proper
44Latin glyphs and vise versa. But when we combine such fonts we
45really do want to keep \OPENTYPE\ features working and so we
46cannot use virtual fonts (unless we start merging features which
47can become really messy and runtime consuming).
48
49There is a relative simple solution using real fonts that kind of
50behave like virtual ones: virtual real fonts. The trick is in the
51fact that \TEX\ permits access to characters not present in the
52font. Say that we have
53
54\starttyping
55<char 123><char 124><char 125>
56\stoptyping
57
58and that slot~124 has no glyph. In that case \TEX\ just inserts a
59glyph node with a reference to the current font and this
60character. Of course, when we let \TEX\ carry on, at some point it
61will need glyph properties like the width, height and/or depth.
62And in the backend, when writing the result to file, \TEX\ wants
63to insert the glyph data in the file. In both cases we end up with
64a message in the log file and a result file with missing data.
65
66In \CONTEXT\ \MKIV\ we intercept the node lists at several points
67and one of those is directly after the construction. So let's
68consider the previous example again.
69
70\starttyping
71<font 32 char 123><font 32 char 124><font 32 char 125>
72\stoptyping
73
74Because the font has no character 124 we need a way to substitute
75it with another character. All we have to do is to change the font
76identifier~32 into one that makes sense. Such a replacement loop
77is kind of trivial.
78
79\starttyping
80for n in traverse_id(glyph,head) do
81    local v = vectors[n.font]
82    if v then
83        local id = v[n.char]
84        if id then
85            n.font = id
86        end
87    end
88end
89\stoptyping
90
91We have a table (\type{vectors}) that can have a subtable (\type
92{v}) for font with id (\type {n.font}) in which there can be a
93reference from the current character (\type {n.char}) to another
94font (\type {id}) that we use to replace the font reference (\type
95{n.font}).
96
97Filling the table is relatively easy but an explanation is beyond
98this chapter. We only show the high level interface, one that
99certainly will evolve.
100
101\starttyping
102\definefontfallback
103  [SerifFallback]
104  [Mono]
105  [0x000-0x3FF]
106  [check=yes,force=no]
107\stoptyping
108
109This command registers an entry in the \type {SerifFallback}
110namespace. There can be multiple replacement in row (by just using
111more of these commands), but here we have only one. The range
1120x000--0x3FF will be checked and if the main font lacks a glyph in
113that range, it will be taken from the font with the symbolic name
114\type {Mono}. That name will be resolved when the fallback is
115associated with a font. The \type {check} option tells the
116machinery that we need to check for existence and because we don't
117\type {force}, we will only replace missing glyphs. There is also
118an \type {rscale} option, that permits relative scaling of the
119fallback font to the main font, something that may be needed when
120fonts come from different sources.
121
122\starttyping
123\definefontsynonym
124  [SerifPlus]
125  [Serif]
126  [fallbacks=SerifFallback]
127\stoptyping
128
129This command associates a fallback with a font. There is always a
130parent font and that is the font that triggers the checking of the
131node list.
132
133\starttyping
134\definefont [MySerif] [SerifPlus at 10pt]
135\stoptyping
136
137Here we defines a font called \type {\MySerif} that refers to a
138symbolic name \type {SerifPlus} which in turn refers to the
139current \type {Serif} font (these symbolic names are resolved in
140typescripts, one of the building blocks of \CONTEXT s font
141system). The mentioned fallbacks will be initialized when the font
142is defined. This examples demonstrates that there is a clean
143separation between font definitions and fallbacks. This makes it
144possible to share fallback definitions.
145
146So, let's summarize what happens:
147
148\startitemize[packed]
149\item a font is defined in the normal way but has falbacks
150\item the associated fallback fonts are defined too
151\item the main font gets a table with fallback id's
152\item the main font is used in the document stream
153\item the node list is intercepted and parsed for this font
154\item references to fallback fonts take care of missing glyphs
155\stopitemize
156
157We end with an example.
158
159\startbuffer
160\definefontfallback [Demo] [Mono] [0x30-0x39] [force=yes]
161\definefontsynonym  [DemoSerif] [Serif] [fallbacks=Demo]
162
163\definefont [MyDemoSerif] [DemoSerif at 20pt]
164
165\MyDemoSerif Here the digits, like 13579, are replaced.
166\stopbuffer
167
168\typebuffer
169
170\start \blank[3*medium] \getbuffer \blank[3*medium] \stop
171
172Beware: the fallback definitions are global, but this is hardly a
173problem because normal such trickery is taking place at the document
174level.
175
176\stopcomponent
177