1
2
3
4
5
6\setupversion[alternative=file,text={not corrected yet}]
7
8\definebodyfontenvironment[24pt]
9
10\usemodule[fontseffects]
11
12\startcomponent onandonmodern
13
14\environment onandonenvironment
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:lmroman10regular]
46
47Lets 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 [effect1]
61 [effect=.2]
62\stopbuffer
63
64\typebuffer \getbuffer
65
66\startnarrower
67 \definedfont[DemoSerif*default,effect1]
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,effect1] \showfonteffect}
75
76\startbuffer
77\definefontfeature
78 [effect2]
79 [effect={width=.3}]
80\stopbuffer
81
82\typebuffer \getbuffer
83
84\startnarrower
85 \definedfont[DemoSerif*default,effect2]
86 \samplefile{ward}
87\stopnarrower
88
89This time we use:
90
91{\definedfont[DemoSerif*default,effect2] \showfonteffect}
92
93\startbuffer
94\definefontfeature
95 [effect3]
96 [effect={width=.3,delta=0.4}]
97\stopbuffer
98
99\typebuffer \getbuffer
100
101\startnarrower
102 \showfontkerns
103 \definedfont[DemoSerif*default,effect3]
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,effect3] \showfonteffect}
111
112\startbuffer
113\definefontfeature
114 [effect4]
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,effect4]
123 \samplefile{ward}
124\stopnarrower
125
126An additional parameter \type {factor} will influence the way (for instance)
127kerns get affected:
128
129{\definedfont[DemoSerif*effect4] \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 [effect5]
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,effect5]
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 [effect6]
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,effect6]
167 \samplefile{ward}
168\stopnarrower
169
170\startbuffer
171\definefontfeature
172 [effect7]
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,effect7]
181 \samplefile{ward}
182\stopnarrower
183
184\startbuffer
185\definefontfeature
186 [effect8]
187 [effect={width=.2,delta=0.4,factor=0.3,effect=hidden},
188 boundingbox=yes]
189\stopbuffer
190
191\typebuffer \getbuffer
192
193We also show the boundingboxes of the glyphs here so that you can see what youre
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,effect8]
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. Lets
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 (dxk,0) ;
269 draw point 8 of (fullcircle scaled 1cm) withcolor white ;
270 draw point 3.5 of (fullsquare scaled 1cm) shifted (dxk,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 poormans 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 (dxk,0) ;
312 draw point 8 of (fullcircle scaled 1cm) withcolor white ;
313 draw point 3.5 of (fullsquare scaled 1cm) shifted (dxk,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. Its 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
345isnt 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[effect200]
351 [effect={width=0.2,delta=0}]
352\definefontfeature[effect230]
353 [effect={width=0.2,delta=0.3}]
354\definefontfeature[effect260]
355 [effect={width=0.2,delta=0.6}]
356\definefontfeature[effect400]
357 [effect={width=0.4,delta=0}]
358\definefontfeature[effect430]
359 [effect={width=0.4,delta=0.3}]
360\definefontfeature[effect460]
361 [effect={width=0.4,delta=0.6}]
362\definefontfeature[effect800]
363 [effect={width=0.8,delta=0}]
364\definefontfeature[effect830]
365 [effect={width=0.8,delta=0.3}]
366\definefontfeature[effect860]
367 [effect={width=0.8,delta=0.6}]
368\definefontfeature[effect862]
369 [effect={width=0.8,delta=0.6,factor=0.2}]
370\definefontfeature[effect864]
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
381
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
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,effect200}{5}
407 \ShowOneSample{width=0.2\\delta=0.3} {#1}{default,effect230}{5}
408 \ShowOneSample{width=0.2\\delta=0.6} {#1}{default,effect260}{5}
409 \ShowOneSample{width=0.4\\delta=0} {#1}{default,effect400}{5}
410 \ShowOneSample{width=0.4\\delta=0.3} {#1}{default,effect430}{5}
411 \ShowOneSample{width=0.4\\delta=0.6} {#1}{default,effect460}{5}
412 \ShowOneSample{width=0.8\\delta=0} {#1}{default,effect800}{5}
413 \ShowOneSample{width=0.8\\delta=0.3} {#1}{default,effect830}{5}
414 \ShowOneSample{width=0.8\\delta=0.6} {#1}{default,effect860}{5}
415 \ShowOneSample{width=0.8\\delta=0.6\\factor=0.2}{#1}{default,effect862}{5}
416 \ShowOneSample{width=0.8\\delta=0.6\\factor=0.4}{#1}{default,effect864}{5}
417 \stop
418 \stopsubsubject
419\stoptexdefinition
420
421We show some extremes, using the font used in this document. so dont 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 andor repositioned
441glyphs, or whatever the designer thinks reasonable. In \in {figure}
442[fig:ligatureeffectsmess] this is demonstrated. We use the following
443feature sets:
444
445\startbuffer
446\definefontfeature
447 [demo1]
448 [default]
449 [hlig=yes]
450
451\definefontfeature
452 [demo2]
453 [demo1]
454 [effect=0.5]
455\stopbuffer
456
457\typebuffer \getbuffer
458
459\startplacefigure[title={The effects on ligatures.},reference=fig:ligatureeffectsmess]
460 \startcombination[1*3]
461 { \scale [scale=5000] {
462 \definedfont[texgyrepagellaregular*demo1]fist effe
463 \par
464 \definedfont[texgyrepagellaregular*demo2]fist effe
465 } } {
466 texgyre pagella regular
467 } { \scale [scale=5000] {
468 \definedfont[cambria*demo1]fist effe
469 \par
470 \definedfont[cambria*demo2]fist effe
471 } } {
472 cambria
473 } { \scale [scale=5000] {
474 \definedfont[ebgaramond12regular*demo1]fist effe
475 \par
476 \definedfont[ebgaramond12regular*demo2]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 dont 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 weve 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[lmrmregular][effect={width=0.15,delta=1.00}]
501 \definefontfeature[lmrmbold] [effect={width=0.30,delta=1.00}]
502 \definefontfeature[lmssregular][effect={width=0.10,delta=1.00}]
503 \definefontfeature[lmssbold] [effect={width=0.20,delta=1.00}]
504 \definefontfeature[lmttregular][effect={width=0.15,delta=1.00}]
505 \definefontfeature[lmttbold] [effect={width=0.30,delta=1.00}]
506 \definefontfeature[lmmmregular][effect={width=0.15,delta=1.00}]
507 \definefontfeature[lmmmbold] [effect={width=0.30,delta=1.00}]
508
509 \starttypescript [serif] [modernlatin]
510 \definefontsynonym
511 [Serif] [file:lmroman10regular]
512 [features={default,lmrmregular}]
513 \definefontsynonym
514 [SerifItalic] [file:lmroman10italic]
515 [features={default,lmrmregular}]
516 \definefontsynonym
517 [SerifSlanted] [file:lmromanslant10regular]
518 [features={default,lmrmregular}]
519 \definefontsynonym
520 [SerifBold] [file:lmroman10regular]
521 [features={default,lmrmbold}]
522 \definefontsynonym
523 [SerifBoldItalic] [file:lmroman10italic]
524 [features={default,lmrmbold}]
525 \definefontsynonym
526 [SerifBoldSlanted] [file:lmromanslant10regular]
527 [features={default,lmrmbold}]
528 \stoptypescript
529
530 \starttypescript [sans] [modernlatin]
531 \definefontsynonym
532 [Sans] [file:lmsans10regular]
533 [features={default,lmssregular}]
534 \definefontsynonym
535 [SansItalic] [file:lmsans10oblique]
536 [features={default,lmssregular}]
537 \definefontsynonym
538 [SansSlanted] [file:lmsans10oblique]
539 [features={default,lmssregular}]
540 \definefontsynonym
541 [SansBold] [file:lmsans10regular]
542 [features={default,lmssbold}]
543 \definefontsynonym
544 [SansBoldItalic] [file:lmsans10oblique]
545 [features={default,lmssbold}]
546 \definefontsynonym
547 [SansBoldSlanted] [file:lmsans10oblique]
548 [features={default,lmssbold}]
549 \stoptypescript
550
551 \starttypescript [mono] [modernlatin]
552 \definefontsynonym
553 [Mono] [file:lmmono10regular]
554 [features={default,lmttregular}]
555 \definefontsynonym
556 [MonoItalic] [file:lmmono10italic]
557 [features={default,lmttregular}]
558 \definefontsynonym
559 [MonoSlanted] [file:lmmonoslant10regular]
560 [features={default,lmttregular}]
561 \definefontsynonym
562 [MonoBold] [file:lmmono10regular]
563 [features={default,lmttbold}]
564 \definefontsynonym
565 [MonoBoldItalic] [file:lmmono10italic]
566 [features={default,lmttbold}]
567 \definefontsynonym
568 [MonoBoldSlanted] [file:lmmonoslant10regular]
569 [features={default,lmttbold}]
570 \stoptypescript
571
572 \starttypescript [math] [modernlatin]
573 \loadfontgoodies[lm]
574 \definefontsynonym
575 [MathRoman] [file:latinmodernmathregular.otf]
576 [features={math\mathsizesuffix,lmmmregular,mathextra},
577 goodies=lm]
578 \definefontsynonym
579 [MathRomanBold] [file:latinmodernmathregular.otf]
580 [features={math\mathsizesuffix,lmmmbold,mathextra},
581 goodies=lm]
582 \stoptypescript
583
584 \starttypescript [modernlatin]
585 \definetypeface [\typescriptone]
586 [rm] [serif] [modernlatin] [default]
587 \definetypeface [\typescriptone]
588 [ss] [sans] [modernlatin] [default]
589 \definetypeface [\typescriptone]
590 [tt] [mono] [modernlatin] [default]
591 \definetypeface [\typescriptone]
592 [mm] [math] [modernlatin] [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[modernlatin,rm,10pt]}}]
608 \start
609 \switchtobodyfont[modernlatin,rm,10pt]
610 \getbuffer
611 \stop
612\stopsubsubsubject
613
614\startsubsubsubject[title={\type{\switchtobodyfont[modernlatin,ss,10pt]}}]
615 \start
616 \switchtobodyfont[modernlatin,ss,10pt]
617 \getbuffer
618 \stop
619\stopsubsubsubject
620
621\startsubsubsubject[title={\type{\switchtobodyfont[modernlatin,tt,10pt]}}]
622 \start
623 \switchtobodyfont[modernlatin,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[lmbald][effect={width=0.25,effect=both}]
640\definefontfeature[pgbald][effect={width=0.25,effect=both}]
641\definefontfeature[djbald][effect={width=0.35,effect=both}]
642
643\definefontfeature
644 [lmbold]
645 [effect={width=0.25,hdelta=0,ddelta=0,effect=both},
646 extend=1.10]
647
648\definefontfeature
649 [pgbold]
650 [effect={width=0.25,hdelta=0,ddelta=0,effect=both},
651 extend=1.00]
652
653\definefontfeature
654 [djbold]
655 [effect={width=0.35,hdelta=0,ddelta=0,effect=both},
656 extend=1.05]
657
658\definefont[lmbald][Serif*default,lmbald sa d]
659\definefont[pgbald][Serif*default,pgbald sa d]
660\definefont[djbald][Serif*default,djbald sa d]
661
662\definefont[lmbold][Serif*default,lmbold sa d]
663\definefont[pgbold][Serif*default,pgbold sa d]
664\definefont[djbold][Serif*default,djbold 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. Its all a matter of taste, but some control is there.
672
673\starttabulate[llll]
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
706Lets take another go at Pagella. We define a few features, colors
707and fonts first:
708
709\startbuffer
710\definefontfeature
711 [pgfake1]
712 [effect={width=0.25,effect=both}]
713
714\definefontfeature
715 [pgfake2]
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,pgfake1]
721\definefont[pgfakeboldb][Serif*default,pgfake2]
722
723\definecolor[colorpgregular] [t=.5,a=1,r=.6]
724\definecolor[colorpgbold] [t=.5,a=1,g=.6]
725\definecolor[colorpgfakebolda][t=.5,a=1,b=.6]
726\definecolor[colorpgfakeboldb][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:pagellacompared]
732while we show the same overlayed in \in {figure} [fig:pagellaoverlayed]. 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 doesnt 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:pagellacompared]
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:pagellaoverlayed]
770 \startcombination[2*3]
771 {
772 \scale [scale=7500] {
773 \startoverlay
774 {\color[colorpgregular] {\pgregular \SampleWord}}
775 {\color[colorpgbold] {\pgbold \SampleWord}}
776 \stopoverlay
777 }
778 } {
779 bold over regular
780 } {
781 \scale [scale=7500] {
782 \startoverlay
783 {\color[colorpgregular] {\pgregular \SampleWord}}
784 {\color[colorpgfakeboldb]{\pgfakeboldb \SampleWord}}
785 \stopoverlay
786 }
787 } {
788 fakebolda over regular
789 } {
790 \scale [scale=7500] {
791 \startoverlay
792 {\color[colorpgregular] {\pgregular \SampleWord}}
793 {\color[colorpgfakebolda]{\pgfakeboldb \SampleWord}}
794 \stopoverlay
795 }
796 } {
797 fakeboldb over regular
798 } {
799 \scale [scale=7500] {
800 \startoverlay
801 {\color[colorpgbold] {\pgbold \SampleWord}}
802 {\color[colorpgfakeboldb]{\pgfakeboldb \SampleWord}}
803 \stopoverlay
804 }
805 } {
806 fakeboldb over bold
807 } {
808 \scale [scale=7500] {
809 \startoverlay
810 {\color[colorpgfakebolda]{\pgfakebolda \SampleWord}}
811 {\color[colorpgfakeboldb]{\pgfakeboldb \SampleWord}}
812 \stopoverlay
813 }
814 } {
815 fakeboldb over fakebolda
816 } {
817 \scale [scale=7500] {
818 \startoverlay
819 {\color[colorpgregular] {\pgregular \SampleWord}}
820 {\color[colorpgbold] {\pgbold \SampleWord}}
821 {\color[colorpgfakebolda]{\pgfakebolda \SampleWord}}
822 {\color[colorpgfakeboldb]{\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.settingstohash(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. Lets define
941some features.
942
943\startbuffer
944\definefontfeature
945 [boldenarabic1]
946 [effect={width=0.4}]
947
948\definefontfeature
949 [boldenarabic2]
950 [effect={width=0.4,effect=outer}]
951
952\definefontfeature
953 [boldenarabic3]
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,boldenarabic1 @ 30pt]
969 \samplefile{khattar}\par
970 \definedfont[arabictest*arabic,boldenarabic2 @ 30pt]
971 \samplefile{khattar}\par
972 \definedfont[arabictest*arabic,boldenarabic3 @ 30pt]
973 \samplefile{khattar}\par
974\stop
975\stopbuffer
976
977With \MICROSOFT\ Arabtype the \type {khattar.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 dont over do bold here and to get
986a distinction we make the original thinner.
987
988\startbuffer
989\definefontfeature[effectarthin] [effect={width=0.01,effect=inner}]
990\definefontfeature[effectarthick][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,effectarthin @ 30pt]
1003 \samplefile{khattar}\par
1004 \definedfont[husayni*arabic,effectarthick @ 30pt]
1005 \samplefile{khattar}\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 (-3xc ,8yc) withcolor "darkred" ;
1020 draw fullsquare scaled 3 shifted ( 6xs ,7ys) withcolor "darkblue";
1021 draw fulltriangle scaled 4 shifted ( 6xt+5,6yt) withcolor "darkgreen";
1022 ) shifted (offset,0) scaled mm ;
1023 draw p
1024 withpen pencircle
1025 if how = 2 :
1026 xscaled l yscaled (l2) 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,-12,-12,-12,"\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,
1061its 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
1087were 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:regularoverbold] we overlay regular and bold. The result
1144doesnt 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:regularoverbold]
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 [boldened30]
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 [boldened30]
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 dont 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 i73840QM 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 were 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
1278
1279
1280\stopsection
1281
1282\stopchapter
1283
1284\stopcomponent
1285 |