% language=us % 284 instances, 234 shared in backend, 126 common vectors, 108 common hashes, load time 1.343 seconds %setupversion[alternative=concept,text={not corrected yet}] \setupversion[alternative=file,text={not corrected yet}] \definebodyfontenvironment[24pt] \usemodule[fonts-effects] \startcomponent onandon-modern \environment onandon-environment \startchapter[title={Modern Latin}] \startsection[title={Introduction}] In \CONTEXT, already in \MKII, we have a feature tagged \quote {effects} that can be used to render a font in outline or bolder versions. It uses some low level \PDF\ directives to accomplish this and it works quite well. When a user on the \CONTEXT\ list asked if we could also provide it as a font feature in the repertoire of additional features in \CONTEXT, I was a bit reluctant to provide that because it operates at another level than the glyph stream. Also, such a feature can be abused and result in a bad looking document. However, by adding a few simple options to the \LUATEX\ engine such a feature could actually be achieved rather easy: it was trivial to implement given that we can influence font handling at the \LUA\ end. In retrospect extended and pseudo slanted fonts could be done this way too but there we have some historic ballast. Also, the backend now handles such transformations very efficient because they are combined with font scaling. Anyway, by adding this feature in spite of possible objections, I could do some more advanced experiments. In the following pages I will demonstrate how we support effects as a feature in \CONTEXT. Instead of simply applying some magic \PDF\ text operators in the backend a more integrated approach is used. The difference with the normal effect mechanism is that where the one described here is bound to a font instance while the normal mechanism operates on the glyph stream. \stopsection \startsection[title={The basics}] \definefontsynonym[DemoSerif][file:lmroman10-regular] Let's start with a basic boldening example. First we demonstrate a regular Latin Modern sample (using \type {ward.tex}): \startnarrower \definedfont[DemoSerif*default] \samplefile{ward} \stopnarrower This font looks rather thin (light). Next we define an effect or \type {0.2} and typeset the same sample: \startbuffer \definefontfeature [effect-1] [effect=.2] \stopbuffer \typebuffer \getbuffer \startnarrower \definedfont[DemoSerif*default,effect-1] \samplefile{ward} \stopnarrower This simple call gives reasonable default results. But you can have more control than this. The previous examples use the following properties: {\definedfont[DemoSerif*default,effect-1] \showfonteffect} \startbuffer \definefontfeature [effect-2] [effect={width=.3}] \stopbuffer \typebuffer \getbuffer \startnarrower \definedfont[DemoSerif*default,effect-2] \samplefile{ward} \stopnarrower This time we use: {\definedfont[DemoSerif*default,effect-2] \showfonteffect} \startbuffer \definefontfeature [effect-3] [effect={width=.3,delta=0.4}] \stopbuffer \typebuffer \getbuffer \startnarrower \showfontkerns \definedfont[DemoSerif*default,effect-3] \samplefile{ward} \stopnarrower We have now tweaked one more property and show the fontkerns in order to see what happens with them: {\definedfont[DemoSerif*default,effect-3] \showfonteffect} \startbuffer \definefontfeature [effect-4] [effect={width=.3,delta=0.4,factor=0.3}] \stopbuffer \typebuffer \getbuffer \startnarrower \showfontkerns \definedfont[DemoSerif*default,effect-4] \samplefile{ward} \stopnarrower An additional parameter \type {factor} will influence the way (for instance) kerns get affected: {\definedfont[DemoSerif*effect-4] \showfonteffect} \stopsection \startsection[title=Outlines] There are four effects. Normally a font is rendered with effect \type {inner}. The \type {outer} effect just draws the outlines while \type {both} gives a rather fat result. The \type {hidden} effect hides the text. \startbuffer \definefontfeature [effect-5] [effect={width=0.2,delta=0.4,factor=0.3,effect=inner}] \stopbuffer \typebuffer \getbuffer \startnarrower \showfontkerns \definedfont[DemoSerif*default,effect-5] \samplefile{ward} \stopnarrower An inner effect is rather useless unless you want to use the other properties of this mechanism. \startbuffer \definefontfeature [effect-6] [effect={width=.2,delta=0.4,factor=0.3,effect=outer}] \stopbuffer \typebuffer \getbuffer \startnarrower \showfontkerns \definedfont[DemoSerif*default,effect-6] \samplefile{ward} \stopnarrower \startbuffer \definefontfeature [effect-7] [effect={width=.2,delta=0.4,factor=0.3,effect=both}] \stopbuffer \typebuffer \getbuffer \startnarrower \showfontkerns \definedfont[DemoSerif*default,effect-7] \samplefile{ward} \stopnarrower \startbuffer \definefontfeature [effect-8] [effect={width=.2,delta=0.4,factor=0.3,effect=hidden}, boundingbox=yes] % to show something \stopbuffer \typebuffer \getbuffer We also show the boundingboxes of the glyphs here so that you can see what you're missing. Actually this text is still there and you can select it in the viewer. \startnarrower \showfontkerns \showglyphs \definedfont[DemoSerif*default,effect-8] \samplefile{ward} \stopnarrower \stopsection \startsection[title=The logic] In order to support this I had to make some choices. The calculations involved are best explained in terms of \CONTEXT\ font machinery. \startformula \Delta _{\text{wd}} = \text{effect} _{\text{wdelta}} \times \text{parameter}_{\text{hfactor}} \times \text{effect} _{\text{width}} \times 100 \stopformula \startformula \Delta _{\text{ht}} = \text{effect} _{\text{hdelta}} \times \text{parameter}_{\text{vfactor}} \times \text{effect} _{\text{width}} \times 100 \stopformula \startformula \Delta _{\text{dp}} = \text{effect} _{\text{ddelta}} \times \text{parameter}_{\text{vfactor}} \times \text{effect} _{\text{width}} \times 100 \stopformula The factors in the parameter namespace are adapted according to: \startformula \Delta _{\text{factor}} = \text{effect} _{\text{factor}} \times \text{parameters}_{\text{factor}} \stopformula \startformula \Delta _{\text{hfactor}} = \text{effect} _{\text{hfactor}} \times \text{parameters}_{\text{hfactor}} \stopformula \startformula \Delta _{\text{vfactor}} = \text{effect} _{\text{vfactor}} \times \text{parameters}_{\text{vfactor}} \stopformula The horizontal and vertical scaling factors default to the normal factor that defaults to zero so by default we have no additional scaling of for instance kerns. The width (wd), height (ht) and depth (dp) of a glyph are adapted in relation to the line width. A glyph is shifted in its bounding box by half the width correction. The delta defaults to one. \stopsection \startsection[title=About features] This kind of boldening has limitations especially because some fonts use positioning features that closely relate to the visual font properties. Let's give some examples. The most common positioning is kerning. Take for instance these shapes: \startlinecorrection \startMPcode def SampleShapes(expr dx, offset, pw, k) = picture p ; p := image ( draw fullcircle scaled 1cm ; draw fullsquare scaled 1cm shifted (dx+k,0) ; draw point 8 of (fullcircle scaled 1cm) withcolor white ; draw point 3.5 of (fullsquare scaled 1cm) shifted (dx+k,0) withcolor white ; ) shifted (offset,0) ; draw p withpen pencircle scaled pw ; draw boundingbox p withcolor white ; enddef ; SampleShapes(15mm, 0mm,1mm,0mm) ; SampleShapes(15mm, 40mm,2mm,0mm) ; SampleShapes(17mm, 80mm,2mm,0mm) ; \stopMPcode \stoplinecorrection The first one is that we start with. The circle and square have a line width of one unit and a distance (kern) of five units. The second pair has a line width of two units and the same distance while the third pair has a distance of seven units. So, in the last case we have just increased the kern with a value relative to the increase of line width. \startlinecorrection \startMPcode SampleShapes(15mm, 0mm,1mm,0mm) ; SampleShapes(15mm, 40mm,2mm,2mm) ; SampleShapes(17mm, 80mm,2mm,2mm) ; \stopMPcode \stoplinecorrection In this example we have done the same but we started with a distance of zero. You can consider this a kind of anchoring. This happens in for instance cursive scripts where entry and exit points are used to connect shapes. In a latin script you can think of a poor|-|mans attachment of a cedilla or ogonek. But what to do with for instance an accent on top of a character? In that case we could do the same as with kerning. However, when we mix styles we would like to have a consistent height so maybe there scaling is not a good idea. This is why we can set the factors and deltas explictly for vertical and horizontal movements. However, this will only work well when a font is consistent in how it applies these movements. In this case, if could recognize cursive anchoring (the last pair in the example) we could compensate for it. \startMPinclusions def SampleShapes(expr dx, offset, pw, k) = picture p ; p := image ( draw fullcircle scaled 1cm ; draw fullsquare scaled 1cm shifted (dx+k,0) ; draw point 8 of (fullcircle scaled 1cm) withcolor white ; draw point 3.5 of (fullsquare scaled 1cm) shifted (dx+k,0) withcolor white ; ) shifted (offset,0) ; draw p withpen pencircle scaled pw ; draw boundingbox p withcolor white ; enddef ; \stopMPinclusions \startlinecorrection \startMPcode SampleShapes(10mm, 0mm,1mm,0mm) ; SampleShapes(10mm, 40mm,1mm,1mm) ; SampleShapes(10mm, 80mm,2mm,0mm) ; SampleShapes(10mm,120mm,2mm,2mm) ; \stopMPcode \stoplinecorrection So, an interesting extension to the positioning part of the font handler could be to influence all the scaling factors: anchors, cursives, single and pair wise positioning in both directions (so eight independent factors). Technically this is no big deal so I might give it a go when I have a need for it. \stopsection \startsection[title=Some (extreme) examples] The last decade buying a font has become a bit of a nightmare simply because you have to choose the weights that you need. It's the business model to not stick to four shapes in a few weights but offer a whole range and each of course costs money. Latin Modern is based on Computer Modern and is meant for high resolution rendering. The design of the font is such that you can create instances but in practice that isn't done. One property that let the font stand out is its bold which runs rather wide. However, how about cooking up a variant? For this we will use a series of definitions: \startbuffer \definefontfeature[effect-2-0-0] [effect={width=0.2,delta=0}] \definefontfeature[effect-2-3-0] [effect={width=0.2,delta=0.3}] \definefontfeature[effect-2-6-0] [effect={width=0.2,delta=0.6}] \definefontfeature[effect-4-0-0] [effect={width=0.4,delta=0}] \definefontfeature[effect-4-3-0] [effect={width=0.4,delta=0.3}] \definefontfeature[effect-4-6-0] [effect={width=0.4,delta=0.6}] \definefontfeature[effect-8-0-0] [effect={width=0.8,delta=0}] \definefontfeature[effect-8-3-0] [effect={width=0.8,delta=0.3}] \definefontfeature[effect-8-6-0] [effect={width=0.8,delta=0.6}] \definefontfeature[effect-8-6-2] [effect={width=0.8,delta=0.6,factor=0.2}] \definefontfeature[effect-8-6-4] [effect={width=0.8,delta=0.6,factor=0.4}] \stopbuffer \typebuffer \getbuffer And a helper macro: \startbuffer \starttexdefinition ShowOneSample #1#2#3#4 %\testpage[5] %\startsubsubsubject[title=\type{#1}] \start \definedfont[#2*#3 @ 10pt] \setupinterlinespace \startlinecorrection \showglyphs \showfontkerns \scale[sx=#4,sy=#4]{effective n\"ots} \stoplinecorrection \blank[samepage] \dontcomplain \showfontkerns \margintext{\tt\txx\maincolor#1} \samplefile{ward} \par \stop %\stopsubsubsubject \stoptexdefinition \stopbuffer \typebuffer \getbuffer \starttexdefinition ShowSamples #1 \startsubsubject[title=#1] \start \ShowOneSample{no effect} {#1}{default} {5} \ShowOneSample{width=0.2\\delta=0} {#1}{default,effect-2-0-0}{5} \ShowOneSample{width=0.2\\delta=0.3} {#1}{default,effect-2-3-0}{5} \ShowOneSample{width=0.2\\delta=0.6} {#1}{default,effect-2-6-0}{5} \ShowOneSample{width=0.4\\delta=0} {#1}{default,effect-4-0-0}{5} \ShowOneSample{width=0.4\\delta=0.3} {#1}{default,effect-4-3-0}{5} \ShowOneSample{width=0.4\\delta=0.6} {#1}{default,effect-4-6-0}{5} \ShowOneSample{width=0.8\\delta=0} {#1}{default,effect-8-0-0}{5} \ShowOneSample{width=0.8\\delta=0.3} {#1}{default,effect-8-3-0}{5} \ShowOneSample{width=0.8\\delta=0.6} {#1}{default,effect-8-6-0}{5} \ShowOneSample{width=0.8\\delta=0.6\\factor=0.2}{#1}{default,effect-8-6-2}{5} \ShowOneSample{width=0.8\\delta=0.6\\factor=0.4}{#1}{default,effect-8-6-4}{5} \stop \stopsubsubject \stoptexdefinition We show some extremes, using the font used in this document. so don't complain about beauty here. \texdefinition{ShowSamples}{Serif} \texdefinition{ShowSamples}{SerifBold} \texdefinition{ShowSamples}{SerifItalic} \texdefinition{ShowSamples}{SerifBoldItalic} \texdefinition{ShowSamples}{Sans} \start \setupalign[flushleft,broad,nothyphenated,verytolerant] \texdefinition{ShowSamples}{Mono} \stop \stopsection \startsection[title=Pitfall] The quality of the result depends on how the font is made. For instance, ligatures can be whole shapes, replaced glyphs and|/|or repositioned glyphs, or whatever the designer thinks reasonable. In \in {figure} [fig:ligature-effects-mess] this is demonstrated. We use the following feature sets: \startbuffer \definefontfeature [demo-1] [default] [hlig=yes] \definefontfeature [demo-2] [demo-1] [effect=0.5] \stopbuffer \typebuffer \getbuffer \startplacefigure[title={The effects on ligatures.},reference=fig:ligature-effects-mess] \startcombination[1*3] { \scale [scale=5000] { \definedfont[texgyrepagellaregular*demo-1]fist effe \par \definedfont[texgyrepagellaregular*demo-2]fist effe } } { texgyre pagella regular } { \scale [scale=5000] { \definedfont[cambria*demo-1]fist effe \par \definedfont[cambria*demo-2]fist effe } } { cambria } { \scale [scale=5000] { \definedfont[ebgaramond12regular*demo-1]fist effe \par \definedfont[ebgaramond12regular*demo-2]fist effe } } { ebgaramond 12 regular } \stopcombination \stopplacefigure Normally the artifacts (as in the fi ligature in ebgaramond as of 2018) will go unnoticed at small sized. Also, when the user has a low res display, printer or when the publishers is one of those who print a scanned \PDF\ the reader might not notice it at all. Most readers don't even know what to look at. \stopsection \startsection[title=A modern Modern] So how can we make an effective set of Latin Modern that fits in todays look and feel. Of course this is a very subjective experiment but we've seen experiments with these fonts before (like these cm super collections). Here is an example of a typescript definition: \starttyping \starttypescriptcollection[modernlatin] \definefontfeature[lm-rm-regular][effect={width=0.15,delta=1.00}] \definefontfeature[lm-rm-bold] [effect={width=0.30,delta=1.00}] \definefontfeature[lm-ss-regular][effect={width=0.10,delta=1.00}] \definefontfeature[lm-ss-bold] [effect={width=0.20,delta=1.00}] \definefontfeature[lm-tt-regular][effect={width=0.15,delta=1.00}] \definefontfeature[lm-tt-bold] [effect={width=0.30,delta=1.00}] \definefontfeature[lm-mm-regular][effect={width=0.15,delta=1.00}] \definefontfeature[lm-mm-bold] [effect={width=0.30,delta=1.00}] \starttypescript [serif] [modern-latin] \definefontsynonym [Serif] [file:lmroman10-regular] [features={default,lm-rm-regular}] \definefontsynonym [SerifItalic] [file:lmroman10-italic] [features={default,lm-rm-regular}] \definefontsynonym [SerifSlanted] [file:lmromanslant10-regular] [features={default,lm-rm-regular}] \definefontsynonym [SerifBold] [file:lmroman10-regular] [features={default,lm-rm-bold}] \definefontsynonym [SerifBoldItalic] [file:lmroman10-italic] [features={default,lm-rm-bold}] \definefontsynonym [SerifBoldSlanted] [file:lmromanslant10-regular] [features={default,lm-rm-bold}] \stoptypescript \starttypescript [sans] [modern-latin] \definefontsynonym [Sans] [file:lmsans10-regular] [features={default,lm-ss-regular}] \definefontsynonym [SansItalic] [file:lmsans10-oblique] [features={default,lm-ss-regular}] \definefontsynonym [SansSlanted] [file:lmsans10-oblique] [features={default,lm-ss-regular}] \definefontsynonym [SansBold] [file:lmsans10-regular] [features={default,lm-ss-bold}] \definefontsynonym [SansBoldItalic] [file:lmsans10-oblique] [features={default,lm-ss-bold}] \definefontsynonym [SansBoldSlanted] [file:lmsans10-oblique] [features={default,lm-ss-bold}] \stoptypescript \starttypescript [mono] [modern-latin] \definefontsynonym [Mono] [file:lmmono10-regular] [features={default,lm-tt-regular}] \definefontsynonym [MonoItalic] [file:lmmono10-italic] [features={default,lm-tt-regular}] \definefontsynonym [MonoSlanted] [file:lmmonoslant10-regular] [features={default,lm-tt-regular}] \definefontsynonym [MonoBold] [file:lmmono10-regular] [features={default,lm-tt-bold}] \definefontsynonym [MonoBoldItalic] [file:lmmono10-italic] [features={default,lm-tt-bold}] \definefontsynonym [MonoBoldSlanted] [file:lmmonoslant10-regular] [features={default,lm-tt-bold}] \stoptypescript \starttypescript [math] [modern-latin] \loadfontgoodies[lm] \definefontsynonym [MathRoman] [file:latinmodern-math-regular.otf] [features={math\mathsizesuffix,lm-mm-regular,mathextra}, goodies=lm] \definefontsynonym [MathRomanBold] [file:latinmodern-math-regular.otf] [features={math\mathsizesuffix,lm-mm-bold,mathextra}, goodies=lm] \stoptypescript \starttypescript [modern-latin] \definetypeface [\typescriptone] [rm] [serif] [modern-latin] [default] \definetypeface [\typescriptone] [ss] [sans] [modern-latin] [default] \definetypeface [\typescriptone] [tt] [mono] [modern-latin] [default] \definetypeface [\typescriptone] [mm] [math] [modern-latin] [default] \quittypescriptscanning \stoptypescript \stoptypescriptcollection \stoptyping We show some more samples now for which we use\type {zapf.tex}. \startbuffer {\tf\samplefile{zapf}}\blank {\bf\samplefile{zapf}}\blank {\it\samplefile{zapf}}\blank {\bi\samplefile{zapf}}\blank {\sl\samplefile{zapf}}\blank {\bs\samplefile{zapf}}\blank \stopbuffer \startsubsubsubject[title={\type{\switchtobodyfont[modern-latin,rm,10pt]}}] \start \switchtobodyfont[modern-latin,rm,10pt] \getbuffer \stop \stopsubsubsubject \startsubsubsubject[title={\type{\switchtobodyfont[modern-latin,ss,10pt]}}] \start \switchtobodyfont[modern-latin,ss,10pt] \getbuffer \stop \stopsubsubsubject \startsubsubsubject[title={\type{\switchtobodyfont[modern-latin,tt,10pt]}}] \start \switchtobodyfont[modern-latin,tt,10pt] \setupalign[flushleft,broad,nothyphenated,verytolerant] \getbuffer \stop \stopsubsubsubject \stopsection \startsection[title=Finetuning] In practice we only need to compensate the width but can leave the height and depth untouched. In the following examples we see the normal bold next to the regular as well as the boldened version. For this we will use a couple of definitions: \startbuffer \definefontfeature[lm-bald][effect={width=0.25,effect=both}] \definefontfeature[pg-bald][effect={width=0.25,effect=both}] \definefontfeature[dj-bald][effect={width=0.35,effect=both}] \definefontfeature [lm-bold] [effect={width=0.25,hdelta=0,ddelta=0,effect=both}, extend=1.10] \definefontfeature [pg-bold] [effect={width=0.25,hdelta=0,ddelta=0,effect=both}, extend=1.00] \definefontfeature [dj-bold] [effect={width=0.35,hdelta=0,ddelta=0,effect=both}, extend=1.05] \definefont[lmbald][Serif*default,lm-bald sa d] \definefont[pgbald][Serif*default,pg-bald sa d] \definefont[djbald][Serif*default,dj-bald sa d] \definefont[lmbold][Serif*default,lm-bold sa d] \definefont[pgbold][Serif*default,pg-bold sa d] \definefont[djbold][Serif*default,dj-bold sa d] \stopbuffer \typebuffer \getbuffer We can combine the extend and effect features to get a bold running as wide as a normal bold. We limit the height and depth so that we can use regular and bold in the same sentence. It's all a matter of taste, but some control is there. \starttabulate[|l|l|l|l|] \NC \BC \tt modern \BC \tt pagella \BC \tt dejavu \NC \NR \NC \type{\tfd} \NC \switchtobodyfont [modern,24pt]\strut\ruledhbox{\tfd ABC}\NC \switchtobodyfont[pagella,24pt]\strut\ruledhbox{\tfd ABC}\NC \switchtobodyfont [dejavu,24pt]\strut\ruledhbox{\tfd ABC}\NC \NR \NC \type{\..bald} \NC \switchtobodyfont [modern,24pt]\strut\ruledhbox{\lmbald ABC}\NC \switchtobodyfont[pagella,24pt]\strut\ruledhbox{\pgbald ABC}\NC \switchtobodyfont [dejavu,24pt]\strut\ruledhbox{\djbald ABC}\NC \NR \NC \type{\bfd} \NC \switchtobodyfont [modern,24pt]\strut\ruledhbox{\bfd ABC}\NC \switchtobodyfont[pagella,24pt]\strut\ruledhbox{\bfd ABC}\NC \switchtobodyfont [dejavu,24pt]\strut\ruledhbox{\bfd ABC}\NC \NR \NC \type{\..bold} \NC \switchtobodyfont [modern,24pt]\strut\ruledhbox{\lmbold ABC}\NC \switchtobodyfont[pagella,24pt]\strut\ruledhbox{\pgbold ABC}\NC \switchtobodyfont [dejavu,24pt]\strut\ruledhbox{\djbold ABC}\NC \NR \stoptabulate Let's take another go at Pagella. We define a few features, colors and fonts first: \startbuffer \definefontfeature [pg-fake-1] [effect={width=0.25,effect=both}] \definefontfeature [pg-fake-2] [effect={width=0.25,hdelta=0,ddelta=0,effect=both}] \definefont[pgregular] [Serif*default] \definefont[pgbold] [SerifBold*default] \definefont[pgfakebolda][Serif*default,pg-fake-1] \definefont[pgfakeboldb][Serif*default,pg-fake-2] \definecolor[color-pgregular] [t=.5,a=1,r=.6] \definecolor[color-pgbold] [t=.5,a=1,g=.6] \definecolor[color-pgfakebolda][t=.5,a=1,b=.6] \definecolor[color-pgfakeboldb][t=.5,a=1,r=.6,g=.6] \stopbuffer \typebuffer \getbuffer When we apply these we get the results of \in {figure} [fig:pagella-compared] while we show the same overlayed in \in {figure} [fig:pagella-overlayed]. As you can see, the difference in real bold and fake bold is subtle: the inner shape of the \quote {o} differs. Also note that the position of the accents doesn't change in the vertical direction but moves along with the width. \def\SampleWord{\^o\"ep\c s} \startplacefigure[title={Four pagella style variants compared.},reference=fig:pagella-compared] \startcombination[2*2] { \scale [scale=7500] { \ruledhbox{\showglyphs\pgregular \SampleWord} } } { regular (red) } { \scale [scale=7500] { \ruledhbox{\showglyphs\pgbold \SampleWord} } } { bold (green) } { \scale [scale=7500] { \ruledhbox{\showglyphs\pgfakebolda \SampleWord} } } { fakebolda (blue) } { \scale [scale=7500] { \ruledhbox{\showglyphs\pgfakeboldb \SampleWord} } } { fakeboldb (yellow) } \stopcombination \stopplacefigure \startplacefigure[title={Four pagella style variants overlayed.},reference=fig:pagella-overlayed] \startcombination[2*3] { \scale [scale=7500] { \startoverlay {\color[color-pgregular] {\pgregular \SampleWord}} {\color[color-pgbold] {\pgbold \SampleWord}} \stopoverlay } } { bold over regular } { \scale [scale=7500] { \startoverlay {\color[color-pgregular] {\pgregular \SampleWord}} {\color[color-pgfakeboldb]{\pgfakeboldb \SampleWord}} \stopoverlay } } { fakebolda over regular } { \scale [scale=7500] { \startoverlay {\color[color-pgregular] {\pgregular \SampleWord}} {\color[color-pgfakebolda]{\pgfakeboldb \SampleWord}} \stopoverlay } } { fakeboldb over regular } { \scale [scale=7500] { \startoverlay {\color[color-pgbold] {\pgbold \SampleWord}} {\color[color-pgfakeboldb]{\pgfakeboldb \SampleWord}} \stopoverlay } } { fakeboldb over bold } { \scale [scale=7500] { \startoverlay {\color[color-pgfakebolda]{\pgfakebolda \SampleWord}} {\color[color-pgfakeboldb]{\pgfakeboldb \SampleWord}} \stopoverlay } } { fakeboldb over fakebolda } { \scale [scale=7500] { \startoverlay {\color[color-pgregular] {\pgregular \SampleWord}} {\color[color-pgbold] {\pgbold \SampleWord}} {\color[color-pgfakebolda]{\pgfakebolda \SampleWord}} {\color[color-pgfakeboldb]{\pgfakeboldb \SampleWord}} \stopoverlay } } { all four overlayed } \stopcombination \stopplacefigure \stopsection \startsection[title=The code] The amount of code involved is not that large and is a nice illustration of what \LUATEX\ provides (I have omitted a few lines of tracing and error reporting). The only thing added to the font scaler elsewhere is that we pass the \type {mode} and \type {width} parameters to \TEX\ so that they get used in the backend to inject the few operators needed. \starttyping local effects = { inner = 0, outer = 1, both = 2, hidden = 3, } local function initialize(tfmdata,value) local spec if type(value) == "number" then spec = { width = value } else spec = utilities.parsers.settings_to_hash(value) end local effect = spec.effect or "both" local width = tonumber(spec.width) or 0 local mode = effects[effect] if mode then local factor = tonumber(spec.factor) or 0 local hfactor = tonumber(spec.vfactor) or factor local vfactor = tonumber(spec.hfactor) or factor local delta = tonumber(spec.delta) or 1 local wdelta = tonumber(spec.wdelta) or delta local hdelta = tonumber(spec.hdelta) or delta local ddelta = tonumber(spec.ddelta) or hdelta tfmdata.parameters.mode = mode tfmdata.parameters.width = width * 1000 tfmdata.properties.effect = { effect = effect, width = width, wdelta = wdelta, factor = factor, hdelta = hdelta, hfactor = hfactor, ddelta = ddelta, vfactor = vfactor, } end end local function manipulate(tfmdata) local effect = tfmdata.properties.effect if effect then local characters = tfmdata.characters local parameters = tfmdata.parameters local multiplier = effect.width * 100 local wdelta = effect.wdelta * parameters.hfactor * multiplier local hdelta = effect.hdelta * parameters.vfactor * multiplier local ddelta = effect.ddelta * parameters.vfactor * multiplier local hshift = wdelta / 2 local factor = (1 + effect.factor) * parameters.factor local hfactor = (1 + effect.hfactor) * parameters.hfactor local vfactor = (1 + effect.vfactor) * parameters.vfactor for unicode, char in next, characters do local oldwidth = char.width local oldheight = char.height local olddepth = char.depth if oldwidth and oldwidth > 0 then char.width = oldwidth + wdelta char.commands = { { "right", hshift }, { "char", unicode }, } end if oldheight and oldheight > 0 then char.height = oldheight + hdelta end if olddepth and olddepth > 0 then char.depth = olddepth + ddelta end end parameters.factor = factor parameters.hfactor = hfactor parameters.vfactor = vfactor end end local specification = { name = "effect", description = "apply effects to glyphs", initializers = { base = initialize, node = initialize, }, manipulators = { base = manipulate, node = manipulate, }, } fonts.handlers.otf.features.register(specification) fonts.handlers.afm.features.register(specification) \stoptyping The real code is slightly more complex because we want to stack virtual features properly but the principle is the same. \stopsection \startsection[title=Arabic] It is tempting to test effects with arabic but we need to keep in mind that for that we should add some more support in the \CONTEXT\ font handler. Let's define some features. \startbuffer \definefontfeature [bolden-arabic-1] [effect={width=0.4}] \definefontfeature [bolden-arabic-2] [effect={width=0.4,effect=outer}] \definefontfeature [bolden-arabic-3] [effect={width=0.5,wdelta=0.5,ddelta=.2,hdelta=.2,factor=.1}] \stopbuffer \typebuffer \getbuffer \startbuffer \setupalign [righttoleft] \setupinterlinespace [1.5] \start \definedfont[arabictest*arabic,bolden-arabic-1 @ 30pt] \samplefile{khatt-ar}\par \definedfont[arabictest*arabic,bolden-arabic-2 @ 30pt] \samplefile{khatt-ar}\par \definedfont[arabictest*arabic,bolden-arabic-3 @ 30pt] \samplefile{khatt-ar}\par \stop \stopbuffer With \MICROSOFT\ Arabtype the \type {khatt-ar.tex} looks as follows: \typebuffer \start \definefontsynonym[arabictest][arabtype] \getbuffer\stop And with Idris' Husayni we get: \typebuffer \start \definefontsynonym[arabictest][husayni] \getbuffer\stop Actually, quite okay are the following. We don't over do bold here and to get a distinction we make the original thinner. \startbuffer \definefontfeature[effect-ar-thin] [effect={width=0.01,effect=inner}] \definefontfeature[effect-ar-thick][effect={width=0.20,extend=1.05}] \stopbuffer \typebuffer \getbuffer \start \setupalign [righttoleft] \setupinterlinespace [1.5] \definedfont[husayni*arabic,effect-ar-thin @ 30pt] \samplefile{khatt-ar}\par \definedfont[husayni*arabic,effect-ar-thick @ 30pt] \samplefile{khatt-ar}\par \stop The results are acceptable at small sizes but at larger sizes you will start to see kerning, anchoring and cursive artifacts. The outline examples show that the amount of overlap differs per font and the more overlap we have the better boldening will work. \startMPinclusions def DrawShapes(expr how) = def SampleShapes(expr offset, pw, xc, xs, xt, yc, ys, yt, txt, more) = numeric l ; l := pw * mm ; picture p ; p := image ( draw fullcircle scaled 10 ; draw fullcircle scaled 3 shifted (-3+xc ,8+yc) withcolor "darkred" ; draw fullsquare scaled 3 shifted ( 6+xs ,7+ys) withcolor "darkblue"; draw fulltriangle scaled 4 shifted ( 6+xt+5,6+yt) withcolor "darkgreen"; ) shifted (offset,0) scaled mm ; draw p withpen pencircle if how = 2 : xscaled l yscaled (l/2) rotated 30 ; else : scaled l ; fi ; draw boundingbox p withcolor "darkyellow" ; draw textext(txt) shifted (xpart center p, -8mm) ; draw textext(more) shifted (xpart center p, -11mm) ; enddef ; SampleShapes( 0,1, 0,0,0, 0, 0, 0, "\tinyfont \setstrut \strut original", "\tinyfont \setstrut \strut ") ; SampleShapes( 25,2, 0,0,0, 0, 0, 0, "\tinyfont \setstrut \strut instance", "\tinyfont \setstrut \strut ") ; SampleShapes( 50,2,-1,1,0, 0, 0, 0, "\tinyfont \setstrut \strut mark", "\tinyfont \setstrut \strut x only") ; SampleShapes( 75,2,-1,1,1, 0, 0, 0, "\tinyfont \setstrut \strut mark + mkmk","\tinyfont \setstrut \strut x only") ; SampleShapes(100,2,-1,1,1, 1, 1, 1, "\tinyfont \setstrut \strut mark + mkmk","\tinyfont \setstrut \strut x and y") ; SampleShapes(125,2,-1,2,2,-1/2,-1/2,-1/2,"\tinyfont \setstrut \strut mark + mkmk","\tinyfont \setstrut \strut x and -y") ; enddef ; \stopMPinclusions In arabic (and sometimes latin) fonts the marks (or accents in latin) are attached to base shapes and normally one will use the \type {mark} to anchor a mark to a base character or specific component of a ligature. The \type {mkmk} feature is then used to anchor marks to other marks. Consider the following example. \startlinecorrection \scale [width=\textwidth] {\startMPcode DrawShapes(1) ; \stopMPcode} \stoplinecorrection We start with \type {original}: a base shape with three marks: the red circle and blue square anchor to the base and the green triangle anchors to the blue square. When we bolden, the shapes will start touching. In the case of latin scripts, it's normal to keep the accents on the same height so this is why the third picture only shifts in the horizontal direction. The fourth picture demonstrates that we need to compensate the two bound marks. One can decide to move the lot up as in the fifth picture but that is no option here. Matters can be even more complex when a non circular pen is introduced. In that case a transformation from one font to another using the transformed \OPENTYPE\ positioning logic (values) is even more tricky and unless one knows the properties (and usage) of a mark it makes no sense at all. Actually the sixths variant is probably nicer here but there we actually move the marks down! \startlinecorrection \scale [width=\textwidth] {\startMPcode DrawShapes(2) ; \stopMPcode} \stoplinecorrection For effects this means that when it gets applied to such a font, only small values work out well. \stopsection \startsection[title=Math] Math is dubious as there is all kind of positioning involved. Future versions might deal with this, although bolder math (math itself has bold, so actually we're talking of bold with some heavy) is needed for titling. If we keep that in mind we can actually just bolden math and probably most will come out reasonable well. One of the potential troublemakers is the radical (root) sign that can be bound to a rule. Bumping the rules is no big deal and patching the relevant radical properties neither, so indeed we can do: \startbuffer[mathblob] 2\times\sqrt{\frac{\sqrt{\frac{\sqrt{2}}{\sqrt{2}}}} {\sqrt{\frac{\sqrt{2}}{\sqrt{2}}}}} \stopbuffer \startbuffer \switchtobodyfont [modernlatin,17.3pt] $ \mr \darkblue \getbuffer[mathblob] \quad \mb \darkgreen \getbuffer[mathblob] $ \stopbuffer \typebuffer \blank \start \getbuffer \stop \blank Where the \type {mathblob} buffer is: \typebuffer[mathblob] Here you also see a fraction rule that has been bumped. In display mode we get: \startbuffer \switchtobodyfont[modernlatin,17.3pt] \startformula \mr \darkblue \getbuffer[mathblob] \quad \mb \darkgreen \getbuffer[mathblob] \stopformula \stopbuffer \typebuffer \blank \start \getbuffer \stop \blank Extensibles behave well too: \startbuffer \switchtobodyfont [modernlatin,17.3pt] \dostepwiserecurse {1} {30} {5} { $ \mr \sqrt{\blackrule[width=2mm,height=#1mm,color=darkblue]} \quad \mb \sqrt{\blackrule[width=2mm,height=#1mm,color=darkgreen]} $ } \stopbuffer \typebuffer \blank \start \getbuffer \stop \blank \definecolor[colormr] [t=.5,a=1,b=.6] \definecolor[colormb] [t=.5,a=1,g=.6] In \in {figure} [fig:regular-over-bold] we overlay regular and bold. The result doesn't look that bad after all, does it? It took however a bit of experimenting and a fix in \LUATEX: pickup the value from the font instead of the currently used (but frozen) math parameter. \startplacefigure[title={Modern Latin regular over bold.},reference=fig:regular-over-bold] \switchtobodyfont[modernlatin,17.3pt] \scale[width=.25\textwidth]{\startoverlay {\color[colormb]{$\mb\sqrt{\frac{1}{x}}$}} {\color[colormr]{$ \sqrt{\frac{1}{x}}$}} \stopoverlay} \stopplacefigure In case you wonder how currently normal Latin Modern bold looks, here we go: \startbuffer \switchtobodyfont[latinmodern,17.3pt] \startformula \mr \darkblue \getbuffer[mathblob] \quad \mb \darkgreen \getbuffer[mathblob] \stopformula \stopbuffer \typebuffer \blank \start \getbuffer \stop \blank \unexpanded\def\ShowMathSample#1% {\switchtobodyfont[#1,14.4pt]% \mathematics{% \mr \darkblue \getbuffer[mathblob] \quad \mb \darkgreen \getbuffer[mathblob] }} \unexpanded\def\ShowMathCaption#1% {\switchtobodyfont[#1]% #1: $ {\mr2\enspace \scriptstyle2\enspace \scriptscriptstyle2} \enspace {\mb2\enspace \scriptstyle2\enspace \scriptscriptstyle2} $} \startcombination[3*2] {\ShowMathSample {dejavu}} {\ShowMathCaption{dejavu}} {\ShowMathSample{pagella}} {\ShowMathCaption{pagella}} {\ShowMathSample {termes}} {\ShowMathCaption{termes}} {\ShowMathSample {bonum}} {\ShowMathCaption{bonum}} {\ShowMathSample {schola}} {\ShowMathCaption{schola}} {\ShowMathSample{cambria}} {\ShowMathCaption{cambria}} \stopcombination I must admit that I cheat a bit. In order to get a better looking pseudo math we need to extend the shapes horizontally as well as squeeze them a bit vertically. So, the real effect definitions more look like this: \starttyping \definefontfeature [boldened-30] [effect={width=0.3,extend=1.15,squeeze=0.985,% delta=1,hdelta=0.225,ddelta=0.225,vshift=0.225}] \stoptyping and because we can calculate the funny values sort of automatically, this gets simplified to: \starttyping \definefontfeature [boldened-30] [effect={width=0.30,auto=yes}] \stoptyping We leave it to your imagination to figure out what happens behind the screens. Just think of some virtual font magic combined with the engine supported \type {extend} and \type {squeeze} function. And because we already support bold math in \CONTEXT, you will get it when you are doing bold titling. \startbuffer \def\MathSample {\overbrace{2 + \sqrt{\frac{\sqrt{\frac{\sqrt{2}}{\sqrt{2}}}} {\sqrt{\frac{\sqrt{\underbar{2}}}{\sqrt{\overbar{2}}}}}}}} \definehead [mysubject] [subject] \setuphead [mysubject] [style=\tfc, color=darkblue, before=\blank, after=\blank] \mysubject{Regular\quad$\MathSample\quad\mb\MathSample$} \setuphead [mysubject] [style=\bfc, color=darkred] \mysubject{Bold \quad$\MathSample\quad\mb\MathSample$} \stopbuffer \typebuffer \getbuffer Of course one can argue about the right values for boldening and compensation if dimensions so don't expect the current predefined related features to be frozen yet. For sure this mechanism will create more fonts than normal but fortunately it can use the low level optimizations for sharing instances so in the end the overhead is not that large. This chapter uses 36 different fonts, creates 270 font instances (different scaling and properties) of which 220 are shared in the backend. The load time is 5 seconds in \LUATEX\ and 1.2 seconds in \LUAJITTEX\ on a somewhat old laptop with a i7-3840QM processor running 64 bit \MSWINDOWS. Of course we load a lot of bodyfonts at different sizes so in a normal run the extra loading is limited to just a couple of extra instances for math (normally 3, one for each math size). \stopsection \startsection[title=Conclusion] So what can we conclude? When we started with \LUATEX, right from the start \CONTEXT\ supported true \UNICODE\ math by using virtual \UNICODE\ math fonts. One of the objectives of the \TEX Gyre project is to come up with a robust complete set of math fonts, text fonts with a bunch of useful symbols, and finally a subset bold math font for titling. Now we have real \OPENTYPE\ math fonts, although they are still somewhat experimental. Because we're impatient, we now provide bold math by using effects but the future will learn to what extent the real bold math fonts will differ and be more pleasant to look at. After all, what we describe he is just an experiment that got a bit out of hands. % And if you wonder if this kind of messing with fonts is okay? Well, you don't % know what specs we sometimes get (and then ignore). \stopsection \stopchapter \stopcomponent