onandon-modern.tex /size: 41 Kb    last modification: 2023-12-21 09:43
1% language=us
2
3% 284 instances, 234 shared in backend, 126 common vectors, 108 common hashes, load time 1.343 seconds
4
5%setupversion[alternative=concept,text={not corrected yet}]
6\setupversion[alternative=file,text={not corrected yet}]
7
8\definebodyfontenvironment[24pt]
9
10\usemodule[fonts-effects]
11
12\startcomponent onandon-modern
13
14\environment onandon-environment
15
16\startchapter[title={Modern Latin}]
17
18\startsection[title={Introduction}]
19
20In \CONTEXT, already in \MKII, we have a feature tagged \quote {effects} that can
21be used to render a font in outline or bolder versions. It uses some low level
22\PDF\ directives to accomplish this and it works quite well. When a user on the
23\CONTEXT\ list asked if we could also provide it as a font feature in the
24repertoire of additional features in \CONTEXT, I was a bit reluctant to provide
25that because it operates at another level than the glyph stream. Also, such a
26feature can be abused and result in a bad looking document. However, by adding a
27few simple options to the \LUATEX\ engine such a feature could actually be
28achieved rather easy: it was trivial to implement given that we can influence
29font handling at the \LUA\ end. In retrospect extended and pseudo slanted fonts
30could be done this way too but there we have some historic ballast. Also, the
31backend now handles such transformations very efficient because they are combined
32with font scaling. Anyway, by adding this feature in spite of possible
33objections, I could do some more advanced experiments.
34
35In the following pages I will demonstrate how we support effects as a feature in
36\CONTEXT. Instead of simply applying some magic \PDF\ text operators in the
37backend a more integrated approach is used. The difference with the normal effect
38mechanism is that where the one described here is bound to a font instance while
39the normal mechanism operates on the glyph stream.
40
41\stopsection
42
43\startsection[title={The basics}]
44
45\definefontsynonym[DemoSerif][file:lmroman10-regular]
46
47Let's start with a basic boldening example. First we demonstrate a regular Latin
48Modern sample (using \type {ward.tex}):
49
50\startnarrower
51    \definedfont[DemoSerif*default]
52    \samplefile{ward}
53\stopnarrower
54
55This font looks rather thin (light). Next we define an effect or \type {0.2} and
56typeset the same sample:
57
58\startbuffer
59\definefontfeature
60  [effect-1]
61  [effect=.2]
62\stopbuffer
63
64\typebuffer \getbuffer
65
66\startnarrower
67    \definedfont[DemoSerif*default,effect-1]
68    \samplefile{ward}
69\stopnarrower
70
71This simple call gives reasonable default results. But you can have more control
72than this. The previous examples use the following properties:
73
74{\definedfont[DemoSerif*default,effect-1] \showfonteffect}
75
76\startbuffer
77\definefontfeature
78  [effect-2]
79  [effect={width=.3}]
80\stopbuffer
81
82\typebuffer \getbuffer
83
84\startnarrower
85    \definedfont[DemoSerif*default,effect-2]
86    \samplefile{ward}
87\stopnarrower
88
89This time we use:
90
91{\definedfont[DemoSerif*default,effect-2] \showfonteffect}
92
93\startbuffer
94\definefontfeature
95  [effect-3]
96  [effect={width=.3,delta=0.4}]
97\stopbuffer
98
99\typebuffer \getbuffer
100
101\startnarrower
102    \showfontkerns
103    \definedfont[DemoSerif*default,effect-3]
104    \samplefile{ward}
105\stopnarrower
106
107We have now tweaked one more property and show the fontkerns in order to see what
108happens with them:
109
110{\definedfont[DemoSerif*default,effect-3] \showfonteffect}
111
112\startbuffer
113\definefontfeature
114  [effect-4]
115  [effect={width=.3,delta=0.4,factor=0.3}]
116\stopbuffer
117
118\typebuffer \getbuffer
119
120\startnarrower
121    \showfontkerns
122    \definedfont[DemoSerif*default,effect-4]
123    \samplefile{ward}
124\stopnarrower
125
126An additional parameter \type {factor} will influence the way (for instance)
127kerns get affected:
128
129{\definedfont[DemoSerif*effect-4] \showfonteffect}
130
131\stopsection
132
133\startsection[title=Outlines]
134
135There are four effects. Normally a font is rendered with effect \type {inner}.
136The \type {outer} effect just draws the outlines while \type {both} gives a
137rather fat result. The \type {hidden} effect hides the text.
138
139\startbuffer
140\definefontfeature
141  [effect-5]
142  [effect={width=0.2,delta=0.4,factor=0.3,effect=inner}]
143\stopbuffer
144
145\typebuffer \getbuffer
146
147\startnarrower
148    \showfontkerns
149    \definedfont[DemoSerif*default,effect-5]
150    \samplefile{ward}
151\stopnarrower
152
153An inner effect is rather useless unless you want to use the other properties of
154this mechanism.
155
156\startbuffer
157\definefontfeature
158  [effect-6]
159  [effect={width=.2,delta=0.4,factor=0.3,effect=outer}]
160\stopbuffer
161
162\typebuffer \getbuffer
163
164\startnarrower
165    \showfontkerns
166    \definedfont[DemoSerif*default,effect-6]
167    \samplefile{ward}
168\stopnarrower
169
170\startbuffer
171\definefontfeature
172  [effect-7]
173  [effect={width=.2,delta=0.4,factor=0.3,effect=both}]
174\stopbuffer
175
176\typebuffer \getbuffer
177
178\startnarrower
179    \showfontkerns
180    \definedfont[DemoSerif*default,effect-7]
181    \samplefile{ward}
182\stopnarrower
183
184\startbuffer
185\definefontfeature
186  [effect-8]
187  [effect={width=.2,delta=0.4,factor=0.3,effect=hidden},
188   boundingbox=yes] % to show something
189\stopbuffer
190
191\typebuffer \getbuffer
192
193We also show the boundingboxes of the glyphs here so that you can see what you're
194missing. Actually this text is still there and you can select it in the viewer.
195
196\startnarrower
197    \showfontkerns
198    \showglyphs
199    \definedfont[DemoSerif*default,effect-8]
200    \samplefile{ward}
201\stopnarrower
202
203\stopsection
204
205\startsection[title=The logic]
206
207In order to support this I had to make some choices. The calculations involved
208are best explained in terms of \CONTEXT\ font machinery.
209
210\startformula
211    \Delta _{\text{wd}}  = \text{effect}   _{\text{wdelta}}
212                    \times \text{parameter}_{\text{hfactor}}
213                    \times \text{effect}   _{\text{width}}
214                    \times 100
215\stopformula
216
217\startformula
218    \Delta _{\text{ht}}  = \text{effect}   _{\text{hdelta}}
219                    \times \text{parameter}_{\text{vfactor}}
220                    \times \text{effect}   _{\text{width}}
221                    \times 100
222\stopformula
223
224\startformula
225    \Delta _{\text{dp}}  = \text{effect}   _{\text{ddelta}}
226                    \times \text{parameter}_{\text{vfactor}}
227                    \times \text{effect}   _{\text{width}}
228                    \times 100
229\stopformula
230
231The factors in the parameter namespace are adapted according to:
232
233\startformula
234    \Delta _{\text{factor}} = \text{effect}    _{\text{factor}}
235                       \times \text{parameters}_{\text{factor}}
236\stopformula
237
238\startformula
239    \Delta _{\text{hfactor}} = \text{effect}    _{\text{hfactor}}
240                        \times \text{parameters}_{\text{hfactor}}
241\stopformula
242
243\startformula
244    \Delta _{\text{vfactor}} = \text{effect}    _{\text{vfactor}}
245                        \times \text{parameters}_{\text{vfactor}}
246\stopformula
247
248The horizontal and vertical scaling factors default to the normal factor that
249defaults to zero so by default we have no additional scaling of for instance
250kerns. The width (wd), height (ht) and depth (dp) of a glyph are adapted in
251relation to the line width. A glyph is shifted in its bounding box by half the
252width correction. The delta defaults to one.
253
254\stopsection
255
256\startsection[title=About features]
257
258This kind of boldening has limitations especially because some fonts use
259positioning features that closely relate to the visual font properties. Let's
260give some examples. The most common positioning is kerning. Take for instance
261these shapes:
262
263\startlinecorrection
264\startMPcode
265    def SampleShapes(expr dx, offset, pw, k) =
266        picture p ; p := image (
267            draw               fullcircle scaled 1cm ;
268            draw               fullsquare scaled 1cm  shifted (dx+k,0) ;
269            draw point 8   of (fullcircle scaled 1cm)                  withcolor white ;
270            draw point 3.5 of (fullsquare scaled 1cm) shifted (dx+k,0) withcolor white ;
271        ) shifted (offset,0) ;
272        draw p withpen pencircle scaled pw ;
273        draw boundingbox p withcolor white ;
274    enddef ;
275    SampleShapes(15mm,  0mm,1mm,0mm) ;
276    SampleShapes(15mm, 40mm,2mm,0mm) ;
277    SampleShapes(17mm, 80mm,2mm,0mm) ;
278\stopMPcode
279\stoplinecorrection
280
281The first one is that we start with. The circle and square have a line width of
282one unit and a distance (kern) of five units. The second pair has a line width of
283two units and the same distance while the third pair has a distance of seven
284units. So, in the last case we have just increased the kern with a value relative
285to the increase of line width.
286
287\startlinecorrection
288\startMPcode
289    SampleShapes(15mm,  0mm,1mm,0mm) ;
290    SampleShapes(15mm, 40mm,2mm,2mm) ;
291    SampleShapes(17mm, 80mm,2mm,2mm) ;
292\stopMPcode
293\stoplinecorrection
294
295In this example we have done the same but we started with a distance of zero. You
296can consider this a kind of anchoring. This happens in for instance cursive
297scripts where entry and exit points are used to connect shapes. In a latin script
298you can think of a poor|-|mans attachment of a cedilla or ogonek. But what to do
299with for instance an accent on top of a character? In that case we could do the
300same as with kerning. However, when we mix styles we would like to have a
301consistent height so maybe there scaling is not a good idea. This is why we can
302set the factors and deltas explictly for vertical and horizontal movements.
303However, this will only work well when a font is consistent in how it applies
304these movements. In this case, if could recognize cursive anchoring (the last
305pair in the example) we could compensate for it.
306
307\startMPinclusions
308    def SampleShapes(expr dx, offset, pw, k) =
309        picture p ; p := image (
310            draw               fullcircle scaled 1cm ;
311            draw               fullsquare scaled 1cm  shifted (dx+k,0) ;
312            draw point 8   of (fullcircle scaled 1cm)                  withcolor white ;
313            draw point 3.5 of (fullsquare scaled 1cm) shifted (dx+k,0) withcolor white ;
314        ) shifted (offset,0) ;
315        draw p withpen pencircle scaled pw ;
316        draw boundingbox p withcolor white ;
317    enddef ;
318\stopMPinclusions
319
320\startlinecorrection
321\startMPcode
322    SampleShapes(10mm,  0mm,1mm,0mm) ;
323    SampleShapes(10mm, 40mm,1mm,1mm) ;
324    SampleShapes(10mm, 80mm,2mm,0mm) ;
325    SampleShapes(10mm,120mm,2mm,2mm) ;
326\stopMPcode
327\stoplinecorrection
328
329So, an interesting extension to the positioning part of the font handler could be
330to influence all the scaling factors: anchors, cursives, single and pair wise
331positioning in both directions (so eight independent factors). Technically this
332is no big deal so I might give it a go when I have a need for it.
333
334\stopsection
335
336\startsection[title=Some (extreme) examples]
337
338The last decade buying a font has become a bit of a nightmare simply because you
339have to choose the weights that you need. It's the business model to not stick to
340four shapes in a few weights but offer a whole range and each of course costs
341money.
342
343Latin Modern is based on Computer Modern and is meant for high resolution rendering.
344The design of the font is such that you can create instances but in practice that
345isn't done. One property that let the font stand out is its bold which runs rather
346wide. However, how about cooking up a variant? For this we will use a series of
347definitions:
348
349\startbuffer
350\definefontfeature[effect-2-0-0]
351  [effect={width=0.2,delta=0}]
352\definefontfeature[effect-2-3-0]
353  [effect={width=0.2,delta=0.3}]
354\definefontfeature[effect-2-6-0]
355  [effect={width=0.2,delta=0.6}]
356\definefontfeature[effect-4-0-0]
357  [effect={width=0.4,delta=0}]
358\definefontfeature[effect-4-3-0]
359  [effect={width=0.4,delta=0.3}]
360\definefontfeature[effect-4-6-0]
361  [effect={width=0.4,delta=0.6}]
362\definefontfeature[effect-8-0-0]
363  [effect={width=0.8,delta=0}]
364\definefontfeature[effect-8-3-0]
365  [effect={width=0.8,delta=0.3}]
366\definefontfeature[effect-8-6-0]
367  [effect={width=0.8,delta=0.6}]
368\definefontfeature[effect-8-6-2]
369  [effect={width=0.8,delta=0.6,factor=0.2}]
370\definefontfeature[effect-8-6-4]
371  [effect={width=0.8,delta=0.6,factor=0.4}]
372\stopbuffer
373
374\typebuffer \getbuffer
375
376And a helper macro:
377
378\startbuffer
379\starttexdefinition ShowOneSample #1#2#3#4
380 %\testpage[5]
381 %\startsubsubsubject[title=\type{#1}]
382  \start
383    \definedfont[#2*#3 @ 10pt]
384    \setupinterlinespace
385    \startlinecorrection
386        \showglyphs \showfontkerns
387        \scale[sx=#4,sy=#4]{effective n\"ots}
388    \stoplinecorrection
389    \blank[samepage]
390    \dontcomplain
391    \showfontkerns
392    \margintext{\tt\txx\maincolor#1}
393    \samplefile{ward}
394    \par
395  \stop
396 %\stopsubsubsubject
397\stoptexdefinition
398\stopbuffer
399
400\typebuffer \getbuffer
401
402\starttexdefinition ShowSamples #1
403  \startsubsubject[title=#1]
404    \start
405        \ShowOneSample{no effect}                       {#1}{default}             {5}
406        \ShowOneSample{width=0.2\\delta=0}              {#1}{default,effect-2-0-0}{5}
407        \ShowOneSample{width=0.2\\delta=0.3}            {#1}{default,effect-2-3-0}{5}
408        \ShowOneSample{width=0.2\\delta=0.6}            {#1}{default,effect-2-6-0}{5}
409        \ShowOneSample{width=0.4\\delta=0}              {#1}{default,effect-4-0-0}{5}
410        \ShowOneSample{width=0.4\\delta=0.3}            {#1}{default,effect-4-3-0}{5}
411        \ShowOneSample{width=0.4\\delta=0.6}            {#1}{default,effect-4-6-0}{5}
412        \ShowOneSample{width=0.8\\delta=0}              {#1}{default,effect-8-0-0}{5}
413        \ShowOneSample{width=0.8\\delta=0.3}            {#1}{default,effect-8-3-0}{5}
414        \ShowOneSample{width=0.8\\delta=0.6}            {#1}{default,effect-8-6-0}{5}
415        \ShowOneSample{width=0.8\\delta=0.6\\factor=0.2}{#1}{default,effect-8-6-2}{5}
416        \ShowOneSample{width=0.8\\delta=0.6\\factor=0.4}{#1}{default,effect-8-6-4}{5}
417    \stop
418  \stopsubsubject
419\stoptexdefinition
420
421We show some extremes, using the font used in this document. so don't complain
422about beauty here.
423
424\texdefinition{ShowSamples}{Serif}
425\texdefinition{ShowSamples}{SerifBold}
426\texdefinition{ShowSamples}{SerifItalic}
427\texdefinition{ShowSamples}{SerifBoldItalic}
428\texdefinition{ShowSamples}{Sans}
429
430\start
431    \setupalign[flushleft,broad,nothyphenated,verytolerant]
432    \texdefinition{ShowSamples}{Mono}
433\stop
434
435\stopsection
436
437\startsection[title=Pitfall]
438
439The quality of the result depends on how the font is made. For instance,
440ligatures can be whole shapes, replaced glyphs and|/|or repositioned
441glyphs, or whatever the designer thinks reasonable. In \in {figure}
442[fig:ligature-effects-mess] this is demonstrated. We use the following
443feature sets:
444
445\startbuffer
446\definefontfeature
447  [demo-1]
448  [default]
449  [hlig=yes]
450
451\definefontfeature
452  [demo-2]
453  [demo-1]
454  [effect=0.5]
455\stopbuffer
456
457\typebuffer \getbuffer
458
459\startplacefigure[title={The effects on ligatures.},reference=fig:ligature-effects-mess]
460    \startcombination[1*3]
461        { \scale [scale=5000] {
462            \definedfont[texgyrepagellaregular*demo-1]fist effe
463            \par
464            \definedfont[texgyrepagellaregular*demo-2]fist effe
465        } } {
466            texgyre pagella regular
467        } { \scale [scale=5000] {
468            \definedfont[cambria*demo-1]fist effe
469            \par
470            \definedfont[cambria*demo-2]fist effe
471        } } {
472            cambria
473        } { \scale [scale=5000] {
474            \definedfont[ebgaramond12regular*demo-1]fist effe
475            \par
476            \definedfont[ebgaramond12regular*demo-2]fist effe
477        } } {
478            ebgaramond 12 regular
479        }
480    \stopcombination
481\stopplacefigure
482
483Normally the artifacts (as in the fi ligature in ebgaramond as of 2018) will go
484unnoticed at small sized. Also, when the user has a low res display, printer or
485when the publishers is one of those who print a scanned \PDF\ the reader might
486not notice it at all. Most readers don't even know what to look at.
487
488\stopsection
489
490\startsection[title=A modern Modern]
491
492So how can we make an effective set of Latin Modern that fits in todays look and
493feel. Of course this is a very subjective experiment but we've seen experiments
494with these fonts before (like these cm super collections). Here is an example of
495a typescript definition:
496
497\starttyping
498\starttypescriptcollection[modernlatin]
499
500  \definefontfeature[lm-rm-regular][effect={width=0.15,delta=1.00}]
501  \definefontfeature[lm-rm-bold]   [effect={width=0.30,delta=1.00}]
502  \definefontfeature[lm-ss-regular][effect={width=0.10,delta=1.00}]
503  \definefontfeature[lm-ss-bold]   [effect={width=0.20,delta=1.00}]
504  \definefontfeature[lm-tt-regular][effect={width=0.15,delta=1.00}]
505  \definefontfeature[lm-tt-bold]   [effect={width=0.30,delta=1.00}]
506  \definefontfeature[lm-mm-regular][effect={width=0.15,delta=1.00}]
507  \definefontfeature[lm-mm-bold]   [effect={width=0.30,delta=1.00}]
508
509  \starttypescript [serif] [modern-latin]
510    \definefontsynonym
511      [Serif] [file:lmroman10-regular]
512      [features={default,lm-rm-regular}]
513    \definefontsynonym
514      [SerifItalic] [file:lmroman10-italic]
515      [features={default,lm-rm-regular}]
516    \definefontsynonym
517      [SerifSlanted] [file:lmromanslant10-regular]
518      [features={default,lm-rm-regular}]
519    \definefontsynonym
520      [SerifBold] [file:lmroman10-regular]
521      [features={default,lm-rm-bold}]
522    \definefontsynonym
523      [SerifBoldItalic] [file:lmroman10-italic]
524      [features={default,lm-rm-bold}]
525    \definefontsynonym
526      [SerifBoldSlanted] [file:lmromanslant10-regular]
527      [features={default,lm-rm-bold}]
528  \stoptypescript
529
530  \starttypescript [sans] [modern-latin]
531    \definefontsynonym
532      [Sans] [file:lmsans10-regular]
533      [features={default,lm-ss-regular}]
534    \definefontsynonym
535      [SansItalic] [file:lmsans10-oblique]
536      [features={default,lm-ss-regular}]
537    \definefontsynonym
538      [SansSlanted] [file:lmsans10-oblique]
539      [features={default,lm-ss-regular}]
540    \definefontsynonym
541      [SansBold] [file:lmsans10-regular]
542      [features={default,lm-ss-bold}]
543    \definefontsynonym
544      [SansBoldItalic] [file:lmsans10-oblique]
545      [features={default,lm-ss-bold}]
546    \definefontsynonym
547      [SansBoldSlanted] [file:lmsans10-oblique]
548      [features={default,lm-ss-bold}]
549  \stoptypescript
550
551  \starttypescript [mono] [modern-latin]
552    \definefontsynonym
553      [Mono] [file:lmmono10-regular]
554      [features={default,lm-tt-regular}]
555    \definefontsynonym
556      [MonoItalic] [file:lmmono10-italic]
557      [features={default,lm-tt-regular}]
558    \definefontsynonym
559      [MonoSlanted] [file:lmmonoslant10-regular]
560      [features={default,lm-tt-regular}]
561    \definefontsynonym
562      [MonoBold] [file:lmmono10-regular]
563      [features={default,lm-tt-bold}]
564    \definefontsynonym
565      [MonoBoldItalic] [file:lmmono10-italic]
566      [features={default,lm-tt-bold}]
567    \definefontsynonym
568      [MonoBoldSlanted] [file:lmmonoslant10-regular]
569      [features={default,lm-tt-bold}]
570  \stoptypescript
571
572  \starttypescript [math] [modern-latin]
573    \loadfontgoodies[lm]
574    \definefontsynonym
575      [MathRoman] [file:latinmodern-math-regular.otf]
576      [features={math\mathsizesuffix,lm-mm-regular,mathextra},
577       goodies=lm]
578    \definefontsynonym
579      [MathRomanBold] [file:latinmodern-math-regular.otf]
580      [features={math\mathsizesuffix,lm-mm-bold,mathextra},
581       goodies=lm]
582  \stoptypescript
583
584  \starttypescript [modern-latin]
585    \definetypeface [\typescriptone]
586      [rm] [serif] [modern-latin] [default]
587    \definetypeface [\typescriptone]
588      [ss] [sans]  [modern-latin] [default]
589    \definetypeface [\typescriptone]
590      [tt] [mono]  [modern-latin] [default]
591    \definetypeface [\typescriptone]
592      [mm] [math]  [modern-latin] [default]
593    \quittypescriptscanning
594  \stoptypescript
595
596\stoptypescriptcollection
597\stoptyping
598
599We show some more samples now for which we use\type {zapf.tex}.
600
601\startbuffer
602    {\tf\samplefile{zapf}}\blank {\bf\samplefile{zapf}}\blank
603    {\it\samplefile{zapf}}\blank {\bi\samplefile{zapf}}\blank
604    {\sl\samplefile{zapf}}\blank {\bs\samplefile{zapf}}\blank
605\stopbuffer
606
607\startsubsubsubject[title={\type{\switchtobodyfont[modern-latin,rm,10pt]}}]
608    \start
609        \switchtobodyfont[modern-latin,rm,10pt]
610        \getbuffer
611    \stop
612\stopsubsubsubject
613
614\startsubsubsubject[title={\type{\switchtobodyfont[modern-latin,ss,10pt]}}]
615    \start
616        \switchtobodyfont[modern-latin,ss,10pt]
617        \getbuffer
618    \stop
619\stopsubsubsubject
620
621\startsubsubsubject[title={\type{\switchtobodyfont[modern-latin,tt,10pt]}}]
622    \start
623        \switchtobodyfont[modern-latin,tt,10pt]
624        \setupalign[flushleft,broad,nothyphenated,verytolerant]
625        \getbuffer
626    \stop
627\stopsubsubsubject
628
629\stopsection
630
631\startsection[title=Finetuning]
632
633In practice we only need to compensate the width but can leave the height
634and depth untouched. In the following examples we see the normal bold next
635to the regular as well as the boldened version. For this we will use a couple
636of definitions:
637
638\startbuffer
639\definefontfeature[lm-bald][effect={width=0.25,effect=both}]
640\definefontfeature[pg-bald][effect={width=0.25,effect=both}]
641\definefontfeature[dj-bald][effect={width=0.35,effect=both}]
642
643\definefontfeature
644  [lm-bold]
645  [effect={width=0.25,hdelta=0,ddelta=0,effect=both},
646   extend=1.10]
647
648\definefontfeature
649  [pg-bold]
650  [effect={width=0.25,hdelta=0,ddelta=0,effect=both},
651   extend=1.00]
652
653\definefontfeature
654  [dj-bold]
655  [effect={width=0.35,hdelta=0,ddelta=0,effect=both},
656   extend=1.05]
657
658\definefont[lmbald][Serif*default,lm-bald sa d]
659\definefont[pgbald][Serif*default,pg-bald sa d]
660\definefont[djbald][Serif*default,dj-bald sa d]
661
662\definefont[lmbold][Serif*default,lm-bold sa d]
663\definefont[pgbold][Serif*default,pg-bold sa d]
664\definefont[djbold][Serif*default,dj-bold sa d]
665\stopbuffer
666
667\typebuffer \getbuffer
668
669We can combine the extend and effect features to get a bold running as wide as a
670normal bold. We limit the height and depth so that we can use regular and bold in
671the same sentence. It's all a matter of taste, but some control is there.
672
673\starttabulate[|l|l|l|l|]
674\NC
675    \BC
676    \tt modern  \BC
677    \tt pagella \BC
678    \tt dejavu  \NC
679\NR
680\NC
681    \type{\tfd} \NC
682    \switchtobodyfont [modern,24pt]\strut\ruledhbox{\tfd    ABC}\NC
683    \switchtobodyfont[pagella,24pt]\strut\ruledhbox{\tfd    ABC}\NC
684    \switchtobodyfont [dejavu,24pt]\strut\ruledhbox{\tfd    ABC}\NC
685\NR
686\NC
687    \type{\..bald} \NC
688    \switchtobodyfont [modern,24pt]\strut\ruledhbox{\lmbald ABC}\NC
689    \switchtobodyfont[pagella,24pt]\strut\ruledhbox{\pgbald ABC}\NC
690    \switchtobodyfont [dejavu,24pt]\strut\ruledhbox{\djbald ABC}\NC
691\NR
692\NC
693    \type{\bfd} \NC
694    \switchtobodyfont [modern,24pt]\strut\ruledhbox{\bfd    ABC}\NC
695    \switchtobodyfont[pagella,24pt]\strut\ruledhbox{\bfd    ABC}\NC
696    \switchtobodyfont [dejavu,24pt]\strut\ruledhbox{\bfd    ABC}\NC
697\NR
698\NC
699    \type{\..bold} \NC
700    \switchtobodyfont [modern,24pt]\strut\ruledhbox{\lmbold ABC}\NC
701    \switchtobodyfont[pagella,24pt]\strut\ruledhbox{\pgbold ABC}\NC
702    \switchtobodyfont [dejavu,24pt]\strut\ruledhbox{\djbold ABC}\NC
703\NR
704\stoptabulate
705
706Let's take another go at Pagella. We define a few features, colors
707and fonts first:
708
709\startbuffer
710\definefontfeature
711  [pg-fake-1]
712  [effect={width=0.25,effect=both}]
713
714\definefontfeature
715  [pg-fake-2]
716  [effect={width=0.25,hdelta=0,ddelta=0,effect=both}]
717
718\definefont[pgregular]  [Serif*default]
719\definefont[pgbold]     [SerifBold*default]
720\definefont[pgfakebolda][Serif*default,pg-fake-1]
721\definefont[pgfakeboldb][Serif*default,pg-fake-2]
722
723\definecolor[color-pgregular]  [t=.5,a=1,r=.6]
724\definecolor[color-pgbold]     [t=.5,a=1,g=.6]
725\definecolor[color-pgfakebolda][t=.5,a=1,b=.6]
726\definecolor[color-pgfakeboldb][t=.5,a=1,r=.6,g=.6]
727\stopbuffer
728
729\typebuffer \getbuffer
730
731When we apply these we get the results of \in {figure} [fig:pagella-compared]
732while we show the same overlayed in \in {figure} [fig:pagella-overlayed]. As you
733can see, the difference in real bold and fake bold is subtle: the inner shape of
734the \quote {o} differs. Also note that the position of the accents doesn't change
735in the vertical direction but moves along with the width.
736
737\def\SampleWord{\^o\"ep\c s}
738
739\startplacefigure[title={Four pagella style variants compared.},reference=fig:pagella-compared]
740    \startcombination[2*2]
741        {
742            \scale [scale=7500] {
743                \ruledhbox{\showglyphs\pgregular   \SampleWord}
744            }
745        } {
746            regular (red)
747        } {
748            \scale [scale=7500] {
749                \ruledhbox{\showglyphs\pgbold      \SampleWord}
750            }
751        } {
752            bold (green)
753        } {
754            \scale [scale=7500] {
755                \ruledhbox{\showglyphs\pgfakebolda \SampleWord}
756            }
757        } {
758            fakebolda (blue)
759        } {
760            \scale [scale=7500] {
761                \ruledhbox{\showglyphs\pgfakeboldb \SampleWord}
762            }
763        } {
764            fakeboldb (yellow)
765        }
766    \stopcombination
767\stopplacefigure
768
769\startplacefigure[title={Four pagella style variants overlayed.},reference=fig:pagella-overlayed]
770    \startcombination[2*3]
771        {
772            \scale [scale=7500] {
773                \startoverlay
774                    {\color[color-pgregular]  {\pgregular   \SampleWord}}
775                    {\color[color-pgbold]     {\pgbold      \SampleWord}}
776                \stopoverlay
777            }
778        } {
779            bold over regular
780        } {
781            \scale [scale=7500] {
782                \startoverlay
783                    {\color[color-pgregular]  {\pgregular   \SampleWord}}
784                    {\color[color-pgfakeboldb]{\pgfakeboldb \SampleWord}}
785                \stopoverlay
786            }
787        } {
788            fakebolda over regular
789        } {
790            \scale [scale=7500] {
791                \startoverlay
792                    {\color[color-pgregular]  {\pgregular   \SampleWord}}
793                    {\color[color-pgfakebolda]{\pgfakeboldb \SampleWord}}
794                \stopoverlay
795            }
796        } {
797            fakeboldb over regular
798        } {
799            \scale [scale=7500] {
800                \startoverlay
801                    {\color[color-pgbold]     {\pgbold      \SampleWord}}
802                    {\color[color-pgfakeboldb]{\pgfakeboldb \SampleWord}}
803                \stopoverlay
804            }
805        } {
806            fakeboldb over bold
807        } {
808            \scale [scale=7500] {
809                \startoverlay
810                    {\color[color-pgfakebolda]{\pgfakebolda \SampleWord}}
811                    {\color[color-pgfakeboldb]{\pgfakeboldb \SampleWord}}
812                \stopoverlay
813            }
814        } {
815             fakeboldb over fakebolda
816        } {
817            \scale [scale=7500] {
818                \startoverlay
819                    {\color[color-pgregular]  {\pgregular   \SampleWord}}
820                    {\color[color-pgbold]     {\pgbold      \SampleWord}}
821                    {\color[color-pgfakebolda]{\pgfakebolda \SampleWord}}
822                    {\color[color-pgfakeboldb]{\pgfakeboldb \SampleWord}}
823                \stopoverlay
824            }
825        } {
826             all four overlayed
827        }
828    \stopcombination
829\stopplacefigure
830
831\stopsection
832
833\startsection[title=The code]
834
835The amount of code involved is not that large and is a nice illustration of what
836\LUATEX\ provides (I have omitted a few lines of tracing and error reporting).
837The only thing added to the font scaler elsewhere is that we pass the \type
838{mode} and \type {width} parameters to \TEX\ so that they get used in the backend
839to inject the few operators needed.
840
841\starttyping
842local effects = {
843  inner  = 0,
844  outer  = 1,
845  both   = 2,
846  hidden = 3,
847}
848
849local function initialize(tfmdata,value)
850  local spec
851  if type(value) == "number" then
852      spec = { width = value }
853  else
854      spec = utilities.parsers.settings_to_hash(value)
855  end
856  local effect = spec.effect or "both"
857  local width  = tonumber(spec.width) or 0
858  local mode   = effects[effect]
859  if mode then
860    local factor  = tonumber(spec.factor)  or 0
861    local hfactor = tonumber(spec.vfactor) or factor
862    local vfactor = tonumber(spec.hfactor) or factor
863    local delta   = tonumber(spec.delta)   or 1
864    local wdelta  = tonumber(spec.wdelta)  or delta
865    local hdelta  = tonumber(spec.hdelta)  or delta
866    local ddelta  = tonumber(spec.ddelta)  or hdelta
867    tfmdata.parameters.mode   = mode
868    tfmdata.parameters.width  = width * 1000
869    tfmdata.properties.effect = {
870      effect  = effect, width   = width,
871      wdelta  = wdelta, factor  = factor,
872      hdelta  = hdelta, hfactor = hfactor,
873      ddelta  = ddelta, vfactor = vfactor,
874    }
875  end
876end
877
878local function manipulate(tfmdata)
879  local effect = tfmdata.properties.effect
880  if effect then
881    local characters = tfmdata.characters
882    local parameters = tfmdata.parameters
883    local multiplier = effect.width * 100
884    local wdelta = effect.wdelta * parameters.hfactor * multiplier
885    local hdelta = effect.hdelta * parameters.vfactor * multiplier
886    local ddelta = effect.ddelta * parameters.vfactor * multiplier
887    local hshift = wdelta / 2
888    local factor  = (1 + effect.factor)  * parameters.factor
889    local hfactor = (1 + effect.hfactor) * parameters.hfactor
890    local vfactor = (1 + effect.vfactor) * parameters.vfactor
891    for unicode, char in next, characters do
892      local oldwidth  = char.width
893      local oldheight = char.height
894      local olddepth  = char.depth
895      if oldwidth and oldwidth > 0 then
896        char.width = oldwidth + wdelta
897        char.commands = {
898          { "right", hshift },
899          { "char", unicode },
900        }
901      end
902      if oldheight and oldheight > 0 then
903        char.height = oldheight + hdelta
904      end
905      if olddepth and olddepth > 0 then
906        char.depth = olddepth + ddelta
907      end
908    end
909    parameters.factor  = factor
910    parameters.hfactor = hfactor
911    parameters.vfactor = vfactor
912  end
913end
914
915local specification = {
916  name        = "effect",
917  description = "apply effects to glyphs",
918  initializers = {
919     base = initialize,
920     node = initialize,
921  },
922  manipulators = {
923    base = manipulate,
924    node = manipulate,
925  },
926}
927
928fonts.handlers.otf.features.register(specification)
929fonts.handlers.afm.features.register(specification)
930\stoptyping
931
932The real code is slightly more complex because we want to stack virtual features
933properly but the principle is the same.
934
935\stopsection
936
937\startsection[title=Arabic]
938
939It is tempting to test effects with arabic but we need to keep in mind that for
940that we should add some more support in the \CONTEXT\ font handler. Let's define
941some features.
942
943\startbuffer
944\definefontfeature
945  [bolden-arabic-1]
946  [effect={width=0.4}]
947
948\definefontfeature
949  [bolden-arabic-2]
950  [effect={width=0.4,effect=outer}]
951
952\definefontfeature
953  [bolden-arabic-3]
954  [effect={width=0.5,wdelta=0.5,ddelta=.2,hdelta=.2,factor=.1}]
955\stopbuffer
956
957\typebuffer \getbuffer
958
959\startbuffer
960
961\setupalign
962  [righttoleft]
963
964\setupinterlinespace
965  [1.5]
966
967\start
968  \definedfont[arabictest*arabic,bolden-arabic-1 @ 30pt]
969  \samplefile{khatt-ar}\par
970  \definedfont[arabictest*arabic,bolden-arabic-2 @ 30pt]
971  \samplefile{khatt-ar}\par
972  \definedfont[arabictest*arabic,bolden-arabic-3 @ 30pt]
973  \samplefile{khatt-ar}\par
974\stop
975\stopbuffer
976
977With \MICROSOFT\ Arabtype the \type {khatt-ar.tex} looks as follows:
978
979\typebuffer \start \definefontsynonym[arabictest][arabtype] \getbuffer\stop
980
981And with Idris' Husayni we get:
982
983\typebuffer \start \definefontsynonym[arabictest][husayni]  \getbuffer\stop
984
985Actually, quite okay are the following. We don't over do bold here and to get
986a distinction we make the original thinner.
987
988\startbuffer
989\definefontfeature[effect-ar-thin] [effect={width=0.01,effect=inner}]
990\definefontfeature[effect-ar-thick][effect={width=0.20,extend=1.05}]
991\stopbuffer
992
993\typebuffer \getbuffer
994
995\start
996  \setupalign
997    [righttoleft]
998
999  \setupinterlinespace
1000    [1.5]
1001
1002  \definedfont[husayni*arabic,effect-ar-thin  @ 30pt]
1003  \samplefile{khatt-ar}\par
1004  \definedfont[husayni*arabic,effect-ar-thick @ 30pt]
1005  \samplefile{khatt-ar}\par
1006\stop
1007
1008The results are acceptable at small sizes but at larger sizes you will start to
1009see kerning, anchoring and cursive artifacts. The outline examples show that the
1010amount of overlap differs per font and the more overlap we have the better
1011boldening will work.
1012
1013\startMPinclusions
1014    def DrawShapes(expr how) =
1015        def SampleShapes(expr offset, pw, xc, xs, xt, yc, ys, yt, txt, more) =
1016            numeric l ; l := pw * mm ;
1017            picture p ; p := image (
1018                draw fullcircle   scaled 10 ;
1019                draw fullcircle   scaled  3 shifted (-3+xc  ,8+yc) withcolor "darkred" ;
1020                draw fullsquare   scaled  3 shifted ( 6+xs  ,7+ys) withcolor "darkblue";
1021                draw fulltriangle scaled  4 shifted ( 6+xt+5,6+yt) withcolor "darkgreen";
1022            ) shifted (offset,0) scaled mm ;
1023            draw p
1024                withpen pencircle
1025                    if how = 2 :
1026                        xscaled l yscaled (l/2) rotated 30 ;
1027                    else :
1028                        scaled l ;
1029                    fi ;
1030            draw boundingbox p
1031                withcolor "darkyellow" ;
1032            draw textext(txt)
1033                shifted (xpart center p, -8mm) ;
1034            draw textext(more)
1035                shifted (xpart center p, -11mm) ;
1036        enddef ;
1037        SampleShapes(  0,1, 0,0,0, 0,   0,   0,  "\tinyfont \setstrut \strut original",   "\tinyfont \setstrut \strut ") ;
1038        SampleShapes( 25,2, 0,0,0, 0,   0,   0,  "\tinyfont \setstrut \strut instance",   "\tinyfont \setstrut \strut ") ;
1039        SampleShapes( 50,2,-1,1,0, 0,   0,   0,  "\tinyfont \setstrut \strut mark",       "\tinyfont \setstrut \strut x only") ;
1040        SampleShapes( 75,2,-1,1,1, 0,   0,   0,  "\tinyfont \setstrut \strut mark + mkmk","\tinyfont \setstrut \strut x only") ;
1041        SampleShapes(100,2,-1,1,1, 1,   1,   1,  "\tinyfont \setstrut \strut mark + mkmk","\tinyfont \setstrut \strut x and y") ;
1042        SampleShapes(125,2,-1,2,2,-1/2,-1/2,-1/2,"\tinyfont \setstrut \strut mark + mkmk","\tinyfont \setstrut \strut x and -y") ;
1043    enddef ;
1044\stopMPinclusions
1045
1046In arabic (and sometimes latin) fonts the marks (or accents in latin) are
1047attached to base shapes and normally one will use the \type {mark} to anchor a
1048mark to a base character or specific component of a ligature. The \type {mkmk}
1049feature is then used to anchor marks to other marks. Consider the following
1050example.
1051
1052\startlinecorrection
1053\scale
1054  [width=\textwidth]
1055  {\startMPcode DrawShapes(1) ; \stopMPcode}
1056\stoplinecorrection
1057
1058We start with \type {original}: a base shape with three marks: the red circle and
1059blue square anchor to the base and the green triangle anchors to the blue square.
1060When we bolden, the shapes will start touching. In the case of latin scripts,
1061it's normal to keep the accents on the same height so this is why the third
1062picture only shifts in the horizontal direction. The fourth picture demonstrates
1063that we need to compensate the two bound marks. One can decide to move the lot up
1064as in the fifth picture but that is no option here.
1065
1066Matters can be even more complex when a non circular pen is introduced. In that
1067case a transformation from one font to another using the transformed \OPENTYPE\
1068positioning logic (values) is even more tricky and unless one knows the
1069properties (and usage) of a mark it makes no sense at all. Actually the sixths
1070variant is probably nicer here but there we actually move the marks down!
1071
1072\startlinecorrection
1073\scale
1074  [width=\textwidth]
1075  {\startMPcode DrawShapes(2) ; \stopMPcode}
1076\stoplinecorrection
1077
1078For effects this means that when it gets applied to such a font, only small
1079values work out well.
1080
1081\stopsection
1082
1083\startsection[title=Math]
1084
1085Math is dubious as there is all kind of positioning involved. Future versions
1086might deal with this, although bolder math (math itself has bold, so actually
1087we're talking of bold with some heavy) is needed for titling. If we keep that
1088in mind we can actually just bolden math and probably most will come out
1089reasonable well. One of the potential troublemakers is the radical (root) sign
1090that can be bound to a rule. Bumping the rules is no big deal and patching the
1091relevant radical properties neither, so indeed we can do:
1092
1093\startbuffer[mathblob]
10942\times\sqrt{\frac{\sqrt{\frac{\sqrt{2}}{\sqrt{2}}}}
1095  {\sqrt{\frac{\sqrt{2}}{\sqrt{2}}}}}
1096\stopbuffer
1097
1098\startbuffer
1099\switchtobodyfont [modernlatin,17.3pt]
1100$
1101  \mr \darkblue  \getbuffer[mathblob] \quad
1102  \mb \darkgreen \getbuffer[mathblob]
1103$
1104\stopbuffer
1105
1106\typebuffer \blank \start \getbuffer \stop \blank
1107
1108Where the \type {mathblob} buffer is:
1109
1110\typebuffer[mathblob]
1111
1112Here you also see a fraction rule that has been bumped. In display mode we
1113get:
1114
1115\startbuffer
1116\switchtobodyfont[modernlatin,17.3pt]
1117\startformula
1118  \mr \darkblue  \getbuffer[mathblob] \quad
1119  \mb \darkgreen \getbuffer[mathblob]
1120\stopformula
1121\stopbuffer
1122
1123\typebuffer \blank \start \getbuffer \stop \blank
1124
1125Extensibles behave well too:
1126
1127\startbuffer
1128\switchtobodyfont [modernlatin,17.3pt]
1129\dostepwiserecurse {1} {30} {5} {
1130  $
1131    \mr \sqrt{\blackrule[width=2mm,height=#1mm,color=darkblue]}
1132    \quad
1133    \mb \sqrt{\blackrule[width=2mm,height=#1mm,color=darkgreen]}
1134  $
1135}
1136\stopbuffer
1137
1138\typebuffer \blank \start \getbuffer \stop \blank
1139
1140\definecolor[colormr] [t=.5,a=1,b=.6]
1141\definecolor[colormb] [t=.5,a=1,g=.6]
1142
1143In \in {figure} [fig:regular-over-bold] we overlay regular and bold. The result
1144doesn't look that bad after all, does it? It took however a bit of experimenting
1145and a fix in \LUATEX: pickup the value from the font instead of the currently
1146used (but frozen) math parameter.
1147
1148\startplacefigure[title={Modern Latin regular over bold.},reference=fig:regular-over-bold]
1149\switchtobodyfont[modernlatin,17.3pt]
1150\scale[width=.25\textwidth]{\startoverlay
1151    {\color[colormb]{$\mb\sqrt{\frac{1}{x}}$}}
1152    {\color[colormr]{$   \sqrt{\frac{1}{x}}$}}
1153\stopoverlay}
1154\stopplacefigure
1155
1156In case you wonder how currently normal Latin Modern bold looks, here we go:
1157
1158\startbuffer
1159\switchtobodyfont[latinmodern,17.3pt]
1160\startformula
1161  \mr \darkblue  \getbuffer[mathblob] \quad
1162  \mb \darkgreen \getbuffer[mathblob]
1163\stopformula
1164\stopbuffer
1165
1166\typebuffer \blank \start \getbuffer \stop \blank
1167
1168\unexpanded\def\ShowMathSample#1%
1169  {\switchtobodyfont[#1,14.4pt]%
1170   \mathematics{%
1171    \mr \darkblue  \getbuffer[mathblob] \quad
1172    \mb \darkgreen \getbuffer[mathblob]
1173   }}
1174
1175\unexpanded\def\ShowMathCaption#1%
1176  {\switchtobodyfont[#1]%
1177   #1:
1178   $
1179   {\mr2\enspace \scriptstyle2\enspace \scriptscriptstyle2}
1180   \enspace
1181   {\mb2\enspace \scriptstyle2\enspace \scriptscriptstyle2}
1182   $}
1183
1184\startcombination[3*2]
1185    {\ShowMathSample {dejavu}} {\ShowMathCaption{dejavu}}
1186    {\ShowMathSample{pagella}} {\ShowMathCaption{pagella}}
1187    {\ShowMathSample {termes}} {\ShowMathCaption{termes}}
1188    {\ShowMathSample  {bonum}} {\ShowMathCaption{bonum}}
1189    {\ShowMathSample {schola}} {\ShowMathCaption{schola}}
1190    {\ShowMathSample{cambria}} {\ShowMathCaption{cambria}}
1191\stopcombination
1192
1193I must admit that I cheat a bit. In order to get a better looking pseudo math
1194we need to extend the shapes horizontally as well as squeeze them a bit vertically.
1195So, the real effect definitions more look like this:
1196
1197\starttyping
1198\definefontfeature
1199  [boldened-30]
1200  [effect={width=0.3,extend=1.15,squeeze=0.985,%
1201     delta=1,hdelta=0.225,ddelta=0.225,vshift=0.225}]
1202\stoptyping
1203
1204and because we can calculate the funny values sort of automatically, this gets
1205simplified to:
1206
1207\starttyping
1208\definefontfeature
1209  [boldened-30]
1210  [effect={width=0.30,auto=yes}]
1211\stoptyping
1212
1213We leave it to your imagination to figure out what happens behind the screens.
1214Just think of some virtual font magic combined with the engine supported \type
1215{extend} and \type {squeeze} function. And because we already support bold math
1216in \CONTEXT, you will get it when you are doing bold titling.
1217
1218\startbuffer
1219\def\MathSample
1220  {\overbrace{2 +
1221     \sqrt{\frac{\sqrt{\frac{\sqrt{2}}{\sqrt{2}}}}
1222       {\sqrt{\frac{\sqrt{\underbar{2}}}{\sqrt{\overbar{2}}}}}}}}
1223
1224\definehead
1225  [mysubject]
1226  [subject]
1227
1228\setuphead
1229  [mysubject]
1230  [style=\tfc,
1231   color=darkblue,
1232   before=\blank,
1233   after=\blank]
1234
1235\mysubject{Regular\quad$\MathSample\quad\mb\MathSample$}
1236
1237\setuphead
1238  [mysubject]
1239  [style=\bfc,
1240   color=darkred]
1241
1242\mysubject{Bold   \quad$\MathSample\quad\mb\MathSample$}
1243\stopbuffer
1244
1245\typebuffer
1246
1247\getbuffer
1248
1249Of course one can argue about the right values for boldening and compensation if
1250dimensions so don't expect the current predefined related features to be frozen
1251yet.
1252
1253For sure this mechanism will create more fonts than normal but fortunately it
1254can use the low level optimizations for sharing instances so in the end the
1255overhead is not that large. This chapter uses 36 different fonts, creates 270
1256font instances (different scaling and properties) of which 220 are shared in the
1257backend. The load time is 5 seconds in \LUATEX\ and 1.2 seconds in \LUAJITTEX\ on
1258a somewhat old laptop with a i7-3840QM processor running 64 bit \MSWINDOWS. Of
1259course we load a lot of bodyfonts at different sizes so in a normal run the extra
1260loading is limited to just a couple of extra instances for math (normally 3, one
1261for each math size).
1262
1263\stopsection
1264
1265\startsection[title=Conclusion]
1266
1267So what can we conclude? When we started with \LUATEX, right from the start
1268\CONTEXT\ supported true \UNICODE\ math by using virtual \UNICODE\ math fonts.
1269One of the objectives of the \TEX Gyre project is to come up with a robust
1270complete set of math fonts, text fonts with a bunch of useful symbols, and
1271finally a subset bold math font for titling. Now we have real \OPENTYPE\ math
1272fonts, although they are still somewhat experimental. Because we're impatient, we
1273now provide bold math by using effects but the future will learn to what extent
1274the real bold math fonts will differ and be more pleasant to look at. After all,
1275what we describe he is just an experiment that got a bit out of hands.
1276
1277% And if you wonder if this kind of messing with fonts is okay? Well, you don't
1278% know what specs we sometimes get (and then ignore).
1279
1280\stopsection
1281
1282\stopchapter
1283
1284\stopcomponent
1285