1
2
3\startcomponent cldmacros
4
5
6
7
8
9\environment cldenvironment
10
11\startchapter[title=Font goodies]
12
13\startsection[title=Introduction]
14
15One of the interesting aspects of \TEX\ is that it provides control over fonts
16and \LUATEX\ provides quite some. In \CONTEXT\ we support basic functionality,
17like \OPENTYPE\ features, as well as some extra functionality. We also have a
18mechanism for making virtual fonts which is mostly used for the transition from
19\TYPEONE\ math fonts to \OPENTYPE\ math fonts. Instead of hard coding specific
20details in the core \LUA\ code, we use so called \LUA\ Font Goodies to control
21them. These goodies are collected in tables and live in files. When a font is
22loaded, one or more such goodie files can be loaded alongside.
23
24In the following typescript we load a goodies file that defines a virtual Lucida
25math font. The goodie file is loaded immediately and some information in the
26table is turned into a form that permits access later on: the virtual font id
27\type {lucidamath} that is used as part of the font specification.
28
29\starttyping
30\starttypescript [math] [lucida]
31 \loadfontgoodies[lucidamath]
32 \definefontsynonym[MathRoman][lucidamath@lucidamath]
33\stoptypescript
34\stoptyping
35
36Not all information is to be used directly. Some can be accessed when needed. In
37the following case the file \type {dingbats.lfg} gets loaded (only once) when the
38font is actually used. In that file, there is information that is used by the
39\type {unicoding} feature.
40
41\starttyping
42\definefontfeature
43 [dingbats]
44 [mode=base,
45 goodies=dingbats,
46 unicoding=yes]
47
48\definefont[dingbats][file:dingbats][features=dingbats]
49\stoptyping
50
51In the following sections some aspects of goodies are discussed. We dont go into
52details of what these goodies are, but just stick to the \LUA\ side of the
53specification.
54
55\stopsection
56
57\startsection[title=Virtual math fonts]
58
59A virtual font is defined using the \type {virtuals} entry in the \type
60{mathematics} subtable. As \TYPEONE\ fonts are used, an additional table \type
61{mapfiles} is needed to specify the files that map filenames onto real files.
62
63\startsmalltyping
64return {
65 name = "pxmath",
66 version = "1.00",
67 comment = "Goodies that complement px math.",
68 author = "Hans Hagen",
69 copyright = "ConTeXt development team",
70 mathematics = {
71 mapfiles = {
72 "mkivpx.map",
73 },
74 virtuals = {
75 ["pxmath"] = {
76 { name = "texgyrepagellaregular.otf", features = "virtualmath", main = true },
77 { name = "rpxr.tfm", vector = "texmr" } ,
78 { name = "rpxmi.tfm", vector = "texmi", skewchar=0x7F },
79 { name = "rpxpplri.tfm", vector = "texit", skewchar=0x7F },
80 { name = "pxsy.tfm", vector = "texsy", skewchar=0x30, parameters = true } ,
81 { name = "pxex.tfm", vector = "texex", extension = true } ,
82 { name = "pxsya.tfm", vector = "texma" },
83 { name = "pxsyb.tfm", vector = "texmb" },
84 { name = "texgyrepagellabold.otf", vector = "texbf" } ,
85 { name = "texgyrepagellabolditalic.otf", vector = "texbi" } ,
86 { name = "lmsans10regular.otf", vector = "texss", optional=true },
87 { name = "lmmono10regular.otf", vector = "textt", optional=true },
88 },
89 }
90 }
91}
92\stopsmalltyping
93
94Here the \type {pxmath} virtual font is defined. A series of fonts is loaded and
95combined into one. The \type {vector} entry is used to tell the builder how to
96map the glyphs onto \UNICODE. Additional vectors can be defined, for instance:
97
98\starttyping
99fonts.encodings.math["mine"] = {
100 [0x1234] = 0x56,
101}
102\stoptyping
103
104Eventually these specifications wil be replaced by real \OPENTYPE\ fonts, but
105even then we will keep the virtual definitions around.
106
107\startsection[title=Math alternates]
108
109In addition to the official \type {ssty} feature for enforcing usage of script
110and scriptscript glyphs, some stylistic alternates can be present.
111
112\startsmalltyping
113return {
114 name = "xitsmath",
115 version = "1.00",
116 comment = "Goodies that complement xits (by Khaled Hosny).",
117 author = "Hans Hagen",
118 copyright = "ConTeXt development team",
119 mathematics = {
120 alternates = {
121 cal = {
122 feature = ss01,
123 value = 1,
124 comment = "Mathematical Calligraphic Alphabet"
125 },
126 greekssup = {
127 feature = ss02,
128 value = 1,
129 comment = "Mathematical Greek Sans Serif Alphabet"
130 },
131 greekssit = {
132 feature = ss03,
133 value = 1,
134 comment = "Mathematical Italic Sans Serif Digits"
135 },
136 monobfnum = {
137 feature = ss04,
138 value = 1,
139 comment = "Mathematical Bold Monospace Digits"
140 },
141 mathbbbf = {
142 feature = ss05,
143 value = 1,
144 comment = "Mathematical Bold DoubleStruck Alphabet"
145 },
146 mathbbit = {
147 feature = ss06,
148 value = 1,
149 comment = "Mathematical Italic DoubleStruck Alphabet"
150 },
151 mathbbbi = {
152 feature = ss07,
153 value = 1,
154 comment = "Mathematical Bold Italic DoubleStruck Alphabet"
155 },
156 upint = {
157 feature = ss08,
158 value = 1,
159 comment = "Upright Integrals"
160 },
161 }
162 }
163}
164\stopsmalltyping
165
166These can be activated (in math mode) with the \type {\mathalternate} command
167like:
168
169\starttyping
170$\mathalternate{cal}Z$
171\stoptyping
172
173\stopsection
174
175\startsection[title=Math parameters]
176
177Another goodie related to math is the overload of some parameters (part of the
178font itself) and variables (used in making virtual shapes).
179
180\startsmalltyping
181return {
182 name = "lmmath",
183 version = "1.00",
184 comment = "Goodies that complement latin modern math.",
185 author = "Hans Hagen",
186 copyright = "ConTeXt development team",
187 mathematics = {
188 mapfiles = {
189 "lmmath.map",
190 "lmrm.map",
191 "mkivbase.map",
192 },
193 virtuals = {
194 ["lmroman5math"] = five,
195 ["lmroman6math"] = six,
196 ["lmroman7math"] = seven,
197 ["lmroman8math"] = eight,
198 ["lmroman9math"] = nine,
199 ["lmroman10math"] = ten,
200 ["lmroman10boldmath"] = tenbold,
201 ["lmroman12math"] = twelve,
202 ["lmroman17math"] = seventeen,
203 },
204 variables = {
205 joinrelfactor = 3, default anyway
206 },
207 parameters = { test values
208 FactorA = 123.456,
209 FactorB = false,
210 FactorC = function(value,target,original) return 7.89 * target.factor end,
211 FactorD = "Hi There!",
212 },
213 }
214}
215\stopsmalltyping
216
217In this example you see several virtuals defined which is due to the fact that
218Latin Modern has design sizes. The values (like \type {twelve} are tables defined
219before the return happens and are not shown here. The variables are rather
220\CONTEXT\ specific, and the parameters are those that come with regular
221\OPENTYPE\ math fonts (so the example names are invalid).
222
223In the following example we show two wasy to change parameters. In this case we
224have a regular \OPENTYPE\ math font. First we install a patch to the font itself.
225That change will be cached. We could also have changed that parameter using the
226goodies table. The first method is the oldest.
227
228\startsmalltyping
229local patches = fonts.handlers.otf.enhancers.patches
230
231local function patch(data,filename,threshold)
232 local m = data.metadata.math
233 if m then
234 local d = m.DisplayOperatorMinHeight or 0
235 if d < threshold then
236 patches.report("DisplayOperatorMinHeight(
237 m.DisplayOperatorMinHeight = threshold
238 end
239 end
240end
241
242patches.register(
243 "after",
244 "check math parameters",
245 "asana",
246 function(data,filename)
247 patch(data,filename,1350)
248 end
249)
250
251local function less(value,target,original)
252 return 0.25 * value
253end
254
255return {
256 name = "asanamath",
257 version = "1.00",
258 comment = "Goodies that complement asana.",
259 author = "Hans Hagen",
260 copyright = "ConTeXt development team",
261 mathematics = {
262 parameters = {
263 StackBottomDisplayStyleShiftDown = less,
264 StackBottomShiftDown = less,
265 StackDisplayStyleGapMin = less,
266 StackGapMin = less,
267 StackTopDisplayStyleShiftUp = less,
268 StackTopShiftUp = less,
269 StretchStackBottomShiftDown = less,
270 StretchStackGapAboveMin = less,
271 StretchStackGapBelowMin = less,
272 StretchStackTopShiftUp = less,
273 }
274 }
275}
276\stopsmalltyping
277
278We use a function so that the scaling is taken into account as the values passed
279are those resulting from the scaling of the font to the requested size.
280
281\stopsection
282
283\startsection[title=Unicoding]
284
285We still have to deal with existing \TYPEONE\ fonts, and some of them have an
286encoding that is hard to map onto \UNICODE\ without additional information. The
287following goodie does that. The keys in the \type {unicodes} table are the glyph
288names. Keep in mind that this only works with simple fonts. The \CONTEXT\ code
289takes care of kerns but thats about it.
290
291\startsmalltyping
292return {
293 name = "dingbats",
294 version = "1.00",
295 comment = "Goodies that complement dingbats (funny names).",
296 author = "Hans Hagen",
297 copyright = "ConTeXt development team",
298 remapping = {
299 tounicode = true,
300 unicodes = {
301 a1 = 0x2701,
302 a10 = 0x2721,
303 a100 = 0x275E,
304 a101 = 0x2761,
305 .............
306 a98 = 0x275C,
307 a99 = 0x275D,
308 },
309 },
310}
311\stopsmalltyping
312
313The \type {tounicode} option makes sure that additional information ends ip in
314the output so that cutandpaste becomes more trustworthy.
315
316\stopsection
317
318\startsection[title=Typescripts]
319
320Some font collections, like antykwa, come with so many variants that defining
321them all in typescripts becomes somewhat of a nuisance. While a regular font has
322a typescript of a few lines, antykwa needs way more lines. This is why we provide
323a nother way as well, using goodies.
324
325\startsmalltyping
326return {
327 name = "antykwapoltawskiego",
328 version = "1.00",
329 comment = "Goodies that complement Antykwa Poltawskiego",
330 author = "Hans Mojca",
331 copyright = "ConTeXt development team",
332 files = {
333 name = "antykwapoltawskiego", shared
334 list = {
335 ["AntPoltLtCondRegular.otf"] = {
336 name = "antykwapoltawskiego",
337 weight = "light",
338 style = "regular",
339 width = "condensed",
340 },
341 ["AntPoltLtCondItalic.otf"] = {
342 weight = "light",
343 style = "italic",
344 width = "condensed",
345 },
346 ["AntPoltCondRegular.otf"] = {
347 weight = "normal",
348 style = "regular",
349 width = "condensed",
350 },
351
352 .......
353
354
355 ["AntPoltExpdBoldItalic.otf"] = {
356 weight = "bold",
357 style = "italic",
358 width = "expanded",
359 },
360 },
361 },
362 typefaces = { for Mojca (experiment, names might change)
363 ["antykwapoltawskiegolight"] = {
364 shortcut = "rm",
365 shape = "serif",
366 fontname = "antykwapoltawskiego",
367 normalweight = "light",
368 boldweight = "medium",
369 width = "normal",
370 size = "default",
371 features = "default",
372 },
373
374 .......
375
376 },
377}
378\stopsmalltyping
379
380This is a typical example of when a goodies file is loaded directly:
381
382\starttyping
383\loadfontgoodies[antykwapoltawskiego]
384\stoptyping
385
386A bodyfont is now defined by choosing from the defined combinations:
387
388\starttyping
389\definetypeface
390 [name=mojcasfavourite,
391 preset=antykwapoltawskiego,
392 normalweight=light,
393 boldweight=bold,
394 width=expanded]
395
396\setupbodyfont
397 [mojcasfavourite]
398\stoptyping
399
400This mechanism is a follow up on a discussion at a \CONTEXT\ conference, still
401somewhat experimental, and a playground for Mojca.
402
403\stopsection
404
405\startsection[title=Font strategies]
406
407This goodie is closely related to the Oriental \TEX\ project where a dedicated
408paragraph optimizer can be used. A rather advanced font is used (husayni) and its
409associated goodie file is rather extensive. It defines stylistic features,
410implements a couple of feature sets, provides colorschemes and most of all,
411defines some strategies for making paragraphs look better. Some of the goodie
412file is shown here.
413
414\startsmalltyping
415local yes = "yes"
416
417local basics = {
418 analyze = yes,
419 mode = "node",
420 language = "dflt",
421 script = "arab",
422}
423
424local analysis = {
425 ccmp = yes,
426 init = yes, medi = yes, fina = yes,
427}
428
429local regular = {
430 rlig = yes, calt = yes, salt = yes, anum = yes,
431 ss01 = yes, ss03 = yes, ss07 = yes, ss10 = yes, ss12 = yes, ss15 = yes, ss16 = yes,
432 ss19 = yes, ss24 = yes, ss25 = yes, ss26 = yes, ss27 = yes, ss31 = yes, ss34 = yes,
433 ss35 = yes, ss36 = yes, ss37 = yes, ss38 = yes, ss41 = yes, ss42 = yes, ss43 = yes,
434 js16 = yes,
435}
436
437local positioning = {
438 kern = yes, curs = yes, mark = yes, mkmk = yes,
439}
440
441local minimalstretching = {
442 js11 = yes, js03 = yes,
443}
444
445local mediumstretching = {
446 js12=yes, js05=yes,
447}
448
449local maximalstretching= {
450 js13 = yes, js05 = yes, js09 = yes,
451}
452
453local wideall = {
454 js11 = yes, js12 = yes, js13 = yes, js05 = yes, js09 = yes,
455}
456
457local shrink = {
458 flts = yes, js17 = yes, ss05 = yes, ss11 = yes, ss06 = yes, ss09 = yes,
459}
460
461local default = {
462 basics, analysis, regular, positioning, xxxx = yes, yyyy = 2,
463}
464
465return {
466 name = "husayni",
467 version = "1.00",
468 comment = "Goodies that complement the Husayni font by Idris Samawi Hamid.",
469 author = "Idris Samawi Hamid and Hans Hagen",
470 featuresets = { here we dont have references to featuresets
471 default = {
472 default,
473 },
474 minimalstretching = {
475 default,
476 js11 = yes, js03 = yes,
477 },
478 mediumstretching = {
479 default,
480 js12=yes, js05=yes,
481 },
482 maximalstretching= {
483 default,
484 js13 = yes, js05 = yes, js09 = yes,
485 },
486 wideall = {
487 default,
488 js11 = yes, js12 = yes, js13 = yes, js05 = yes, js09 = yes,
489 },
490 shrink = {
491 default,
492 flts = yes, js17 = yes, ss05 = yes, ss11 = yes, ss06 = yes, ss09 = yes,
493 },
494 },
495 solutions = { here we have references to featuresets, so we use strings!
496 experimental = {
497 less = {
498 "shrink"
499 },
500 more = {
501 "minimalstretching",
502 "mediumstretching",
503 "maximalstretching",
504 "wideall"
505 },
506 },
507 },
508 stylistics = {
509 ......
510 ss03 = "level1 stack over Jiim, initial entry only",
511 ss04 = "level1 stack over Jiim, initialmedial entry",
512 ......
513 ss54 = "chopped finals",
514 ss55 = "idghamtanwin",
515 ......
516 js11 = "level1 stretching",
517 js12 = "level2 stretching",
518 ......
519 js21 = "Haa.finalalt2",
520 },
521 colorschemes = {
522 default = {
523 [1] = {
524 "Onedotabove", "Onedotbelow", ...
525 },
526 [2] = {
527 "Fathah", "Dammah", "Kasrah", ...
528 },
529 [3] = {
530 "Ttaa.waqf", "SsLY.waqf", "QLY.waqf", ...
531 },
532 [4] = {
533 "ZeroArabic.ayah", "OneArabic.ayah", "TwoArabic.ayah", ...
534 },
535 [5] = {
536 "Ayah", "Ayah.alt1", "Ayah.alt2", ...
537 }
538 }
539 }
540}
541\stopmalltyping
542
543Discussion of these goodies is beyond this document and happens elsewhere.
544
545\stopsection
546
547\startsection[title=Composition]
548
549The \type {compose} features extends a font with additional (virtual) shapes.
550This is mostly used with \TYPEONE\ fonts that lack support for eastern european
551languages. The type {compositions} subtable is used to control placement of
552accents. This can be done per font.
553
554\startmalltyping
555local defaultunits = 193 30
556
557 local compose = {
558 DY = defaultunits,
559 [0x010C] = { DY = defaultunits }, Ccaron
560 [0x02C7] = { DY = defaultunits }, textcaron
561 }
562
563 fractions relative to delta(Xheight xheight)
564
565local defaultfraction = 0.85
566
567local compose = {
568 DY = defaultfraction, uppercase compensation
569}
570
571return {
572 name = "lucidaone",
573 version = "1.00",
574 comment = "Goodies that complement lucida.",
575 author = "Hans and Mojca",
576 copyright = "ConTeXt development team",
577 compositions = {
578 ["lbr"] = compose,
579 ["lbi"] = compose,
580 ["lbd"] = compose,
581 ["lbdi"] = compose,
582 }
583}
584\stopsmalltyping
585
586\stopsection
587
588\startsection[title=Postprocessing]
589
590You can hook postprocessors into the scaler. Future versions might provide more
591control over where this happens.
592
593\startsmalltyping
594local function statistics(tfmdata)
595 commands.showfontparameters(tfmdata)
596end
597
598local function squeeze(tfmdata)
599 for k, v in next, tfmdata.characters do
600 v.height = 0.75 * (v.height or 0)
601 v.depth = 0.75 * (v.depth or 0)
602 end
603end
604
605return {
606 name = "demo",
607 version = "1.00",
608 comment = "An example of goodies.",
609 author = "Hans Hagen",
610 postprocessors = {
611 statistics = statistics,
612 squeeze = squeeze,
613 },
614}
615\stopsmalltyping
616
617\stopsection
618
619\stopchapter
620
621\stopcomponent
622 |