diff options
author | Context Git Mirror Bot <phg42.2a@gmail.com> | 2016-07-25 22:53:51 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg42.2a@gmail.com> | 2016-07-25 22:53:51 +0200 |
commit | 9d7c4ba8449bec1da920c01e24a17c41bbf2211d (patch) | |
tree | bc2c540cb485132a4fc3d0baabeac4d88b3c4af8 /doc/context/sources/general/fonts | |
parent | e5255a951b23372f4f0ad58b9afc38ba3929becf (diff) | |
download | context-9d7c4ba8449bec1da920c01e24a17c41bbf2211d.tar.gz |
2016-07-25 21:54:00
Diffstat (limited to 'doc/context/sources/general/fonts')
16 files changed, 10126 insertions, 0 deletions
diff --git a/doc/context/sources/general/fonts/fonts/fonts-appendix.tex b/doc/context/sources/general/fonts/fonts/fonts-appendix.tex new file mode 100644 index 000000000..ae42b10fa --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-appendix.tex @@ -0,0 +1,484 @@ +% language=uk + +\startcomponent fonts-appendix + +\environment fonts-environment + +\startchapter[title=Appendix][color=darkgray] + +\startsection[title=The \type {tfm} file,reference=fontdata:tfm] + +The (binary) \type {tfm} file is not human readable but can be turned into a +verbose property list which is not that hard to understand. + +\starttyping +tftopl texnansi-lmr10.tfm +\stoptyping + +Here is an excerpt from the data file. It starts with some general properties of +the font. The \type {O} means that the value is in octal while the \type {R} is a +real. Keep in mind that \TEX\ has no datatype \quote {real} so internally it is +just integers representing scaled points. + +\startnarrowtyping +(FAMILY LMROMAN10) +(FACE O 352) +(CODINGSCHEME LY1 ENCODING /TEX'N'ANSI, Y&Y/) +(DESIGNSIZE R 10.0) +(COMMENT DESIGNSIZE IS IN POINTS) +(COMMENT OTHER SIZES ARE MULTIPLES OF DESIGNSIZE) +(CHECKSUM O 4720464277) +\stopnarrowtyping + +A text font has the following font dimensions: + +\startnarrowtyping +(FONTDIMEN + (SLANT R 0.0) + (SPACE R 0.333333) + (STRETCH R 0.166667) + (SHRINK R 0.111112) + (XHEIGHT R 0.43055) + (QUAD R 1.0) + (EXTRASPACE R 0.111112) + ... +) +\stopnarrowtyping + +Kerns and ligatures are packed into a table that is basically a sequence of +labelled entries. Here we see the entry for the character \type {f} which has +three ligatures: \type {ff}, \type {fi} and \type {fl}. Because ligatures can be +chained, octal slot 13 will have ligature entries for \type {ffl} and \type +{ffi}. + +\startnarrowtyping +(LIGTABLE + ... + (LABEL C f) + (LIG C f O 13) + (LIG C i O 14) + (LIG C l O 10) + (KRN O 135 R 0.027779) + (KRN O 41 R 0.027779) + (KRN O 51 R 0.027779) + (KRN O 77 R 0.027779) + (KRN O 223 R 0.027779) + (KRN O 224 R 0.027779) + (KRN O 140 R 0.027779) + (KRN O 47 R 0.027779) + (STOP) + ... +) +\stopnarrowtyping + +Each character gets its own entry. In this case there is no depth involved so it +is not shown. The comment is just a repetition of the entry in the ligtable. + +\startnarrowtyping +(CHARACTER C f + (CHARWD R 0.30555) + (CHARHT R 0.688875) + (CHARIC R 0.079222) + (COMMENT + (LIG C f O 13) + (LIG C i O 14) + (LIG C l O 10) + (KRN O 135 R 0.027779) + (KRN O 41 R 0.027779) + (KRN O 51 R 0.027779) + (KRN O 77 R 0.027779) + (KRN O 223 R 0.027779) + (KRN O 224 R 0.027779) + (KRN O 140 R 0.027779) + (KRN O 47 R 0.027779) + ) +) +\stopnarrowtyping + +\stopsection + +\startsection[title=The \type {vf} file,reference=fontdata:vf] + +A virtual font specification file can be converted to a more readable format with +\type {vftovp}, for instance: + +\starttyping +vftovp eurm10.vf +\stoptyping + +The information in a \type {vf} file will be combined with the data in the +accompanying \type {tfm} file so the output looks similar: + +\startnarrowtyping +(VTITLE ) +(FAMILY UNSPECIFIED) +(FACE F MRR) +(CODINGSCHEME TEX MATH ITALIC) +(DESIGNSIZE R 10.0) +(COMMENT DESIGNSIZE IS IN POINTS) +(COMMENT OTHER SIZES ARE MULTIPLES OF DESIGNSIZE) +(CHECKSUM O 24401046203) +(SEVENBITSAFEFLAG TRUE) +\stopnarrowtyping + +Because this font is a math font there is no space defined. + +\startnarrowtyping +(FONTDIMEN + (SLANT R 0.0) + (SPACE R 0.0) + (STRETCH R 0.0) + (SHRINK R 0.0) + (XHEIGHT R 0.459) + (QUAD R 1.0) + (EXTRASPACE R 0.0) +) +\stopnarrowtyping + +A virtual font will take glyphs from another font and therefore there are entries +that refer to these fonts. In the following definition index \type {0} is created +(the \type {D} specifies a decimal entry). + +\startnarrowtyping +(MAPFONT D 0 + (FONTNAME eurm10) + (FONTCHECKSUM O 4276740471) + (FONTAT R 1.0) + (FONTDSIZE R 10.0) +) +(MAPFONT D 1 + (FONTNAME cmmi10) + (FONTCHECKSUM O 1350061076) + (FONTAT R 1.0) + (FONTDSIZE R 10.0) +) +\stopnarrowtyping + +The zero indexed font is the default, so in the following entry this font is +taken: + +\startnarrowtyping +(CHARACTER C W + (CHARWD R 0.986) + (CHARHT R 0.691) + (CHARIC R 0.056) + (COMMENT + (KRN O 177 R 0.056) + (KRN O 75 R -0.056) + (KRN O 73 R -0.083) + (KRN O 72 R -0.083) + ) + (MAP + (SETCHAR C W) + ) +) +\stopnarrowtyping + +The next specification is a combination of two other glyphs becoming a new +glyph. We see here that the \type {MAP} table is actually a sort of program: + +\startnarrowtyping +(CHARACTER O 200 + (CHARWD R 0.622) + (CHARHT R 0.691) + (MAP + (PUSH) + (MOVEDOWN R -0.18) + (MOVERIGHT R 0.015) + (SELECTFONT D 2) + (SETCHAR O 40) + (POP) + (SELECTFONT D 0) + (SETCHAR C h) + ) +) +\stopnarrowtyping + +The character information is also in the \type {tfm} companion and that is what +\TEX\ uses. The virtual information kicks in when the backend is creating the +page stream and embedding the fonts. + +\stopsection + +\startsection[title=The \type {map} file,reference=fontdata:map] + +In a map file each line maps a font name onto a file that contains the font +shapes in bitmap or outline format. For instance in the file \type +{lm-texnansi.map} we find the line: + +\startnarrowtyping +texnansi-lmr10 LMRoman10-Regular "enclmtexnansi ReEncodeFont" <lm-texnansi.enc <lmr10.pfb +\stopnarrowtyping + +The backend will fetch the glyph data from \type {lmf10.pfb} and use the given +encoding file to resolve indices to glyph names. A \type {pfb} file can contain +more than 256 entries so names are used to access the data. The string between +quotes is used for the encoding vector in the resulting file. + +The second entry in the line is the font name that will be used. This name is +also used to control subset behaviour. Multiple references to this name will be +collapsed into one inclusion when possible, thereby making the file as small as +possible. You better make sure that the names are unique for a specific font. + +In addition to this, there can be directives for extending the font (horizontal +stretch) and transforming it into a slanted variant. Both are to be used with +care. + +In \MKIV\ map files are only used for virtual math fonts and just as in \MKII\ we +load such files selectively. Users don't have to worry about this. + +\stopsection + +\startsection[title=The \type {enc} file,reference=fontdata:enc] + +For historic reasons, an encoding file is a blob of \POSTSCRIPT, probably because +it can be copied into the final output directly. Given that \TEX\ got extended +anyway, you can wonder why this information never ended up in an extended \type +{tfm} or \type {vf} file. It had definitely made the traditional process much +more robust. + +\startnarrowtyping +/enclmtexnansi[ +/.notdef +/Euro +... +/dotaccent +/hungarumlaut +/ogonek +... +/ffi +/ffl +/dotlessi +/dotlessj +/grave +... +/thorn +/ydieresis +] def +\stopnarrowtyping + +There are excactly 256 entries in such a vector and the names should match those +in a \type {pfb} file. + +\stopsection + +\startsection[title=The \type {afm} file,reference=fontdata:afm] + +Here we show an excerpt from an \type {afm} file that comes with Latin Modern +Roman. Just as with a \type {tfm} file we start with some general information. +However we don't need to convert the file as is it already in human readable +format. + +\startnarrowtyping +StartFontMetrics 2.0 +Comment Generated by MetaType1 (a MetaPost-based engine) +Comment Creation Date: 7th October 2009 +Notice Copyright 2003--2009 by B. Jackowski and J.M. Nowacki (on behalf of TeX USERS GROUPS). +Comment Supported by CSTUG, DANTE eV, GUST, GUTenberg, NTG, and TUG. +Comment METATYPE1/Type 1 version by B. Jackowski & J. M. Nowacki +Comment from GUST (http://www.gust.org.pl). +Comment This work is released under the GUST Font License. +Comment For the most recent version of this license see +Comment This work has the LPPL maintenance status `maintained'. +Comment The Current Maintainer of this work is Bogus\l{}aw Jackowski and Janusz M. Nowacki. +Comment This work consists of the files listed in the MANIFEST-Latin-Modern.txt file. +FontName LMRoman10-Regular +FullName LMRoman10-Regular +FamilyName LMRoman10 +Weight Normal +ItalicAngle 0 +IsFixedPitch false +UnderlinePosition -146 +UnderlineThickness 40 +Version 2.004 +EncodingScheme FontSpecific +FontBBox -430 -290 1417 1127 +CapHeight 683.33333 +XHeight 430.55556 +Descender -194.44444 +Ascender 694.44444 +Comment PFM parameters: LMRoman10 0 0 0xEE +Comment TFM designsize: 10 (in points) +Comment TFM fontdimen 1: 0 (slant) +Comment TFM fontdimen 2: 3.33333 (space) +Comment TFM fontdimen 3: 1.66667 (space stretch) +Comment TFM fontdimen 4: 1.11111 (space shrink) +Comment TFM fontdimen 5: 4.3055 (xheight) +Comment TFM fontdimen 6: 10 (quad) +Comment TFM fontdimen 7: 1.11111 (extra space) +Comment TFM fontdimen 8: 6.833 (non-standard: uc height) +Comment TFM fontdimen 9: 6.9445 (non-standard: ascender) +Comment TFM fontdimen 10: 11.27 (non-standard: accented cap height) +Comment TFM fontdimen 11: 1.94443 (non-standard: descender depth) +Comment TFM fontdimen 12: 11.27 (non-standard: max height) +Comment TFM fontdimen 13: 2.9 (non-standard: max depth) +Comment TFM fontdimen 14: 5 (non-standard: digit width) +Comment TFM fontdimen 15: 0.88889 (non-standard: uc stem) +Comment TFM fontdimen 16: 12 (non-standard: baselineskip) +Comment TFM fontdimen 17: 0.69444 (non-standard: lc stem) +Comment TFM fontdimen 18: 0.55556 (non-standard: u, i.e., font unit) +Comment TFM fontdimen 19: 0.22223 (non-standard: overshoot) +Comment TFM fontdimen 20: 0.25 (non-standard: thin stem, hair) +Comment TFM fontdimen 21: 0.30556 (non-standard: cap thin stem, i.e., cap_hair) +Comment TFM headerbyte 9: FontSpecific +Comment TFM headerbyte 49: LMRoman10 +Comment TFM headerbyte 72: 234 +\stopnarrowtyping + +Watch the comments! Because \TEX\ needs a couple of so called fontdimens to be +set, the comments list the appropriate values. When a \type {tfm} file is +generated from an \type {afm} file, these values have to be used. + +Each character (or glyph) gets an entry. When we run out of indices i.e.\ pass +the 255 boundary (we start at 0) the index becomes \type {-1}. Only the width is +specified. The height and depth have to be derived from the bounding box for +which the specification starts with key \type {B}. + +\startnarrowtyping +StartCharMetrics 821 +... +C 32 ; WX 333.33333 ; N space ; B 0 0 0 0 ; +... +C 102 ; WX 305.55556 ; N f ; B 33 0 357 705 ; L f ff ; L i fi ; L k f_k ; L l fl ; +C 105 ; WX 277.77777 ; N i ; B 33 0 247 657 ; +C 108 ; WX 277.77777 ; N l ; B 33 0 255 694 ; +... +C -1 ; WX 500 ; N Acute ; B 181 493 388 656 ; +C -1 ; WX 500 ; N acute ; B 188 510 374 698 ; +C -1 ; WX 500 ; N acute.ts1 ; B 208 513 392 699 ; +... +EndCharMetrics +\stopnarrowtyping + +Watch how this font defines a space character and keep in mind that these fonts +date from the time that there was only one kind of space. The \type {L} entry +specifies a ligature. + +The names of glyphs are standardized, and even the \type {f_k} is conforming to +standards. This standardization makes it possible to go back from glyphs to characters +when copying text from a typeset document. + +The kern table is pretty large here and for a reason. First of all the file +defines 821 glyphs so the average amount of kerns per glyph is not that large. +But take a look at the \type {A}. Because the \type {Aacute} has the same shape +it kerns in a similar way. This means that ideally all combined characters end up +with the same value as their base glyph. However, in our case a bit more +selective approach is taken. The \type {Adieresis} has a different set of kerns, +probably to save space. It is for this reason that \OPENTYPE\ fonts have a model +of kern classes so that similar shapes can be treated as one when setting kerns. +You see a similar issue with ligatures, where often the right part of the shape +kerns the same as the (stand alone) first part of the shape does. + +\startnarrowtyping +StartKernData +StartKernPairs 9230 +... +KPX seven.prop hyphen.prop -37 +KPX seven.prop four.prop -74 +KPX seven.prop six.prop -18.5 +KPX hyphen.prop one.prop -37 +KPX hyphen.prop two.prop -18.5 +KPX hyphen.prop seven.prop -55.5 +KPX seven.oldstyle four.oldstyle -74 +KPX A T -83.333 +KPX Aacute T -83.333 +KPX Abreve T -83.333 +KPX Acircumflex T -83.333 +... +KPX Adieresis C -27.778 +... +KPX f bracketright 27.778 +KPX f exclam 27.778 +KPX f parenright 27.778 +KPX f question 27.778 +KPX f quotedblleft 27.778 +KPX f quotedblleft.cm 27.778 +KPX f quotedblright 27.778 +KPX f quotedblright.cm 27.778 +KPX f quoteleft 27.778 +KPX f quoteright 27.778 +... +KPX ff bracketright 27.778 +KPX ff exclam 27.778 +KPX ff parenright 27.778 +KPX ff question 27.778 +KPX ff quotedblleft 27.778 +KPX ff quotedblleft.cm 27.778 +KPX ff quotedblright 27.778 +KPX ff quotedblright.cm 27.778 +KPX ff quoteleft 27.778 +KPX ff quoteright 27.778 +... +EndKernPairs +EndKernData +\stopnarrowtyping + +If you look closely at the names, you will notice that some glyphs have a +variant. In \OPENTYPE\ fonts these variants are grouped in features like \type +{oldstyle}. The first part of such a name is still part of the standardization, +but the second part is up to the font designer. + +The file ends with: + +\startnarrowtyping +EndFontMetrics +\stopnarrowtyping + +\stopsection + +\startsection[title=The \type {otf} file,reference=fontdata:otf] + +In the \LUATEX\ manual you can find an overview of the raw \OTF\ format as +exposed in a \LUA\ table. The first decade of \LUATEX\ we used the built|-|in +loader but even then in \CONTEXT\ we didn't use that format directly but used it +to create a more compact and efficient table instead. The current release of +\CONTEXT\ uses its own loader written in \LUA, but the fundamentals have not +changed much. The tables are cached and can be read in at high speed. The +structure of the tables is unlikely to change much although more data might get +added. Although you can access the data it seldom makes sense to do so. Where +needed interfaces are provided. + +\stopsection + +\startsection[title=The \type {lfg} file,reference=fontdata:lua] + +We use the goodies file control what gets added, replaced, patched or manipulated +in a font. A goodie file permits us to go beyond what font provide by default. +The content of a goodie file differs per font. As we also use this for +experiments, not all entries that you find in such files are meant for users. + +\stopsection + +\startsection[title=Used fonts] + +The examples in the document depend on the fonts used. Here is a list of fonts used +to render this version. Because fonts might have changed in the meantime, some examples +might come out other than intended. + +\startluacode +local list = table.load("fonts-mkiv-usedfonts.lua") + +local NC, NR = context.NC, context.NR + +for i=1,#list do + local l = list[i] + context.starttabulate { "|lB|l|" } + local basename = string.lower(file.basename(l.filename)) + local version = string.lower(l.version) + local filesize = (l.size or 0) / 1000 .. " Kb" + local instances = l.instances or 1 + NC() context("filename") NC() context.type(basename) NC() NR() + NC() context("instances") NC() context.type(instances) NC() NR() + NC() context("filesize") NC() context.type(filesize) NC() NR() + NC() context("version") NC() context.type(version) NC() NR() + context.stoptabulate() +end + +\stopluacode + +\stopsection + +\stopchapter + +\stopcomponent + diff --git a/doc/context/sources/general/fonts/fonts/fonts-environment.tex b/doc/context/sources/general/fonts/fonts/fonts-environment.tex new file mode 100644 index 000000000..971da452d --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-environment.tex @@ -0,0 +1,30 @@ +\startenvironment fonts-environment + + \environment manuals-explaining-environment + \environment manuals-explaining-cover + + \usemodule [s] [fonts-tables] + \usemodule [s] [fonts-missing] + \usemodule [s] [fonts-vectors] + \usemodule [s] [fonts-features] + \usemodule [s] [math-extensibles] + + \definefontfeature[demo-onum][kern=yes,onum=yes] + %definefontfeature[demo-lnum][kern=yes,lnum=yes] + \definefontfeature[demo-tnum][kern=yes,tnum=yes] + \definefontfeature[demo-pnum][kern=yes,pnum=yes] + \definefontfeature[demo-zero][zero=yes] + \definefontfeature[demo-none][] + + \definefont[DemoOnumLM][file:lmroman10-regular*demo-onum at 42pt] + %definefont[DemoLnumLM][file:lmroman10-regular*demo-lnum at 42pt] + \definefont[DemoTnumLM][file:lmroman10-regular*demo-tnum at 42pt] + \definefont[DemoPnumLM][file:lmroman10-regular*demo-pnum at 42pt] + + \definefont[DemoZeroLM][file:lmroman10-regular*demo-zero at 42pt] + \definefont[DemoNoneLM][file:lmroman10-regular*demo-none at 42pt] + + \definefont[DemoZeroLT][file:lmtypewriter10-regular*demo-zero at 42pt] + \definefont[DemoNoneLT][file:lmtypewriter10-regular*demo-none at 42pt] + +\stopenvironment diff --git a/doc/context/sources/general/fonts/fonts/fonts-extensions.tex b/doc/context/sources/general/fonts/fonts/fonts-extensions.tex new file mode 100644 index 000000000..2742b1ce0 --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-extensions.tex @@ -0,0 +1,2312 @@ +% language=uk + +\startcomponent fonts-extensions + +\environment fonts-environment + +\startchapter[title=Extensions][color=darkorange] + +\startsection[title=Introduction] + +One of the benefits of using \TEX\ is that you can add your own features and try +to optimize the look and feel. Of course this can also go wrong and output can +look pretty awful when you don't know what you're doing, but on the average it +works out well. In many aspects the move to an \UNICODE\ data path and \OPENTYPE\ +fonts is a good one and solves a lot of problems with traditional \TEX\ engines +and helps us to avoid complex and ugly hacks. But, if you look into the source +code of \CONTEXT\ you will notice that there's still quite some complex coding +needed. This is because we want to control mechanisms, even if it's only for +dealing with some border cases. It's also the reason why \LUATEX\ is what it is: +an extensible engine, building on tradition. + +As always with \TEX, fonts are an area where many tuning happens and this is also +true in \CONTEXT. In this chapter some of the extensions will be discussed. Some +extensions run on top of the (rather generic) feature mechanism and some are +using dedicated code. + +\stopsection + +\startsection[title=Italics] + +Although \OPENTYPE\ fonts are more rich in features than traditional \TEX\ and +\TYPEONE\ fonts, one important feature is missing: italic correction. This might +sound strange but you need to keep in mind that in practice it's a feature that +needs to be applied manually. + +\starttyping +test {\it test\/} test +\stoptyping + +It is possible to automate this mechanism and this is what the \type {\em} command +does in \MKII: + +\starttyping +test {\em test} test +\stoptyping + +This command knows that it switches to italic (or slanted) and when used nested it +knows to switch back. It also knows if a bold italic or slanted font is used. Therefore +it can add italic correction between an italic and upright shape. + +An italic correction is bound to a glyph and bound to a font. In \in {figure} +[latinmodern-italic] we see how an italic shape extends out of the bounding box. +This is not the case in Dejavu: watch \in {figure} [dejavu-italic]. + +\startplacefigure[reference=latinmodern-italic,title={Italic overshoot in Latin Modern.}] + \startcombination + \startcontent + \backgroundline[gray]{\color[maincolor]{\definedfont[lmroman10-regular*default sa 8]test}} + \stopcontent + \startcaption + Latin Modern Roman Regular + \stopcaption + \startcontent + \backgroundline[gray]{\color[maincolor]{\definedfont[lmroman10-italic*default sa 8]test}} + \stopcontent + \startcaption + Latin Modern Roman Italic + \stopcaption + \stopcombination +\stopplacefigure + +\startplacefigure[reference=dejavu-italic,title={Italic overshoot in Dejavu Serif.}] + \startcombination + \startcontent + \backgroundline[gray]{\color[maincolor]{\definedfont[dejavuserif*default sa 8]test}} + \stopcontent + \startcaption + Dejavu Regular + \stopcaption + \startcontent + \backgroundline[gray]{\color[maincolor]{\definedfont[dejavuserifitalic*default sa 8]test}} + \stopcontent + \startcaption + Dejavu Italic + \stopcaption + \stopcombination +\stopplacefigure + +This means that the application of italic correction should never been applied without +knowing the font. In \in {figure} [italic-upright] we see an upright word following +an italic. The space is determined by the upright one. + +\startplacefigure[reference=italic-upright,title={Italic followed by upright.}] + \startcombination + \startcontent + \backgroundline + [gray] + {\color[maincolor]{\definedfont[lmroman10-italic*default sa 4]test} + \color[maincolor]{\definedfont[lmroman10-regular*default sa 4]\space test}} + \stopcontent + \startcaption + Latin Modern + \stopcaption + \startcontent + \backgroundline + [gray] + {\color[maincolor]{\definedfont[dejavuserifitalic*default sa 4]test}% + \color[maincolor]{\definedfont[dejavuserif*default sa 4]\space test}} + \stopcontent + \startcaption + Dejavu + \stopcaption + \stopcombination +\stopplacefigure + +Because it is to be used with care you need to enable this feature per font, You +also need to explicitly enable the application of this correction. in \in {figure} +[italic-one] we see italic correction in action. + +\startbuffer +\definefontfeature + [italic] + [default] + [itlc=yes] +\stopbuffer + +\typebuffer + +\getbuffer + +\startplacefigure[reference=italic-one,title={Italic correction.}] + \startcombination + \startcontent + \backgroundline + [maincolor] + {\color[white]{\definedfont[lmroman10-italic*default sa 4]test} + \color[white]{\definedfont[lmroman10-regular*default sa 4]\space test}} + \stopcontent + \startcaption + \backgroundline + [maincolor] + {\setupitaliccorrection[text]% + \color[white]{\definedfont[lmroman10-italic*italic sa 4]test} + \color[white]{\definedfont[lmroman10-regular*default sa 4]\space test}} + \stopcaption + \startcontent + \backgroundline + [maincolor] + {\color[white]{\definedfont[dejavuserifitalic*default sa 4]test} + \color[white]{\definedfont[dejavuserif*default sa 4]\space test}} + \stopcontent + \startcaption + \backgroundline + [maincolor] + {\setupitaliccorrection[text]% + \color[white]{\definedfont[dejavuserifitalic*italic sa 4]test} + \color[white]{\definedfont[dejavuserif*default sa 4]\space test}} + \stopcaption + \stopcombination +\stopplacefigure + +This only signals the font constructor that additional italic information has +to be added to the font metrics. As we already mentioned, the application of +correction is driven by the \type {\/} primitive and that one consults the +font metrics. Because the correction is not part of the original font +metrics it is calculated automatically by adding a small value to the +width. This value is calculated as follows: + +\starttyping +factor * (parameters.uwidth or 40) / 2 +\stoptyping + +The \type {uwidth} parameter is sometimes part of the specification but if not, we +take a reasonable default. The factor is under user control: + +\startbuffer +\definefontfeature + [moreitalic] + [default] + [itlc=5] +\stopbuffer + +\typebuffer + +\getbuffer + +This is demonstrated in \in {figure} [italic-two]. You will notice that for Latin +Modern (any) correction makes sense, but for Dejavu it probably makes things look +worse. This is why italic correction is disabled by default. When enabled there +are several variants: + +\starttabulate[|Bl|l|] +\NC global \NC always apply correction \NC \NR +\NC text \NC only apply correction to text \NC \NR +\NC always \NC apply correction between text and boxes \NC \NR +\NC none \NC forget about correction \NC \NR +\stoptabulate + +We keep track of the state using attributes but that comes at a (small) price in terms +of extra memory and runtime. The \type {global} option simply assumes that we always +need to check for correction (of course only for fonts that have this feature enables). +In the given example we used: + +\starttyping +\setupitaliccorrection + [text] +\stoptyping + +You can combine keys: + +\starttyping +\setupitaliccorrection + [global,always] +\stoptyping + +\startplacefigure[reference=italic-two,title={Italic correction (factor 5).}] + \startcombination + \startcontent + \backgroundline + [maincolor] + {\color[white]{\definedfont[lmroman10-italic*default sa 4]test} + \color[white]{\definedfont[lmroman10-regular*default sa 4]\space test}} + \stopcontent + \startcaption + \backgroundline + [maincolor] + {\setupitaliccorrection[text]% + \color[white]{\definedfont[lmroman10-italic*italic sa 4]test} + \color[white]{\definedfont[lmroman10-regular*default sa 4]\space test}} + \stopcaption + \startcontent + \backgroundline + [maincolor] + {\color[white]{\definedfont[dejavuserifitalic*default sa 4]test} + \color[white]{\definedfont[dejavuserif*default sa 4]\space test}} + \stopcontent + \startcaption + \backgroundline + [maincolor] + {\setupitaliccorrection[text]% + \color[white]{\definedfont[dejavuserifitalic*italic sa 4]test} + \color[white]{\definedfont[dejavuserif*default sa 4]\space test}} + \stopcaption + \stopcombination +\stopplacefigure + +The \type {itlc} feature controls if a font gets italic correction applied. In +principle this is all that the user needs to do, given that the mechanism is +enabled. These is an extra feature that controls the implementation: + +\starttabulate[|T|T|p|] +\NC itlc \NC no \NC don't apply italic correction (default) \NC \NR +\NC \NC yes \NC apply italic correction \NC \NR +\NC textitalics \NC no \NC precalculate italic corrections (permit engine usage) \NC \NR +\NC \NC yes \NC precalculate italic corrections (inhibit engine) \NC \NR +\NC \NC delay \NC delay calculation of corrections \NC \NR +\stoptabulate + +When \type {textitalics} is set to \type {yes} or \type {delay} the mechanism +built into the engine is completely disabled. When set to \type {no} the engine +can kick in but normally the alternative method takes precedence so that the +engine sees no reason for further action. You can trace italic corrections with: + +\starttyping +\enabletrackers[typesetters.italics] +\stoptyping + +\stopsection + +\startsection[title=Bounding boxes] + +\startbuffer +\definefontfeature + [withbbox] + [boundingbox=yes] + +\definefont + [FontWithBB] + [Normal*withbbox] +\stopbuffer + +\start \getbuffer \FontWithBB + +There are some features that are rather useless and only make sense when figuring out +issues. An example of such a feature is the following: + +\typebuffer + +This feature adds a background to each character in a font. In some fonts a glyph +has a tight bounding box, while on other fonts some extra space is put on the left +and right. Keep in mind that this feature blocks colored text. + +\par \stop + +\stopsection + +\startsection[title=Slanting] + +This features (as well as the one described in the next section) are seldom used +but provided because they were introduced in \PDFTEX. + +\startbuffer[define] +\definefontfeature + [abitslanted] + [default] + [slant=.1] + +\definefontfeature + [abitmoreslanted] + [default] + [slant=.2] +\stopbuffer + +\startbuffer[sample] +\definedfont[Normal*abitslanted]This is a bit slanted. +\definedfont[Normal*abitmoreslanted]And this is a bit more slanted. +\stopbuffer + +\typebuffer[define,sample] + +The result is: + +\getbuffer[define] + +\startlines +\getbuffer[sample] +\stoplines + +\stopsection + +\startsection[title=Extending] + +The second manipulation is extending the shapes horizontally: + +\startbuffer[define] +\definefontfeature + [abitbolder] + [default] + [extend=1.3] + +\definefontfeature + [abitnarrower] + [default] + [extend=0.7] +\stopbuffer + +\startbuffer[sample] +\definedfont[Normal*abitbolder]This looks a bit bolder. +\definedfont[Normal*abitnarrower]And this is a bit narrower. +\stopbuffer + +\typebuffer[define,sample] + +The result is: + +\getbuffer[define] + +\startlines +\getbuffer[sample] +\stoplines + +We can also combine slanting and extending: + +\startbuffer[define] +\definefontfeature + [abitofboth] + [default] + [extend=1.3, + slant=.1] +\stopbuffer + +\startbuffer[sample] +\definedfont[Normal*abitofboth]This is a bit bolder but also slanted. +\stopbuffer + +\typebuffer[define,sample] + +If you remember those first needle matrix printers you might recognize the +next rendering: + +\getbuffer[define] + +\startlines +\getbuffer[sample] +\stoplines + +\stopsection + +\startsection[title=Fixing] % dimensions + +This is a rather special one. First we show a couple of definitions: + +\startbuffer +\definefontfeature + [dimensions-a] + [default] + [dimensions={1,1,1}] + +\definefontfeature + [dimensions-b] + [default] + [dimensions={1,2,3}] + +\definefontfeature + [dimensions-c] + [default] + [dimensions={1,3,2}] + +\definefontfeature + [dimensions-d] + [default] + [dimensions={3,3,3}] +\stopbuffer + +\typebuffer \getbuffer + +As usual you apply such a feature as follows: + +\starttyping +\definefont[MyFont][Serif*dimensions-a sa 2] +\stoptyping + +Alternatively you can use such a feature on its own: + +\starttyping +\definefontfeature + [dimensions-333] + [dimensions={3,3,3}] +\definefont[MyFont][Serif*default,dimensions-333 sa 2] +\stoptyping + +In \in {figure} [dimensions-side-by-side] you see these four definitions in +action. The leftmost rendering is the default rendering. The three numbers in the +definitions represent the width (in em), height and depth (in ex). + +\startplacefigure[reference={dimensions-side-by-side},title={Freezing dimensions of glyphs.}] + \startcombination[5*1] + \startcontent \hbox to 7em {\hss\ruledhbox{\definedfont[Serif*default sa 2]g}\hss}\stopcontent \startcaption default \stopcaption + \startcontent \hbox to 7em {\hss\ruledhbox{\definedfont[Serif*dimensions-a sa 2]g}\hss}\stopcontent \startcaption \hbox{1em 1ex 1ex} \stopcaption + \startcontent \hbox to 7em {\hss\ruledhbox{\definedfont[Serif*dimensions-b sa 2]g}\hss}\stopcontent \startcaption \hbox{1em 2ex 3ex} \stopcaption + \startcontent \hbox to 7em {\hss\ruledhbox{\definedfont[Serif*dimensions-c sa 2]g}\hss}\stopcontent \startcaption \hbox{1em 3ex 2ex} \stopcaption + \startcontent \hbox to 7em {\hss\ruledhbox{\definedfont[Serif*dimensions-d sa 2]g}\hss}\stopcontent \startcaption \hbox{3em 3ex 3ex} \stopcaption + \stopcombination +\stopplacefigure + +This feature only makes sense for fonts that need a fixed width, like the +\CJK\ fonts that are used for asian scripts. Normally those fonts already +have fixed dimensions, but this feature can be used to fix problematic +fonts or add some more space. However, for such large fonts this also brings a +larger memory footprint. + +A special case is the following: + +\startbuffer +\definefontfeature + [dimensions-e] + [dimensions=strut] +\stopbuffer + +\typebuffer \getbuffer + +This will make the height and depth the same as the current strut height and depth: + +\startbuffer +\ruledhbox{\definedfont[Serif*default,dimensions-e at 8pt]clipped} +\ruledhbox{\definedfont[Serif*default,dimensions-e at 12pt]clipped} +\ruledhbox{\definedfont[Serif*default,dimensions-e at 24pt]clipped} +\stopbuffer + +\typebuffer + +The dimensions are (in this case) limited: + +\startlinecorrection[blank] \dontleavehmode \hpack{\maincolor\inlinebuffer} \stoplinecorrection + +\stopsection + +\startsection[title=Unicoding] + +Nowadays we will mostly use fonts that ship with a \UNICODE\ aware encoding. And +in \CONTEXT, even if we use a \TYPEONE\ font, it gets mapped onto \UNICODE. +However, there are some exceptions, for instance the Zapf Dingbats in \TYPEONE\ +format. These have a rather obscure private encoding and the glyph names run from +\type {a1} upto \type {a206} and have no relation to what the glyph represents. + +In the case of Dingbats we're somewhat lucky that they ended up in \UNICODE, so +we can relocate the glyphs to match their rightful place. This is done by means +of a goodies file. We already discussed this in \in {section} [goodies] so we +only repeat the usage. + +\startbuffer +\definefontfeature + [dingbats] + [mode=base, + goodies=dingbats, + unicoding=yes] + +\definefontsynonym + [ZapfDingbats] + [file:uzdr.afm] + [features=dingbats] +\stopbuffer + +\typebuffer \getbuffer + +I tend to qualify the Dingbat font in \TEX\ distributions as rather unstable +because of name changes and them either or not being included. Therefore it's best to +use the hard coded name because that triggers the most visible error message when +the font is not found. + +A font like this can for instance be used with the glyph placement macros as is +demonstrated below. In the last line we see that a direct \UTF\ input also works +out well. + +\starttabulate[|||T|] +\HL +\NC \type{\getglyphdirect {ZapfDingbats*dingbats}{\number"2701}} \NC \getglyphdirect {ZapfDingbats*dingbats}{\number"2701} \NC \NC \NR +\NC \type{\getglyphdirect {ZapfDingbats*dingbats}{\char"2701}} \NC \getglyphdirect {ZapfDingbats*dingbats}{\char"2701} \NC \NC \NR +\NC \type{\getnamedglyphdirect{ZapfDingbats*dingbats}{a1}} \NC \getnamedglyphdirect{ZapfDingbats*dingbats}{a1} \NC \NC \NR +\NC \type{\getnamedglyphdirect{ZapfDingbats*dingbats}{a11}} \NC \getnamedglyphdirect{ZapfDingbats*dingbats}{a11} \NC \NC \NR +\HL +\NC \type{\getglyphdirect {ZapfDingbats}{\number"2701}} \NC \getglyphdirect {ZapfDingbats}{\number"2701} \NC unknown \NC \NR +\NC \type{\getglyphdirect {ZapfDingbats}{\char"2701}} \NC \getglyphdirect {ZapfDingbats}{\char"2701} \NC unknown \NC \NR +\NC \type{\getnamedglyphdirect{ZapfDingbats}{a1}} \NC \getnamedglyphdirect{ZapfDingbats}{a1} \NC \NC \NR +\NC \type{\getnamedglyphdirect{ZapfDingbats}{a11}} \NC \getnamedglyphdirect{ZapfDingbats}{a11} \NC \NC \NR +\HL +\NC \type{\definedfont[ZapfDingbats*dingbats]✁} \NC \definedfont[ZapfDingbats*dingbats]✁ \NC \NC \NR +\HL +\stoptabulate + +Keep in mind that fonts like Dejavu (that we use here as document font) already +has these characters which is why it shows up in the verbose part of the table. + +\stopsection + +\startsection[title=Protrusion] + +Protrusion is a feature that \LUATEX\ inherits from \PDFTEX. It is sometimes +referred to as hanging punctuation but in our case any character qualifies. Also, +hanging is not frozen but can be tuned in detail. Currently the engine defines +protrusion in terms of the emwidth which is unfortunate and likely to change. +\footnote {In general the low level implementation can be optimized as there are +better mechanisms in \LUATEX.} + +It is sometimes believed that protrusion improves for instance narrower columns, +but I'm pretty sure that this is not the case. It is true that it is taken into +account when breaking a paragraph into lines, and that we then have a little bit +more width available, but at the same time it is an extra constraint: if we +protrude we have to do it for each line (and the whole main body of text) so it's +just a different solution space. The main reason for applying this feature is +{\em not} that the lines look better or that we get better looking narrow lines +but that the right and left margins look nicer. Personally I don't like half +protrusion of punctuation and hyphens. Best is to have small values for regular +characters to improve the visual appearance and use full protrusion for hyphens +(and maybe punctuation). + +\startsubsubject[title=protrusion classes] + +In \CONTEXT\ we've always defined protrusion as a percentage of the width of a +glyph. From \MKII\ we inherit the level of control as well as the ability to +define vectors. The shared properties are collected in so called classes and the +character specific properties in vectors. The following classes are predefined: + +\showprotrusionclass + +The names are used in the definitions: + +\starttyping +\definefontfeature[default][protrusion=quality] +\stoptyping + +Currently adding a class only has a \LUA\ interface. + +\startbuffer +\startluacode +fonts.protrusions.classes.myown = { + vector = 'myown', + factor = 1, +} +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +\stopsubsubject + +\startsubsubject[title=protrusion vectors] + +Vectors are larger but not as large as you might expect. Only a subset of +characters needs to be defined. This is because in practice only latin scripts +are candidates and these scripts have glyphs that look a lot like each other. As +we only operate on the horizontal direction characters like \quote +{aàáâãäå} look the same from the left and right so we only have to define +the protrusion for \quote {a}. + +As with classes, you can define your own vectors: + +\startbuffer +\startluacode +fonts.protrusions.vectors.myown = table.merged ( + fonts.protrusions.vectors.quality, + { + [0x002C] = { 0, 2 }, -- comma + } +) +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +\stopsubsubject + +\startsubsubject[title=protrusion vector pure] + \showprotrusionvector[name=pure] +\stopsubsubject + +\startsubsubject[title=protrusion vector punctuation] + \showprotrusionvector[name=punctuation] +\stopsubsubject + +\startsubsubject[title=protrusion vector alpha] + \showprotrusionvector[name=alpha] +\stopsubsubject + +\startsubsubject[title=protrusion vector quality] + \showprotrusionvector[name=quality] +\stopsubsubject + +\startsubsubject[title=examples of protrusion] + +Next we show the quality protrusion. For this we use \type {tufte.tex} as +this one for sure will result in punctuation and other candidates for +protrusion. + +\startbuffer[define] +\definefontfeature + [whatever] + [default] + [protrusion=quality] + +\definefont[MyTestA][Serif*default at 10pt] +\definefont[MyTestB][Serif*whatever at 10pt] +\stopbuffer + +\startbuffer[example] +\startoverlay + {\ruledvbox \bgroup + \hsize\textwidth + \MyTestA + \setupalign[normal] + \input{tufte} + \egroup} + {\ruledvbox \bgroup + \hsize\textwidth + \MyTestB + \setupalign[hanging,normal] + \maincolor + \input{tufte} + \egroup} +\stopoverlay +\stopbuffer + +\typebuffer[define] +\getbuffer [define] + +We use the following example. The results are shown in \in {figure} +[protrusion:quality]. The colored text is the protruding one. + +\typebuffer[example] + +\startplacefigure[reference=protrusion:quality,title=The difference between no protrusion and quality protrusion.] + \getbuffer [example] +\stopplacefigure + +The previously defined own class and vector is somewhat more extreme: + +\startbuffer[define] +\definefontfeature + [whatever] + [default] + [protrusion=myown] + +\definefont[MyTestA][Serif*default at 10pt] +\definefont[MyTestB][Serif*whatever at 10pt] +\stopbuffer + +\typebuffer[define] +\getbuffer [define] + +In \in {figure} [protrusion:myown] we see that the somewhat extreem definition of +the comma also pulls the preceding character into the margin. + +\startplacefigure[reference=protrusion:myown,title=The influence of extreme protrusion on preceding characters.] + \getbuffer [example] +\stopplacefigure + +\stopsection + +\startsection[title=Expansion] + +Expansion is also an inheritance of \PDFTEX. \footnote {As with protrusion the +implementation in the engine is somewhat suboptimal and inefficient and will be +upgraded to a more \LUATEX-ish way.} This mechanism selectively expands +characters, normally upto 5\%. One reason for applying it is that we have less +visually incompatible spacing, especially when we have underfull or cramped +lines. For each (broken) line the badness is reconsidered with either shrink or +stretch applied to all characters in that line. So, in the worst case a shrunken +line is followed by a stretched one and that can be visible when the scaling +factors are chosen wrong. + +As with protrusion, the solution space is larger but so are the constraints. But +contrary to protrusion here the look and feel of the whole line can be made +better but at the cost of much more runtime and larger (\PDF) files. + +\startsubsubject[title=protrusion classes] + +The amount of expansion depends in the shape of the character. Vertical strokes +are more sensitive for expansion then horizontal ones. So an \quote {o} can +get a different scaling than an \quote {m}. As with protrusion we have collected +the properties in classes: + +\showexpansionclass + +The smaller the step, the more instances of a font we get, the better it +looks, and the larger the files become. it's best not to use too many stretch +and shrink steps. A stretch of 2 and shrink of 2 and step of .25 results in +upto 8~instances plus the regular sized one. + +\stopsubsubject + +\startsubsubject[title=expansion vectors] + +We only have one vector: \type {quality}: + +\showexpansionvector[name=quality] + +\stopsubsubject + +\startsubsubject[title=an example of expansion] + +We use \type {zapf.tex} as example text, if only because Hermann Zapf introduced +this optimization. Keep in mind that you can combine expansion and protrusion. + +\startbuffer[define] +\definefontfeature + [whatever] + [default] + [expansion=quality] + +\definefont[MyTestA][Serif*default at 10pt] +\definefont[MyTestB][Serif*whatever at 10pt] +\stopbuffer + +\startbuffer[example] +\startoverlay + {\ruledvbox \bgroup + \hsize\textwidth + \MyTestA + \setupalign[normal] + \input{tufte} + \egroup} + {\ruledvbox \bgroup + \hsize\textwidth + \MyTestB + \setupalign[hz,normal] + \maincolor + \input{tufte} + \egroup} +\stopoverlay +\stopbuffer + +\typebuffer[define] +\getbuffer [define] + +We use the following example. The results are shown in \in {figure} +[expansion:quality]. The colored text is the protruding one. + +\typebuffer[example] + +\startplacefigure[reference=expansion:quality,title=The difference between no expansion and quality expansion.] + \getbuffer [example] +\stopplacefigure + +\startsubsubject[title=Expansion and kerning] + +When we expand glyphs we also need to look at the font kerns between them. In the +original implementation taken from \PDFTEX\ expansion was implemented using pseudo +fonts (with expanded glyph widths) and expansion of inter|-|character kerns was +based on font information. In \LUATEX\ we have expansion factors in glyph nodes +instead which is more efficient and gives a cleaner separation between front- and +backend as the backend has no need to consult the font. + +For the font kerns we set the kern compensation directly and for that we use the +average expansion factors of the neighbouring fonts so technically we support +kerns between different fonts). This also has the advantage that kerns injected +in node mode are treated well, given that they are tagged as font kern. + +So what is the effect (and need) of scaling font kerns? Let's look at an example. +Kerns can be positive but also negative: + +\startlinecorrection +\startcombination + {\vbox { + \forgetall + \hpack to 3cm{\hss\ruledhbox{\maincolor V\kern-1ptA}\hss} + \hpack to 3cm{\hss\ruledhbox{\maincolor V\kern 0ptA}\hss} + }} {negative} + {\vbox { + \forgetall + \hpack to 3cm{\hss\ruledhbox{\maincolor I\kern.25ptI}\hss} + \hpack to 3cm{\hss\ruledhbox{\maincolor I\kern 0ptI}\hss} + }} {positive} +\stopcombination +\stoplinecorrection + +If we use a rediculous amount of stretch we get the following. In the top line we +scale the kern, in the bottom line we don't. + +\startlinecorrection +\startcombination + {\vbox { + \definedfont[file:texgyrepagella-regular.otf at 12pt]% + \forgetall + \hpack to 3cm{\maincolor \hss\strut \scale[xscale=5000]{V}\kern-5pt\scale[xscale=5000]{A}\hss} + \hpack to 3cm{\maincolor \hss\strut \scale[xscale=5000]{V}\kern-1pt\scale[xscale=5000]{A}\hss} + }} {negative} + {\vbox { + \definedfont[file:texgyrepagella-regular.otf at 12pt]% + \forgetall + \hpack to 3cm{\maincolor \hss\strut \scale[xscale=5000]{I}\kern1.25pt\scale[xscale=5000]{I}\hss} + \hpack to 3cm{\maincolor \hss\strut \scale[xscale=5000]{I}\kern0.25pt\scale[xscale=5000]{I}\hss} + }} {positive} +\stopcombination +\stoplinecorrection + +The reason that we mention this is that when we apply \OPENTYPE\ features, +positioning not necessarily result in font kerns. For instance ligatures can be +the result of careful applied kerns and in some scripts kerns are used to connect +glyphs. This means that we best cannot expand kerns by default. How bad is +that? By looking at the examples above one would say \quotation {real bad}. + +But say that we have about 1pt of font kerns, then a 5\% expansion (which is +already a lot) amounts to 0.05pt so to \blackrule [width=1pt, height=max, +depth=max] we add \blackrule [width=.05pt, height=max, depth=max] which is so +little that it probably goes unnoticed. Even if we use extreme kerns, as between +VA, in practice the small amount of stretch or shrink added to a font kern goes +unnoticed. + +In \in {figure} [hz:natural] we have overlayed the different strategies. The +sample and width is chosen such that we see something. On a display you can +scale up these examples and inspect if there is really something to see, +but on paper zooming in helps, as in \in {figure} [hz:zoomed]. Even then the +effect of expanded kerns is invisible. The used definitions are: + +\definecolor[hz:test:tr][r=1,a=1,t=.5] +\definecolor[hz:test:tg][g=1,a=1,t=.5] +\definecolor[hz:test:tb][b=1,a=1,t=.5] + +\startbuffer +\setupfontexpansion + [extremehz] + [stretch=5,shrink=5,step=.5,vector=default,factor=1] +\setupfontexpansion + [regularhz] + [stretch=2,shrink=2,step=.5,vector=default,factor=1] +\setupfontexpansion + [minimalhz] + [stretch=2,shrink=2,step=.5,vector=default,factor=.5] + +\definefontfeature + [extremehz] [default] + [mode=node,expansion=extremehz] +\definefontfeature + [regularhz] [default] + [mode=node,expansion=regularhz] +\definefontfeature [minimalhz] [default] + [mode=node,expansion=minimalhz] + +\definefont + [ExtremeHzFont] + [file:texgyrepagella-regular.otf*extremehz at 10pt] +\definefont + [RegularHzFont] + [file:texgyrepagella-regular.otf*regularhz at 10pt] +\definefont + [MinimalHzFont] + [file:texgyrepagella-regular.otf*minimalhz at 10pt] +\stopbuffer + +\typebuffer \getbuffer + +\edef\HzSampleText{\cldloadfile{ward}} + +\def\NoHzSample {\vbox{\hsize 10cm \color[hz:test:tr]{\setupalign [nohz]\HzSampleText\par}}} +\def\HzSample {\vbox{\hsize 10cm \color[hz:test:tg]{\setupalign [hz]\HzSampleText\par}}} +\def\FullHzSample{\vbox{\hsize 10cm \color[hz:test:tb]{\setupalign[fullhz]\HzSampleText\par}}} + +\startplacefigure[reference=hz:natural,title={The two expansion methods compared.}] + \showfontkerns + \dontcomplain + \enabledirectives[fonts.injections.fontkern] + \startcombination[1*3] + {\ExtremeHzFont\ruledhpack{\startoverlay {\NoHzSample} {\HzSample } \stopoverlay}} {no hz \& hz} + {\ExtremeHzFont\ruledhpack{\startoverlay {\NoHzSample} {\FullHzSample} \stopoverlay}} {no hz \& full hz} + {\ExtremeHzFont\ruledhpack{\startoverlay {\HzSample } {\FullHzSample} \stopoverlay}} {hz \& full hz} + \stopcombination + \disabledirectives[fonts.injections.fontkern] +\stopplacefigure + +\startplacefigure[reference=hz:zoomed,title={The two expansion methods compared (zoomed in).}] + \showfontkerns + \dontcomplain + \enabledirectives[fonts.injections.fontkern] + \startcombination[3*3] + + {\ExtremeHzFont + \clip[nx=6,ny=5,x=2,y=2,sx=2]{\startoverlay {\NoHzSample} {\HzSample } \stopoverlay}} {extreme: no hz \& hz} + {\ExtremeHzFont + \clip[nx=6,ny=5,x=2,y=2,sx=2]{\startoverlay {\NoHzSample} {\FullHzSample} \stopoverlay}} {extreme: no hz \& full hz} + {\ExtremeHzFont + \clip[nx=6,ny=5,x=2,y=2,sx=2]{\startoverlay {\HzSample } {\FullHzSample} \stopoverlay}} {extreme: hz \& full hz} + + {\RegularHzFont + \clip[nx=6,ny=5,x=2,y=2,sx=2]{\startoverlay {\NoHzSample} {\HzSample } \stopoverlay}} {regular: no hz \& hz} + {\RegularHzFont + \clip[nx=6,ny=5,x=2,y=2,sx=2]{\startoverlay {\NoHzSample} {\FullHzSample} \stopoverlay}} {regular: no hz \& full hz} + {\RegularHzFont + \clip[nx=6,ny=5,x=2,y=2,sx=2]{\startoverlay {\HzSample } {\FullHzSample} \stopoverlay}} {regular: hz \& full hz} + + {\MinimalHzFont + \clip[nx=6,ny=5,x=2,y=2,sx=2]{\startoverlay {\NoHzSample} {\HzSample } \stopoverlay}} {minimal: no hz \& hz} + {\MinimalHzFont + \clip[nx=6,ny=5,x=2,y=2,sx=2]{\startoverlay {\NoHzSample} {\FullHzSample} \stopoverlay}} {minimal: no hz \& full hz} + {\MinimalHzFont + \clip[nx=6,ny=5,x=2,y=2,sx=2]{\startoverlay {\HzSample } {\FullHzSample} \stopoverlay}} {minimal: hz \& full hz} + + \stopcombination + \disabledirectives[fonts.injections.fontkern] +\stopplacefigure + +In \CONTEXT\ the \type {hz} alignment option only enables expansion of glyphs, while \type +{fullhz} also applies it to kerns. However, in the examples here we had to explicitly enable +font kerns in node mode: + +\starttyping +\enabledirectives[fonts.injections.fontkern] +\stoptyping + +It will be clear that you can just stick to using the \type {hz} directive (if +you want expansion at all) because this directive is normally disabled and +because most fonts are processed in node mode. + +\stopsubsubject + +\stopsection + +\startsection[title=Composing] + +This feature is seldom needed but can come in handy for old fonts or when +some special language is to be supported. When writing this section I tested +this feature with Dejavu and only two additional characters were added: + +\definefontfeature + [default-plus-compose] + [compose=yes] + +\definefont + [MyComposedSerif] + [Serif*default-plus-compose] + +% we need to cheat a bit as we don't have the main character in mono + +\startlines \MyComposedSerif +\type{fonts > combining > }\hbox to .5em{\hss Ѷ\hss}\type{ (U+00476) = }\hbox to .5em{\hss Ѵ\hss}\type{ (U+00474) + ̏ (U+0030F)} +\type{fonts > combining > }\hbox to .5em{\hss ѷ\hss}\type{ (U+00477) = }\hbox to .5em{\hss ѵ\hss}\type{ (U+00475) + ̏ (U+0030F)} +\stoplines + +This trace showed up after giving: + +\starttyping +\enabletrackers + [fonts.composing.define] + +\definefontfeature + [default-plus-compose] + [compose=yes] + +\definefont + [MyFont] + [Serif*default-plus-compose] +\stoptyping + +Fonts like Latin Modern have lots of glyphs but still lack some. Although the +composer can add some of the missing, some of those new virtual glyphs probably +will never look real good. For instance, putting additional accents on top of +already accented uppercase characters will fail when that character has a rather +tight (or even clipped) boundingbox in order not to spoil the lineheight. You can +get some more insight in the process by turning on tracing: + +\starttyping +\enabletrackers[fonts.composing.visualize] +\stoptyping + +One reason why composing can be suboptimal is that it uses the boundingbox of the +characters that are combined. If you really depend on a specific font and need +some of the missing characters it makes sense to spend some time on optimizing +the rendering. This can be done via the goodies mechanism. As an example we've +added \type {lm-compose-test.lfg} to the distribution. First we show how it +looks at the \TEX\ end: + +\startbuffer +\enabletrackers[fonts.composing.visualize] + +\definefontfeature + [default-plus-compose] + [compose=yes] + +\loadfontgoodies + [lm-compose-test] % playground + +\definefont + [MyComposedSerif] + [file:lmroman10regular*default-plus-compose at 48pt] +\stopbuffer + +\typebuffer \getbuffer + +\blank +\backgroundline + [halfcolor] + {\MyComposedSerif B\quad\char"1E02\quad\char"1E04} +\blank + +The positions of the dot accents on top and below the capital B is defined +in a goodie file: + +\starttyping +return { + name = "lm-compose-test", + version = "1.00", + comment = "Goodies that demonstrate composition.", + author = "Hans and Mojca", + copyright = "ConTeXt development team", + compositions = { + ["lmroman12-regular"] = compose, + } +} +\stoptyping + +As this is an experimental feature there are several ways to deal with +this. For instance: + +\starttyping +local defaultfraction = 10.0 + +local compose = { + dy = defaultfraction, + [0x1E02] = { -- B dot above + dy = 150 + }, + [0x1E04] = { -- B dot below + dy = 150 + }, +} +\stoptyping + +Here the fraction is relative to the difference between the height of the +accentee and the accent. A better solution is the following: + +\starttyping +local compose = { + [0x1E02] = { -- B dot above + anchored = "top", + }, + [0x1E04] = { -- B dot below + anchored = "bottom", + }, + [0x0042] = { -- B + anchors = { + top = { + x = 300, y = 700, + }, + bottom = { + x = 300, y = -30, + }, + }, + }, + [0x0307] = { + anchors = { + top = { + x = -250, y = 550, + }, + }, + }, + [0x0323] = { + anchors = { + bottom = { + x = -250, y = -80, + }, + }, + }, +} +\stoptyping + +This approach is more or less the same as \OPENTYPE\ anchoring. It takes a bit +more effort to define these tables but the result is better. + +\stopsection + +\startsection[title=Kerning] + +Inter|-|character kerning is not supported at the font level and with good +reason. The fact that something is conceptually possible doesn't mean that we +should use or support it. Normally proper kerning (or the lack of it) is part +of a font design and for some scripts different kerning is not even an option. + +On the average \TEX\ does a proper job on justification but not all programs +are that capable. As a consequence designers (at least we ran into it) tend to +stick to flush left rendering because they don't trust their system to do a +proper job otherwise. On the other hand they seem to have no problem with +messing up the inter|-|character spacing and even combine that with excessive +inter|-|word spacing {\em if} they want to achieve justification (without +hyphenation). And it can become even worse when extreme glyph expansion (like +hz) is applied. + +Anyhow, it will be clear that consider messing with properties like kerning that +are part of the font design is to be done careful. + +\definecharacterkerning [extremekerning] [factor=.125] + +\start \setcharacterkerning[extremekerning] + +For running text additional kerning makes no sense. It not only looks +bad, it also spoils the grayness of a text. When it is applied we need +to deal with special cases. For instance ligatures make no sense so they +should be disabled. Additional kerning should relate to already present +kerning and interword spacing should be adapted accordingly. Embedded +non|-|characters also need to be treated well. + +\par \stop + +This paragraph was typeset as follows: + +\starttyping +\definecharacterkerning [extremekerning] [factor=.125] + +\setcharacterkerning[extremekerning] ... text ... +\stoptyping + +Where additional kerning can make sense, is in titles. The previous +command can do that job. In addition we have a mechanism that +fills a given space. This mechanism uses the following definition: + +\starttyping +\setupcharacterkerning + [stretched] + [factor=max, + width=\availablehsize] +\stoptyping + +\startbuffer +\stretched{\bfd to the limit} +\stopbuffer + +\typebuffer + +\blank \start \color[maincolor]{\getbuffer} \stop \blank + +The following does not work: + +\startbuffer +\ruledhbox to 5cm{\stretched{\bfd to the limit}} +\stopbuffer + +\typebuffer + +\blank \start \color[maincolor]{\getbuffer} \stop \blank + +But this works ok: + +\startbuffer +\setupcharacterkerning + [stretched] + [width=] + +\stretched{\bfd to the limit} +\stopbuffer + +\typebuffer + +\blank \start \color[maincolor]{\getbuffer} \stop \blank + +You can also say this: + +\startbuffer +\stretched[width=]{\bfd to the limit} +\stopbuffer + +\typebuffer + +\blank \start \color[maincolor]{\getbuffer} \stop \blank + +or: + +\startbuffer +\ruledhbox{\stretched[width=10cm]{\bfd to the limit}} +\stopbuffer + +\typebuffer + +\blank \start \color[maincolor]{\getbuffer} \stop \blank + +You can get some insight in what kerning does to your font by the following +command: + +\startbuffer +\usemodule[typesetting-kerning] + +\starttext + \showcharacterkerningsteps + [style=Bold, + sample=how to violate a proper font design, + text=rubish, + first=0, + last=45, + step=5] +\stoptext +\stopbuffer + +\typebuffer + +\blank \getbuffer \blank + +\stopsection + +\startsection[title=Ligatures] + +For some Latin fonts ligature building is quite advanced, take Unifraktur. I have no +problem admitting that I find fraktur hard to read, but this one actually is sort of +an exception. It's also a good candidate for a screen presentation where you mainly +made notes for yourself: no one has to read it, but it looks great, especially if +you consider it to be drawn by a pen. + +Anyway, we will use the following code as example (based on some remarks on the +fonts website). + +\startbuffer[sample] +sitzen / ſitzen / effe fietsen / ch ck ſt tz ſi fi +\stopbuffer + +\typebuffer[sample] + +Some ligatures are implemented in the usual way, using the \type {liga} and \type {dlig} +features, others kick in thanks to \type {ccmp}. This fact alone is an illustration that +the low level \OPENTYPE\ ligature feature is not related to ligatures at all but a more +generic mechanism: you can basically combine multiple shapes into one in all features +exposed to the user. + +We define a bunch of specific feature sets: + +\startbuffer +\definefontfeature + [unifraktur-a] + [default] +\definefontfeature + [unifraktur-b] + [default] + [goodies=unifraktur,keepligatures=yes] +\definefontfeature + [unifraktur-c] + [default] + [ccmp=yes] +\definefontfeature + [unifraktur-d] + [default] + [ccmp=yes,goodies=unifraktur,keepligatures=yes] +\definefontfeature + [unifraktur-e] + [default] + [liga=no,rlig=no,clig=no,dlig=no,ccmp=yes,keepligatures=auto] +\stopbuffer + +\getbuffer \typebuffer + +and also some fonts: + +\startbuffer +\definefont[TestA][UnifrakturCook*unifraktur-a sa 0.9] +\definefont[TestB][UnifrakturCook*unifraktur-b sa 0.9] +\definefont[TestC][UnifrakturCook*unifraktur-c sa 0.9] +\definefont[TestD][UnifrakturCook*unifraktur-d sa 0.9] +\definefont[TestE][UnifrakturCook*unifraktur-e sa 0.9] +\stopbuffer + +\getbuffer \typebuffer + +We show these five alternatives here: + +\starttabulate[|T||] +\NC liga \NC \TestA\getbuffer[sample] \NC \NR +\NC liga + keepligatures \NC \TestB\getbuffer[sample] \NC \NR +\NC liga + ccmp \NC \TestC\getbuffer[sample] \NC \NR +\NC liga + ccmp + keepligatures \NC \TestD\getbuffer[sample] \NC \NR +\NC ccmp + keepligatures \NC \TestE\getbuffer[sample] \NC \NR +\stoptabulate + +The real fun starts when we want to add extra spacing between characters. Some +ligatures need to get broken and some kept. + +\startbuffer +\setupcharacterkerning[kerncharacters][factor=0.5] +\setupcharacterkerning[letterspacing] [factor=0.5] +\stopbuffer + +\getbuffer \typebuffer + +\enabletrackers[typesetters.kerns.ligatures] + +Next we will see how ligatures behave depending on how the mechanisms are set +up. The colors indicate what trickery is used: + +\starttabulate[|T||] +\NC \color[darkred] {red} \NC kept by dynamic feature \NC \NR +\NC \color[darkgreen]{green} \NC kept by static feature \NC \NR +\NC \color[darkblue] {blue} \NC keep by goodie \NC \NR +\stoptabulate + +First we use \type {\kerncharacters}: + +\starttabulate[|T||] +\NC liga \NC \kerncharacters {\TestA\getbuffer[sample]} \NC \NR +\NC liga + keepligatures \NC \kerncharacters {\TestB\getbuffer[sample]} \NC \NR +\NC liga + ccmp \NC \kerncharacters {\TestC\getbuffer[sample]} \NC \NR +\NC liga + ccmp + keepligatures \NC \kerncharacters {\TestD\getbuffer[sample]} \NC \NR +\NC ccmp + keepligatures \NC \kerncharacters {\TestE\getbuffer[sample]} \NC \NR +\stoptabulate + +In the next example we use \type {\letterspacing}: + +\starttabulate[|T||] +\NC liga \NC \letterspacing {\TestA\getbuffer[sample]} \NC \NR +\NC liga + keepligatures \NC \letterspacing {\TestB\getbuffer[sample]} \NC \NR +\NC liga + ccmp \NC \letterspacing {\TestC\getbuffer[sample]} \NC \NR +\NC liga + ccmp + keepligatures \NC \letterspacing {\TestD\getbuffer[sample]} \NC \NR +\NC ccmp + keepligatures \NC \letterspacing {\TestE\getbuffer[sample]} \NC \NR +\stoptabulate + +\disabletrackers[typesetters.kerns.ligatures] + +The difference is that the letterspacing variant dynamically adds the predefined +featureset \type {letterspacing} which is defined in a similar way as \type +{unifraktur-e}. In the case of this font, this variant is the better one to use. +In fact, this variant probably works okay with most fonts. However, by not hard +coding this behaviour we keep control, as one never knows what the demands are. +When no features are used, information from the (given) goodie file \type +{unifraktur.lfg} is consulted: + +\starttyping +letterspacing = { + -- watch it: zwnj's are used (in the tounicodes too) + keptligatures = { + ["c_afii301_k.ccmp"] = true, -- ck + ["c_afii301_h.ccmp"] = true, -- ch + ["t_afii301_z.ccmp"] = true, -- tz + ["uniFB05"] = true, -- ſt + }, +} +\stoptyping + +These kick in when we don't disable ligatures by setting features (case~e). + +There are two pseudo features that can help us out when a font doesn't provide +the wanted ligatures but has the right glyphs for building them. The \UNICODE\ +database has some information about how characters can be (de)composed and we can +use that information to create virtual glyphs: + +\starttyping +\definefontfeature + [default] [default] + [char-ligatures=yes,mode=node] +\stoptyping + +and: + +\starttyping +\definefontfeature + [default] [default] + [compat-ligatures=yes,mode=node] +\stoptyping + +This feature was added after some discussion on the \CONTEXT\ mailing list about +the following use case. + +\startbuffer +\definefontfeature + [default-l] [default] + [char-ligatures=yes, + compat-ligatures=yes, + mode=node] + +\definefont[LigCd][cambria*default] +\definefont[LigPd][texgyrepagellaregular*default] +\definefont[LigCl][cambria*default-l] +\definefont[LigPl][texgyrepagellaregular*default-l] +\stopbuffer + +\typebuffer \getbuffer + +These definitions result in: + +\starttabulate[|l|l|l|l|l|] +\NC \NC \type {\LigCd} \NC \type {\LigPd} \NC \type {\LigCl} \NC \type {\LigPl} \NC \NR +\NC \type{PEL·LÍCULES} \NC \LigCd PEL·LÍCULES \NC \LigPd PEL·LÍCULES \NC \LigCl PEL·LÍCULES \NC \LigPl PEL·LÍCULES \NC \NR +\NC \type{pel·lícules} \NC \LigCd pel·lícules \NC \LigPd pel·lícules \NC \LigCl pel·lícules \NC \LigPl pel·lícules \NC \NR +\NC \type{PEĿLÍCULES} \NC \LigCd PEĿLÍCULES \NC \LigPd PEĿLÍCULES \NC \LigCl PEĿLÍCULES \NC \LigPl PEĿLÍCULES \NC \NR +\NC \type{peŀlícules} \NC \LigCd peŀlícules \NC \LigPd peŀlícules \NC \LigCl peŀlícules \NC \LigPl peŀlícules \NC \NR +\stoptabulate + +Of course one can wonder is this is the right approach and if it's not better to +use a font that provides the needed characters in the first place. + +\stopsection + +\startsection[title=New features] + +\startsubsection[title=Substitution] + +It is possible to add new features via \LUA. Here is an example of a single +substitution: + +\startbuffer +\startluacode + fonts.handlers.otf.addfeature { + name = "stest", + type = "substitution", + data = { + a = "X", + b = "P", + } + } +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +We show an overview at the end of this section, but here is a simple example +already. You need to define the feature before defining a font because otherwise +the font will not know about it. + +\startbuffer +\definefontfeature[stest][stest=yes] +\definedfont[file:dejavu-serifbold.ttf*default] +abracadabra: \addff{stest}abracadabra +\stopbuffer + +\typebuffer \start \blank \maincolor \getbuffer \blank \stop + +Instead of (more readable) glyph names you can also give \UNICODE\ numbers: + +\starttyping +\startluacode + fonts.handlers.otf.addfeature { + name = "stest", + type = "substitution", + data = { + [0x61] = 0x58 + [0x62] = 0x50 + } + } +\stopluacode +\stoptyping + +The definition is quite simple: we just map glyph names (or unicodes) onto +other ones. An alternate is also possible: + +\startbuffer +\startluacode + fonts.handlers.otf.addfeature { + name = "atest", + type = "alternate", + data = { + a = { "X", "Y" }, + b = { "P", "Q" }, + } + } +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +Less useful is a multiple substitution. Normally this one is part of a chain of +replacements. + +\startbuffer +\startluacode + fonts.handlers.otf.addfeature { + name = "mtest", + type = "multiple", + data = { + a = { "X", "Y" }, + b = { "P", "Q" }, + } + } +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +A ligature (or multiple to one) is also possible but normally only makes sense when +there is indeed a ligature. We use a similar definition for mapping the \TEX\ input +sequence \type {---} onto an \emdash. + +\startbuffer +\startluacode + fonts.handlers.otf.addfeature { + name = "ltest", + type = "ligature", + data = { + ['1'] = { "a", "b" }, + ['2'] = { "d", "a" }, + } + } +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +\stopsubsection + +\startsubsection[title=Positioning] + +You can define a kern feature too but when doing so you need to use measures in +font units. + +\startbuffer +\startluacode + fonts.handlers.otf.addfeature { + name = "ktest", + type = "kern", + data = { + a = { b = -500 }, + } + } +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +Pairwise positioning is more complex and involves two (optional) arrays +that specify \type {{dx dy wd ht}} for each of the two glyphs. In the next +example we only displace the second glyph. + +\startbuffer +\startluacode + fonts.handlers.otf.addfeature { + name = "ptest", + type = "pair", + data = { + ["a"] = { ["b"] = { false, { -1000, 1200, 0, 0 } } }, + } + } +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +Of course you need to know a bit about the metrics of the glyphs involved so in +practice this boils down to trial and error. + +\stopsubsection + +\startsubsection[title=Examples] + +We didn't show usage yet. This is because we need to define a feature before we +define a font. New features will be added to a font when it gets defined. + +\startbuffer +\definefontfeature[stest][stest=yes] +\definefontfeature[atest][atest=2] +\definefontfeature[mtest][mtest=yes] +\definefontfeature[ltest][ltest=yes] +\definefontfeature[ktest][ktest=yes] +\definefontfeature[ptest][ptest=yes] +\definefontfeature[ctest][ctest=yes] + +\definedfont[file:dejavu-serif.ttf*default] + +\starttabulate[|l|l|l|] +\NC operation \NC feature \NC abracadabra \NC \NR +\HL +\NC substitution \NC \type {stest} \NC \addff{stest}abracadabra \NC \NR +\NC alternate \NC \type {atest} \NC \addff{atest}abracadabra \NC \NR +\NC multiple \NC \type {mtest} \NC \addff{mtest}abracadabra \NC \NR +\NC ligature \NC \type {ltest} \NC \addff{ltest}abracadabra \NC \NR +\NC kern \NC \type {ktest} \NC \addff{ktest}abracadabra \NC \NR +\NC pair \NC \type {ptest} \NC \addff{ptest}abracadabra \NC \NR +\NC chain sub \NC \type {ctest} \NC \addff{ctest}abracadabra \NC \NR +\stoptabulate +\stopbuffer + +\typebuffer \getbuffer + +\stopsubsection + +\startsubsection[title=Contexts] + +A more complex substitution is the following: + +\startbuffer +\startluacode + fonts.handlers.otf.addfeature { + name = "ytest", + type = "chainsubstitution", + lookups = { + { + type = "substitution", + data = { + ["b"] = "B", + ["c"] = "C", + }, + }, + }, + data = { + rules = { + { + before = { { "a" } }, + current = { { "b", "c" } }, + lookups = { 1 }, + }, + }, + }, + } +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +Here the dataset is a sequence of rules. There can be a \type {before}, \type +{current} and \type {after} match. The replacements are specified with the \type +{lookups} entry and the numbers are indices in the provided \type {lookups} +table. + +\stopsubsection + +\startsubsection[title={Language dependencies}] + +When \OPENTYPE\ was not around we only had to deal with ligatures, smallcaps and +oldstyle and of course kerns. Their number was so small that the term \quote +{features} was not even used. In practice one just loaded a font that had +oldstyle or smallcaps or none of that and was done. There were different fonts and +sold separately. + +In \OPENTYPE\ we have more variation and although these fonts can be much more +advanced the lack of standardization (for instance what gets initialized, or what +shapes are in the default slots) can lead to messy setups. Some fonts bind +features to scripts, some don't, which means that: + +\starttyping +\definefontfeature[smallcaps][smcp=yes,script=dflt] +\definefontfeature[smallcaps][smcp=yes,script=latn] +\definefontfeature[smallcaps][smcp=yes,script=cyrl] +\stoptyping + +are in fact different and you don't know in advance if you need to specify \type +{dflt} or \type {latn}. In practice for a feature like smallcaps there is no +difference between languages, but for ligatures there can be. + +When we extend an existing feature we can think of: + +\starttyping +\definefontfeature[smallcaps][default][smcp=yes,script=auto] +\definefontfeature[smallcaps][default][smcp=yes,script=*] +\stoptyping + +but that can have side effects too (for instance disabling language specific +features). The easiest way to explore this language dependency is to make +a feature of our own. + +\startbuffer +\startluacode +fonts.handlers.otf.addfeature { + name = "simplify", + type = "multiple", + prepend = true, + features = { + ["*"] = { + ["deu"] = true + } + }, + data = { + [utf.byte("ä")] = { "a", "e" }, + [utf.byte("Ä")] = { "A", "E" }, + [utf.byte("ü")] = { "u", "e" }, + [utf.byte("Ü")] = { "U", "E" }, + [utf.byte("ö")] = { "o", "e" }, + [utf.byte("Ö")] = { "O", "E" }, + [utf.byte("ß")] = { "s", "z" }, + [utf.byte("ẞ")] = { "S", "Z" }, + }, +} +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +Here we implement a language specific feature that we use at the \TEX\ end: + +\startbuffer +\definefontfeature + [simplify-de] + [simplify=yes, + language=deu] +\stopbuffer + +\typebuffer \getbuffer + +that we can use as: + +\startbuffer +\definedfont[Serif*default,simplify-de]% +äüöß +{\de äüöß} +{\nl äüöß} +\stopbuffer + +\typebuffer + +and get: \start \maincolor \inlinebuffer \stop, but as you see, both German and +Dutch get the same treatment, which might not be what you want, because in Dutch +the diearesis has a different meaning. + +\startbuffer +\definedfont[Serif*default]% + äüöß +{\de\addff{simplify-de}äüöß} +{\nl äüöß} +\stopbuffer + +\typebuffer + +The above is restricts the usage so now we get: \start \maincolor \inlinebuffer +\stop, which is more language bound. You don't need much imagination for +extending this: + +\startbuffer +\definefontfeature + [simplify] + [simplify=yes, + language=deu] +\stopbuffer + +\typebuffer \getbuffer + +\startbuffer +\definedfont[Serif*default]% + äüöß +{\de\addff{simplify}äüöß} +{\nl\addff{simplify}äüöß} +\stopbuffer + +So what do we expect with the next? + +\typebuffer + +We get: \start \maincolor \inlinebuffer \stop, and we see that the language +setting is not taken into account! This is because the font already has been set +up with a script and language combination. The solution is to temporary set the +font related language explicitly: + +\definefontfeature + [simplify] + [simplify=yes] + +\startbuffer +\definedfont[Serif*default]% + äüöß +{\de\addfflanguage\addff{simplify}äüöß} +{\nl\addfflanguage\addff{simplify}äüöß} +\stopbuffer + +\typebuffer + +So we can automatically switch to language specific features if we want to: +\start \maincolor \inlinebuffer \stop. + +Let's now move to another level of complexity: support for more than one language +as in fact this example was made for Dutch in the first place, but the German +outcome is a bit more visible. + +\startbuffer +\startluacode +fonts.handlers.otf.addfeature { + name = "simplify", + type = "multiple", + prepend = true, + -- prepend = "smcp", + dataset = + { + { + features = { + ["*"] = { + ["nld"] = true + } + }, + data = { + -- [utf.byte("ä")] = { "a" }, + -- [utf.byte("Ä")] = { "A" }, + -- [utf.byte("ü")] = { "u" }, + -- [utf.byte("Ü")] = { "U" }, + -- [utf.byte("ö")] = { "o" }, + -- [utf.byte("Ö")] = { "O" }, + [utf.byte("ij")] = { "i", "j" }, + [utf.byte("IJ")] = { "I", "J" }, + [utf.byte("æ")] = { "a", "e" }, + [utf.byte("Æ")] = { "A", "E" }, + }, + }, + { + -- type = "multiple", -- local values possible + features = { + ["*"] = { + ["deu"] = true + } + }, + data = { + [utf.byte("ä")] = { "a", "e" }, + [utf.byte("Ä")] = { "A", "E" }, + [utf.byte("ü")] = { "u", "e" }, + [utf.byte("Ü")] = { "U", "E" }, + [utf.byte("ö")] = { "o", "e" }, + [utf.byte("Ö")] = { "O", "E" }, + [utf.byte("ß")] = { "s", "z" }, + [utf.byte("ẞ")] = { "S", "Z" }, + }, + } + } +} +\stopluacode +\stopbuffer + +\typebuffer \getbuffer + +For this we use the following example: + +\startbuffer +\definedfont[Serif*default,simplify]% + äüöß ijæ +{\de\addfflanguage äüöß ijæ} +{\nl\addfflanguage äüöß ijæ} +\stopbuffer + +\typebuffer + +Because the Dutch is hard to check we use an \type {æ} replacement too and +commented the similarities with German: \start \maincolor \inlinebuffer \stop. +But still we're not done, say that we want smallcaps too: + +\startbuffer +\definefontfeature[alwayssmcp][smcp=always]% +\definedfont[Serif*default,simplify,alwayssmcp]% + äüöß ijæ +{\de\addfflanguage äüöß ijæ} +{\nl\addfflanguage äüöß ijæ} +\stopbuffer + +\typebuffer + +This comes out as: \start \maincolor \inlinebuffer \stop. + +The reason for specifying \type{smcp} as \type {always} is that otherwise we +get language specific smallcaps while often they are not bound to a language +but to the defaults. The good news is that we can do this automatically: + +\startbuffer +\setupfonts[language=auto]% +\definefontfeature[alwayssmcp][smcp=always]% +\definedfont[Serif*default,simplify,alwayssmcp]% + äüöß ijæ +{\de äüöß ijæ} +{\nl äüöß ijæ} +\stopbuffer + +\typebuffer + +But be aware that this applies to all situations. Here we get: \start \maincolor +\inlinebuffer \stop. + +\stopsubsection + +\startsubsection[title=Syntax summary] + +In the examples we have seen several ways to define features. One of the +differences is that you either set a \type {data} field directly, or that you +specify a dataset. The fields in a dataset entry overload the ones given at the +top level or when not set the top level value will be taken. There is a bit +of (downward compatibility) tolerance built in, but best not depend on that. + +\starttyping +fonts.handlers.otf.addfeature { + name = "demo", + features = { + [<script>] = { + [<language>] = true + } + }, + prepend = true | featurename | position, + dataset = { + { + type = "substitution", + data = { + [<char|code>] = <char|code>, + } + }, + { + type = "alternate", + data = { + [<char|code>] = { <char|code>, <char|code>, ... }, + } + }, + { + type = "multiple", + data = { + [<char|code>] = { <char|code>, <char|code>, ... }, + } + }, + { + type = "ligature", + data = { + [<char|code>] = { <char|code>, <char|code>, ... }, + } + }, + { + type = "kern", + data = { + [<char|code>] = { [<char|code>] = <value> }, + } + }, + { + type = "pair", + data = { + [<char|code>] = { [<char|code>] = { + false | { <value>, <value>, <value>, <value> }, + false | { <value>, <value>, <value>, <value> } + } + } + }, + { + type = "chainsubstitution", + lookups = { + { + type = <typename>, + data = <mapping>, + }, + }, + data = { + rules = { + { + before = { { [<char|code>], ... } }, + current = { { [<char|code>], ... } }, + after = { { [<char|code>], ... } }, + lookups = { <index>, ... }, + }, + }, + }, + }, + }, +} +\stoptyping + +\stopsubsection + +\startsubsection[title=Extra characters] + +\startbuffer[hyphenchars] +\startluacode + + local privateslots = fonts.constructors.privateslots + + local function addspecialhyphen(tfmdata) + + local exheight = tfmdata.parameters.xheight + local emwidth = tfmdata.parameters.quad + local width = emwidth / 4 + local height = exheight / 10 + local depth = exheight / 2 + local offset = emwidth / 6 + + tfmdata.characters[privateslots.righthyphenchar] = { + -- no dimensions + commands = { + + { "right", offset }, + + { "push" }, + { "right", -width }, + { "down", depth }, + { "rule", height, width }, + { "pop" }, + + { "right", -width/5 }, + { "down", depth + height }, + { "rule", 3*height, width/5 }, + + + } + } + + tfmdata.characters[privateslots.lefthyphenchar] = { + -- no dimensions + commands = { + + { "right", -offset }, + + { "push" }, + { "down", depth + height }, + { "rule", 3*height, width/5 }, + { "pop" }, + + { "down", depth }, + { "rule", height, width }, + + } + } + + end + + fonts.constructors.features.otf.register { + name = "specialhyphen", + description = "special hyphen", + manipulators = { + base = addspecialhyphen, + node = addspecialhyphen, + } + } + +\stopluacode +\stopbuffer + +You can add virtual characters to fonts. Here we give an example that is derived +from an example posted on the mailing list. By default, when we hyphenated a word, +we get this: + +\definefont[DemoFont] [Serif*default] + +\blank \start \DemoFont \maincolor \hsize 1mm averylongword \par \stop \blank + +The default character that is appended at the end and beginning of a line +can be specified as follows: + +\startbuffer +\setuplanguage + [en] + [righthyphenchar=45, + lefthyphenchar=45] +\stopbuffer + +\typebuffer + +So now we get: + +\blank \start \getbuffer \DemoFont \maincolor \hsize 1mm averylongword \par \stop \blank + +Say that we want a different signal, for instance some rule. Here is how that can +be done: + +\typebuffer[hyphenchars] + +\getbuffer[hyphenchars] + +Watch the way we use private slots. You can best use a unique glyph name as these +numbers are shared between fonts. With: + +\startbuffer +\definefontfeature + [default] + [default] + [specialhyphen=yes] +\definefont + [DemoFont] + [Serif*default at 24pt] +\setuplanguage + [en] + [righthyphenchar=\getprivateglyphslot{righthyphenchar}, + lefthyphenchar=\getprivateglyphslot{lefthyphenchar}] +\stopbuffer + +\typebuffer + +We get: + +\startlinecorrection[blank] +\getbuffer +\framed + [foregroundstyle=\DemoFont \setupinterlinespace, + offset=none, + frame=no, + width=1mm, + align={flushleft}] + {\hsize 1mm \maincolor averylongword\par} +\stoplinecorrection + +You need to keep in mind that some of these settings are global but in practice that is +not a real problem. Here is how you reset: + +\startbuffer +\definefontfeature + [default] + [default] + [specialhyphen=no] +\setuplanguage + [en] + [righthyphenchar=45, + lefthyphenchar=0] +\stopbuffer + +\typebuffer \getbuffer + +\stopsubsection + +\startsubsection[title=Goodies] + +The examples above extend a font in the \TEX\ document (normally a style) but you +can use a goodies file too, for instance \type {cambria.lfg}. + +\starttyping +return { + name = "cambria", + version = "1.00", + comment = "Goodies that complement cambria.", + author = "Hans Hagen", + copyright = "ConTeXt development team", + extensions = { + { + name = "kern", -- adds to kerns + type = "pair", + data = { + [0x0153] = { -- combining acute + [0x0301] = { -- aeligature + false, + { -500, 0, 0, 0 } + } + }, + } + } + } +} +\stoptyping + +Here we use the feature name \type {kern} and therefore we don't have to define a +specific (new) feature for it. Such a goodie is then used as follows: + +\starttyping +\definefontsynonym + [Serif] + [cambria] + [features=default, + goodies=cambria] +\stoptyping + +You can find such definitions in the \type {type-imp-*.mkiv} files. + +\stopsubsection + +\stopsection + +\startsection[title=Spacing] + +% By default the font loader deduces the spacing from the space character or +% other font properties. You can influence this by the \type {space} feature. +% +% \starttyping +% \definefontfeature +% [korean] +% [default] +% [script=hang, +% language=kor, +% space=local] % or locl +% \stoptyping +% +% Instead of the usual \type {yes} (which means: use character 32), \type {local} +% or \type {locl} (which means: use a replacement provided by the \type{locl} +% feature), you can also pass a character, so +% +% \starttyping +% \definefontfeature +% [spacy] +% [default] +% [space=A] +% \stoptyping +% +% is valid. + +As you probably know, \TEX\ has no space character. When the input is read, +characters tagged as space are intercepted and become glue. Compare this: + +\startlinecorrection[blank] + \startcombination + {\framed + [width=3cm,height=15mm,align={middle,lohi},foregroundcolor=maincolor] + {\dorecurse{5}{test }}} + {\type{text test...}} + {\framed + [width=3cm,height=15mm,align={middle,lohi},foregroundcolor=maincolor] + {\dorecurse{5}{test\char32\relax}}} + {\type{text\char32test...}} + \stopcombination +\stoplinecorrection + +Most fonts have a space character and you can actually use it and indeed a space +character will be injected but as it is not glue, the line break algorithm will +not see it as space. + +Al the magic done with space characters other than the native space character +(decimal 32) are at some point translated into glue. + +\starttabulate[||T|p|] +\NC \bf command \NC \UNICODE \NC width \NC \NR + +\NC \type{\nobreakspace} + \type{\nbsp} \NC U+00A0 \NC space \NC \NR +\NC \type{\ideographicspace} \NC U+2000 \NC quad/2 \NC \NR +\NC \type{\ideographichalffillspace} \NC U+2001 \NC quad \NC \NR +\NC \type{\twoperemspace} + \type{\enspace} \NC U+2002 \NC quad/2 \NC \NR +\NC \type{\emspace} + \type{\quad} \NC U+2003 \NC quad \NC \NR +\NC \type{\threeperemspace} \NC U+2004 \NC quad/3 \NC \NR +\NC \type{\fourperemspace} \NC U+2005 \NC quad/4 \NC \NR +\NC \type{\fiveperemspace} \NC \NC quad/5 \NC \NR +\NC \type{\sixperemspace} \NC U+2006 \NC quad/6 \NC \NR +\NC \type{\figurespace} \NC U+2007 \NC width of zero \NC \NR +\NC \type{\punctuationspace} \NC U+2008 \NC width of period \NC \NR +\NC \type{\breakablethinspace} \NC U+2009 \NC quad/8 \NC \NR +\NC \type{\hairspace} \NC U+200A \NC quad/8 \NC \NR +\NC \type{\zerowidthspace} \NC U+200B \NC 0 \NC \NR +\NC \type{\zerowidthnonjoiner} + \type{\zwnj} \NC U+200C \NC 0 \NC \NR +\NC \type{\zerowidthjoiner} + \type{\zwj} \NC U+200D \NC 0 \NC \NR +\NC \type{\narrownobreakspace} \NC U+202F \NC quad/8 \NC \NR +\NC \type{\zerowidthnobreakspace} \NC U+FEFF \NC \NC \NR +\NC \type{\optionalspace} \NC \NC space when not followed by punctuation \NC \NR +\stoptabulate + +% "205F % space/8 (math) + +The last one is not un \UNICODE\ and the fifths of an emspace is not in \UNICODE\ +either. This emspace (or quad in \TEX\ speak) is a font property. The width of +the space used by \CONTEXT\ is dreived form this value. In case of a monospace +fonts, the following logic is applied: + +\startitemize + \startitem + When there is a space character, the width of that character is used. + \stopitem + \startitem + Otherwise, when there is an emdash present, the width if that character + is used. + \stopitem + \startitem + Otherwise, when there is an \type {charwidth} property available (the + average width), that valua is used. + \stopitem +\stopitemize + +When a proportional font is used, we do as follows: + +\startitemize + \startitem + When there is a space character, the width of that character is used. + \stopitem + \startitem + Otherwise, when there is an emdash present, the width of that character + divided by two is used. + \stopitem + \startitem + Otherwise, when there is an \type {charwidth} property available (the + average width), that value is used. + \stopitem +\stopitemize + +In both cases, when no value is set we use the units of the font (often 1000 or +2048). In \TEX\ a space glue also has stretch and shrink. Here we follow the +traditional \TEX\ logic: + +\startitemize + \startitem + The stretch is set to half the width of a space but to zero with a mono + spaced font. + \stopitem + \startitem + The shrink is set to one third of the width of a space but to zero with a + mono spaced font. + \stopitem +\stopitemize + +The xheight is set to the values specified by the font and when this is unset the +height of the character \type {x} will be used but when this character is not in +the font, we use two fifths of the font's units (normally the same as the +emwidth). The italic angle is also taken from the font (and is of course zero for +a not italic font). Most fonts have these properties set so we seldom have to +fall back to a guess. + +\stopsection + +\startsection[title=Collections] + + {\em Todo.} + +\stopsection + +\stopchapter diff --git a/doc/context/sources/general/fonts/fonts/fonts-features.tex b/doc/context/sources/general/fonts/fonts/fonts-features.tex new file mode 100644 index 000000000..79085c236 --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-features.tex @@ -0,0 +1,2585 @@ +% language=uk + +\startcomponent fonts-features + +\environment fonts-environment + +\startMPextensions + vardef MyRectangle(expr n, w, h, x, y, c) = + image ( + fill unitsquare xyscaled (w,h) shifted (x,y) withcolor c ; + draw textext("\tttf " & decimal n) xsized (1/2) shifted (w/2,h/2) shifted (x,y) withcolor white ; + ) + enddef ; + vardef MyDot(expr x, y) = + image ( + draw (x,y) withpen pencircle scaled (2/3) withcolor white ; + draw (x,y) withpen pencircle scaled (1/2) withcolor black ; + ) + enddef ; +\stopMPextensions + +\startchapter[title=Features][color=darkmagenta] + +\startsection[title=Introduction] + +If you look into fonts, it is hard not to bump into kerns (spacing between +characters) and ligatures (combining multiple shapes into one) and apart from +monospaced fonts most \TYPEONE\ fonts have them. In the \OPENTYPE\ universe we +call these properties features and in such a font there can be many such +features. + +For those who grew up with \TEX\ or still remember the times of eight bit fonts, +it is no secret that \TEX\ macro packages did some magic to get most out of a +font: replacing missing glyphs, fixing metrics, using commands to access shapes +that had a weird code point, to mention a few. As there is absolutely no +guarantee that an \OPENTYPE\ font does better, there is a good reason to continue +messing around with fonts. After all, it's what \TEX\ users seem to like: +control. + +So, when we started writing support for \OPENTYPE\ quite soon a mechanism has +been created that permits adding our own features to the repertoire that comes +with a font. Because \OPENTYPE\ features demand a configuration and control +mechanism, it made sense to generalize that and provide a single interface. + +This means that when we talk about font features, we don't limit ourselves to +those provided by the font, but also those provided by \CONTEXT. As with font +features, they are enabled per font. + +Some of the extra features are sort of generic, others are very font specific and +their properties are somewhat bound to a font. Such features are defined in a +font goodie files. Consider these goodies a font extension mechanism. + +Some features need information that only the engine can provide. This is why we +have analyzers. Some are generic, others are bound to scripts. They come in +action before features are applied. Rather special is applying features in +combination with paragraph building. This is something very specific to \CONTEXT\ +but it depends on properties of the font. It falls into the category \quote +{optimizing}. + +It is clear that when we talk of features many aspects of a font play a role. In +this chapter we will discuss all the mentioned aspects. There is quite a bit of +\LUA\ code shown in this chapter, but don't worry, users will seldom need to +tweak fonts this way. On the other hand it's good to see what is possible. + +\stopsection + +\startsection[title=Regulars] + +\startsubsection[title=Introduction] + +The \OPENTYPE\ specification, which can be found on the \MICROSOFT\ website +is no easy reading. Some of the concepts are easy to understand, like relative +positioning (that we call kerning in \TEX) or ligature substitution (as we +have ligatures in \TEX\ too). It makes no sense to discuss the bitwise composition +of an \OPENTYPE\ or \TRUETYPE\ file here. First of all, all we get to see is +a \LUA\ table, and in \CONTEXT\ even that one gets sanitized and optimized +into a more useable table. However, as the data that comes with a font is +a good indication of what a font is capable of, we will discuss some of it in +an appendix. In this section we will discuss the basic principles and categories +of features. + +\stopsubsection + +\startsubsection[title=Feature sets] + +Because in the next examples we will demonstrate features, we need to know how +we can tell \CONTEXT\ what features to use. Although you can add explicit +feature definitions to a font specification, I strongly advice you not to do this +but use the more abstract mechanism of feature sets. These are defined as follows: + +\starttyping +\definefontfeature + [MyFeatureSet] + [alpha=yes, + beta=no, + gamma=123] +\stoptyping + +Such a set is bound to a font with the \type {*} specifier, as in: + +\starttyping +\definefont + [MyFontInstance] + [MyNiceFont*MyFeatureSet at 12pt] +\stoptyping + +In most cases the already defined \type {default} feature set will suffice. It often +makes sense to use that one as base for new definitions: + +\starttyping +\definefontfeature + [MyFeatureSet] + [default] + [alpha=yes, + beta=no, + gamma=123] +\stoptyping + +The second argument can be a list, as in: + +\starttyping +\definefontfeature + [MyFeatureSet] + [MyFirstSet,MySecondSet] + [alpha=yes, + beta=no, + gamma=123] +\stoptyping + +Of course you need to know what features a font support, and one way to find +out is: + +\starttyping +mtxrun --script font --list --info --pattern=pagella +\stoptyping + +Don't be too surprised if different fonts show different features and even similar +features can be implemented differently. Sometimes you really need to know the font, +but fortunately many fonts come with examples. + +There are many features and there values are kept with the font when it gets +defined. This means that when you change a featureset, it will not affect already +defined fonts. Because fonts are often defined on demand, you need to be aware of +the fact that a redefinition of a featureset can have consequences for already +defined fonts. For instance, a bodyfont switch only sets up the fonts and delays +defining them. + +Although features are a sort of abstractions it can be interesting to see what features +and values are actually used: + +\starttyping +\usemodule[fonts-features] \showusedfeatures +\stoptyping + +You will notice that we have more features than \OPENTYPE\ fonts can offer. This +is because in \CONTEXT\ features is a more general concept. + +\showusedfeatures + +\stopsubsection + +\startsubsection[title=Main categories] + +There are two (but potentially more) main groups of features: those that deal +with substitution, and those that lead to positioning. It is not really needed +to know the gory details, but it helps to know at least a bit about them as +it can help to track down issues with fonts. + +There are several substitutions possible: + +\startitemize[packed] +\startitem a single substitution replaces one glyph by another \stopitem +\startitem a multiple substitution replaces one glyph by one or more \stopitem +\startitem a ligature substitution replaces multiple glyphs by one glyph \stopitem +\startitem an alternate substitution replaces one glyph by one out of a set \stopitem +\stopitemize + +Like it or not, but these categories are not always used as intended: they just +are a way of replacing one or more glyphs by one or more other glyphs. This means +that when for instance \type {ij} gets replaced by one glyph (given that the font +supports it) a ligature substitution is used, even when in fact we have to do +with a diftong that can be represented by one character. + +No matter what features you will use, keep in mind that they are nothing more +than a combination of substitutions and positioning directives. So, the de facto +standard ligature building feature \type {liga} indeed uses a ligature +substitution, but other features with names that resemble no ligatures might use +this substitution as well. + +An example of a single substitution is an oldstyle (\type {onum}) although it can +as well be implemented as a choice out of alternate glyphs. Another example is +smallcaps (\type {smcp}). Nowdays these are more or less standard features for a +grown up font, while in the past they came as separate fonts. So, instead of loading +an extra font, one sticks to one and selects the feature that does the +substitution. + +A second category concerns relative positioning. Again we have several variants: + +\startitemize[packed] +\startitem a single positioning moves a glyph over one of two axis and can change the width and|/|or height \stopitem +\startitem a pair positioning also moved glyphs but concerns two adjacent glyphs \stopitem +\startitem a cursive positioning operates on a range of glyphs and is used to visually connect them \stopitem +\stopitemize + +In addition there are three ways to anchor marks onto glyphs: + +\startitemize[packed] +\startitem a mark can be anchored on a base glyph \stopitem +\startitem a mark can be anchored on a specific (visual) component of a ligature \stopitem +\startitem a mark can be anchored on another mark \stopitem +\stopitemize + +In base mode the single, alternate and ligature substitutions can rather easily +be mapped onto the traditional \TEX\ font handling mechanism and this is what +happens in base mode. A single substitution is just another instance of a glyph +so there we just replace the original index into the glyph table by another one. +In the case of an alternate we change the default index into one of several +possible replacements in the alternate set. Ligatures can be mapped onto \TEX s +ligature mechanism. The single positioning maps nicely on \TEX s kerning +mechanism and pairwise positioning is not applicable in base mode. In node mode +we don't do any remapping at loading time but delegate that to \LUA\ when +processing the node lists. + +Marks are special in the sense that they normally only occur in scripts that also +use substitution and positioning which in turn means that some more housekeeping +is involved. After all, we need to keep track to what a mark applies. Of course a +font can provide regular latin accents as marks but that is ill practice because +cut and paste might not work out as expected. A proper font will support composed +characters and provide glyphs that have the accents built in. Marks are not dealt +with in base mode. + +Talking of complex scripts, the above set of operations is far from enough. Take +for instance Arabic, where a sequence of 5~characters with 3~marks can easily +become two glyphs glued together with two marks only. In the process we can have +single substitutions, ligatures being built, marks being anchored and glyphs +being cursively positioned. But, in order to do this well, some contextual +analysis has to be done as well. Again we have several variants of this: + +\startitemize[packed] +\startitem with contextual substitution a replacement takes place depending on a matching sequence of glyphs, +optionally preceded or followed by matches \stopitem +\startitem with contextual positioning shifting and anchoring happens based on a matching sequence of glyphs, +optionally preceded or followed by matches \stopitem +\startitem multiple contextual substitutions or positionings can be chained together \stopitem +\startitem this can also happen in the reverse order (for right|-|to|-|left scripts) \stopitem +\stopitemize + +In practice there is no fundamental difference between these and we can collapse +them all in a sequence of lookups resulting in a sequence of whatever other +manipulation is wanted. + +Given this, what is a feature? It's mostly a sequence of actions expressed in the +above. And although there is a whole repertoire of semi|-|standardized features +like \type {liga} and \type {onum}, there is no real hard coded support for them +in \CONTEXT. Instead we have a generic feature processor that deals with all of +them. A feature, say \type {abcd}, has a definition that boils down to a sequence +of lookups. A lookup is just a name that is associated to one of the mentioned +actions. So, \type {abcd} can do a decomposition (multiple substitution), then a +replacement (single substitution) based on neighbouring glyphs, then do some +ligature building (ligature substitution) and finally position the resulting +glyphs relative to each other (like cursive positioning and anchoring marks). + +Imagine that we start out with 5 characters in the input. Instead of real glyphs +we represent them by rectangles. The third one is a mark. + +\startlinecorrection +\startMPcode + draw MyRectangle(1,2,6, 0,0,.5red ) ; + draw MyRectangle(2,2,4, 3,0,.5green ) ; draw MyDot(4,4.25) ; + draw MyRectangle(3,2,1, 6,5,.5blue ) ; draw MyDot(7,4.75) ; + draw MyRectangle(4,2,5, 9,0,.5yellow ) ; + draw MyRectangle(5,2,5,12,0,.5magenta) ; + currentpicture := currentpicture ysized(4cm) ; +\stopMPcode +\stoplinecorrection + +In the next variant we see that four and five have been replaced by +number six. This is a ligature replacement. + +\startlinecorrection +\startMPcode + draw MyRectangle(1,2,6,0,0,.5red ) ; + draw MyRectangle(2,2,4,3,0,.5green) ; draw MyDot(4,4.25) ; + draw MyRectangle(3,2,1,6,5,.5blue ) ; draw MyDot(7,4.75) ; + draw MyRectangle(6,3,5,9,0,.5cyan ) ; + currentpicture := currentpicture ysized(4cm) ; +\stopMPcode +\stoplinecorrection + +The mark is an independent entity. Sometimes it has a width, sometimes it hasn't. +In both cases we can position it. Here we move the shape left and down. There are +two ways to do this: simple pairwise kerning but better is to use anchors. Here +we have one anchor per shape but there can be many. + +\startlinecorrection +\startMPcode + draw MyRectangle(1,2,6,0,0 ,.5red ) ; + draw MyRectangle(2,2,4,3,0 ,.5green) ; + draw MyRectangle(3,2,1,3,4.5,.5blue ) ; draw MyDot(4,4.25) ; + draw MyRectangle(6,3,5,6,0 ,.5cyan ) ; + currentpicture := currentpicture ysized(4cm) ; +\stopMPcode +\stoplinecorrection + +Next we apply some kerning. Of course the anchored marks need to move as well. + +\startlinecorrection +\startMPcode + draw MyRectangle(1,2,6,0, 0 ,.5red ) ; + draw MyRectangle(2,2,4,2.5,0 ,.5green) ; + draw MyRectangle(3,2,1,2.5,4.5,.5blue ) ; draw MyDot(3.5,4.25) ; + draw MyRectangle(6,3,5,5, 0 ,.5cyan ) ; + currentpicture := currentpicture ysized(4cm) ; +\stopMPcode +\stoplinecorrection + +Alternatively we can connect the shapes in a cursive way. The name cursive is +somewhat misleading as it just boils down to shifting. The cursive indicates that +the shifts accumulate within a word. + +\startlinecorrection +\startMPcode + draw MyRectangle(1,2,6,0,0 ,.5red ) ; + draw MyRectangle(2,2,4,2,0.5,.5green) ; + draw MyRectangle(3,2,1,2,5 ,.5blue ) ; draw MyDot(3,4.75) ; + draw MyRectangle(6,3,5,4,1 ,.5cyan ) ; + currentpicture := currentpicture ysized(4cm) ; +\stopMPcode +\stoplinecorrection + +\stopsubsection + +\startsubsection[title={Single substitution}] + +Single substitutions are probably the most used ones. For instance, when you +ask for small caps, a lot of glyphs get replaced. When using oldstyle numerals +only digits get replaced but even then each glyph has to be checked. This can be +demonstrated with the Latin Modern fonts. + +\startlinecorrection +\scale + [height=1cm] + {\strut + {\definedfont[lmroman10-bold*default]\$123.45}% + \quad + {\definedfont[lmroman10-bold*oldstyle]\$123.45}} +\stoplinecorrection + +As you can see here, Latin Modern has an oldstyle dollar sign. If you don't like +that one, you're in troubles as it comes with the rest of the oldstyles. The only +way out is to apply the oldstyle numerals to digits only which involves more tagging +than you might be willing to add. So, whenever you choose a substitution, be aware +that you have not that much control over what gets substituted: it's the font that +drives it. Here are some examples: + +\starttyping +\definefontfeature[capsandold][smallcaps,oldstyle] + +\showotfcomposition{dejavu-serif*capsandold at 24pt}{}{It's 2013!} +\showotfcomposition{cambria*capsandold at 24pt}{}{It's 2013!} +\showotfcomposition{lmroman10regular*capsandold at 24pt}{}{It's 2013!} +\showotfcomposition{texgyrepagellaregular*capsandold at 24pt}{}{It's 2013!} +\stoptyping + +\definefontfeature[capsandold][smallcaps,oldstyle] + +\blank \showotfcomposition{dejavu-serif*capsandold at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{It's 2013!}} \blank +\blank \showotfcomposition{cambria*capsandold at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{It's 2013!}} \blank +\blank \showotfcomposition{lmroman10regular*capsandold at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{It's 2013!}} \blank +\blank \showotfcomposition{texgyrepagellaregular*capsandold at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{It's 2013!}} \blank + +\stopsubsection + +\startsubsection[title={Multiple substitution}] + +In a multiple substitution a sequence of characters (glyphs) gets replaced by +another sequence. In fact, you might wonder why one||to||one, multiple||to||one +and multiple||to||multiple are not all generalized into this variant. Efficiency +is probably the main reason. \footnote {Isn't it strange that complex mechanisms +are designed to save a few bytes while at the same time we produce ridiculous +large pictures with cameras.} For instance the many||to||one is often used for +ligatures (\type {liga}) and as a consequence \type {liga} is often misused also +for non||ligatures. + +One usage of multiple replacements is to avoid and or undo other replacements. In +the next example we see a language dependent \type {fi} ligature. Take the dutch +\type {ij} and \type {ie} diftongs. Here we need to prevent the \type {i} +becoming combined with the \type {f} as it would look weird. Among the solutions +for this are: context dependent ligatures (which involves a lot of rules), or +multiple to multiple replacements (looking at the \type {fij} sequence). + +\startbuffer[definitions] +\definefontfeature[default-fijn-en][default][language=eng,script=latn] +\definefontfeature[default-fijn-nl][default][language=nld,script=latn] +\stopbuffer + +\getbuffer[definitions] \typebuffer[definitions] + +\starttyping +\definedfont[lmroman10-regular*default-fijn-en]\en effe fijn fietsen +\definedfont[lmroman10-regular*default-fijn-nl]\nl effe fijn fietsen +\stoptyping + +This gives: + +\startlinecorrection[blank] +\scale [width=\textwidth] \bgroup + \framed [offset=overlay,frame=off,foregroundcolor=maincolor,align=normal,strut=no] \bgroup + \definedfont[lmroman10-regular*default-fijn-en]\en effe fijn fietsen\vskip-1ex + \definedfont[lmroman10-regular*default-fijn-nl]\nl effe fijn fietsen\par + \egroup +\egroup +\stoplinecorrection + +Of course from this result one cannot see what (combination of) substitution(s) +was used, but it's a nice exercise to work out a solution. + +Multiple substitutions are mostly used for scripts more complex than latin or +special fonts like Zapfino where advanced contextual analysis happens. + +\stopsubsection + +\startsubsection[title={Alternate substitution}] + +Alternates are simple one||to||one substitutions. Popular examples are small +capitials and oldstyle numerals. + +A nice application of alternates is the punk font. This font is a Knuth original. +As part of experimenting with the \METAPOST\ library in the early days of +\LUATEX\ and \MKIV, runtime randomization was implemented. However, that variant +used virtual fonts and was somewhat resource hungry. So, in a later stage Khaled +Hosny made an \OPENTYPE\ version using \METAPOST\ output. Randomization is +implemented through the \type {rand} feature. + +In \MKIV\ the \type {rand} feature is not really special and behaves just like +any other (stylistic) alternate. The only difference is that for this feature a +value of \type {yes} equals \type {random}. This also means that any feature that +uses alternates use them randomly. + +\startbuffer +\definefontfeature[punknova-first] [mode=node,kern=yes,rand=first] +\definefontfeature[punknova-2] [mode=node,kern=yes,rand=2] +\definefontfeature[punknova-yes] [mode=node,kern=yes,rand=yes] +\definefontfeature[punknova-random][mode=node,kern=yes,rand=random] +\stopbuffer + +\typebuffer \getbuffer + +We use this is: + +\startbuffer[sample] +The original punk font is designed by Don Knuth: xxxxxxxxxxxx +\stopbuffer + +\startbuffer +\definedfont[punknova-regular at 15pt] \getbuffer[sample] +\definedfont[punknova-regular*punknova-first at 15pt] \getbuffer[sample] +\definedfont[punknova-regular*punknova-2 at 15pt] \getbuffer[sample] +\definedfont[punknova-regular*punknova-yes at 15pt] \getbuffer[sample] +\definedfont[punknova-regular*punknova-random at 15pt] \getbuffer[sample] +\stopbuffer + +\typebuffer[sample] + +\typebuffer + +In order to illustrate the variants we show a sequence of \type {x}'s. There are +upto ten different variants per characters. + +\startlines[color=maincolor] \getbuffer \stoplines + +There is one pitfall with random alternates: if each run leads to a different +outcome, we can end up in oscillation: different shapes give different paragraphs +and we can get more pages or cross references etc.\ that can end up differently +so this is why \CONTEXT\ always uses the same random seed (which gets reset when +you purge the auxiliary files. + +\stopsubsection + +\startsubsection[title={Ligature substitution}] + +A ligature is traditionally a combination of several characters into one. Popular +ligatures are \quote {fi}, \quote {fl}, \quote {ffi} and , \quote {ffl}. +Occasionally we see \quote {\ae}, \quote {\oe} and some more. Often ligatures are +language dependant. For instance in languages like Dutch and German there can be +compound words where one part ends with an \type {f} and the next part starts with +an \type {f} and that looks bad or at least not intuitive. To some extent one +can wonder if this tradition of ligatures is a good one. It definitely made +sense ages ago, but I wouldn't be surprised if they are often added to fonts +because the encoding vectors have them. After all, nothing prevents to go ahead +and come up with way more ligatures. + +There can be many ligature features in a font. Although we support arbitrary +features, that is: those not registered as being official one way or the other, +the following are known by description: + +\startluacode +context.starttabulate { "|lTCT{maincolor}|l|" } +for k, v in table.sortedhash(fonts.handlers.otf.tables.features) do + if string.find(v,"ligature") then + context.NC() + context(k) + context.NC() + context(v) + context.NR() + end +end +context.stoptabulate() +\stopluacode + +The \type {default} feature set has type {liga} as wel as the \TEX\ specific \type {tlig} +that replaces successive hyphen signs into en- and emdashes. The \type {arabic} feature +set also has \type {rlig} enabled. + +Now, there is one thing you should realize when we discuss specific features and +the underlaying mechanisms: there is no real relationship between the features's +name and the mechanisms used: any feature can use any underlying mechanism or +combination. This is why deep down we see that what is internally called ligature +gets used for any purpose where multiple||to||one replacements happen, and why the +\type {liga} feature can use single substitutions or alternates to swap in +another rendering so that the dot of the \type {i} stays free of the preceding +\type {f}. And for some fonts relative positioning can be used to achieve a +ligature effect. + +The next examples demonstrate how the \type {liga} feature deals with \type {ffi}. +Possible solutions are: replace all three at once, replace the first two first and +in a next step, combine a ligature and following character, replace one or more +components by variants that have no interference with the dot of the~\quote{i}. + +\starttyping +\showotfcomposition{dejavu-serif*default at 48pt}{}{ffi} +\showotfcomposition{cambria*default at 48pt}{}{ffi} +\showotfcomposition{lmroman10regular*default at 48pt}{}{ffi} +\showotfcomposition{texgyrepagellaregular*default at 48pt}{}{ffi} +\stoptyping + +\blank \showotfcomposition{dejavu-serif*default at 48pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{ffi}} \blank +\blank \showotfcomposition{cambria*default at 48pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{ffi}} \blank +\blank \showotfcomposition{lmroman10regular*default at 48pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{ffi}} \blank +\blank \showotfcomposition{texgyrepagellaregular*default at 48pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{ffi}} \blank + +\stopsubsection + +\startsubsection[title={Single positioning}] + +Single positioning is also known as kerning, moving characters closer together so +that we get a more uniformly spaced sequence of glyphs. It is a mistake to think +that kerning is always needed! There are fonts that have hardly any kerns or no +kerns at all and still look good. + +\start + \showfontkerns \blank + \definedfont[dejavu-serif*default at 8pt]Dejavu Serif: \input tufte (E.R. Tufte)\blank + \definedfont[cambria*default at 9pt]Cambria: \input tufte (E.R. Tufte)\blank + \definedfont[lmroman10regular*default at 10pt]Latin Roman Regular: \input tufte (E.R. Tufte)\blank + \definedfont[lucidabrightot*default at 8pt]Lucida Bright: \input tufte (E.R. Tufte)\blank + \definedfont[texgyrepagellaregular*default at 9pt]Pagella Regular: \input tufte (E.R. Tufte)\blank +\stop + +The next couple of examples show the action for a few words: + +\blank \showotfcomposition{dejavu-serif*default at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{We thrive}} \blank +\blank \showotfcomposition{cambria*default at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{We thrive}} \blank +\blank \showotfcomposition{lmroman10regular*default at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{We thrive}} \blank +\blank \showotfcomposition{lucidabrightot*default at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{We thrive}} \blank +\blank \showotfcomposition{texgyrepagellaregular*default at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{We thrive}} \blank + +\stopsubsection + +\startsubsection[title={Pairwise positioning}] + +This variant of positioning involved the first, second or both glyphs of a glyph +pair. The specification can influence the horizontal and vertical positions we +well as the widths of the positioned glyphs. + +\startnotabene + We need an example here. +\stopnotabene + +\stopsubsection + +\startsubsection[title={Mark positioning}] + +Marks are (often) small symbols that represent accents (in latin) or vowels (in +arabic) that get attached to base glyphs. In the input stream they come after the +character that they apply to. Many fonts come with precomposed latin characters +which means that an \type {à} in the input is mapped directly onto its +corresponding shape. When the input contains an \type {a} followed by a \type{̀ } +input normalization will normally turn this into an \type {à}. But, when this +doesn't happen, the font machinery has to make sure that the mark gets positioned +right onto the base character. In traditional \TYPEONE\ fonts that more or less +happened automatically by overlaying the shapes. In \OPENTYPE\ (single) +positioning is used to place the mark right. + +\startnarrowtyping +\showotfcomposition{dejavu-serif*default at 24pt}{}{à a\utfchar{"0300} à} +\showotfcomposition{cambria*default at 24pt}{}{à a\utfchar{"0300} à} +\showotfcomposition{lmroman10regular*default at 24pt}{}{à a\utfchar{"0300} à} +\showotfcomposition{lucidabrightot*default at 24pt}{}{à a\utfchar{"0300} à} +\showotfcomposition{texgyrepagellaregular*default at 24pt}{}{à a\utfchar{"0300} à} +\stopnarrowtyping + +Of course a font can contain logic that replaces a sequence of base and mark into +precomposed characters with the right \UNICODE\ entry. + +\blank \showotfcomposition{dejavu-serif*default at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{à a\utfchar{"0300} à}} \blank +\blank \showotfcomposition{cambria*default at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{à a\utfchar{"0300} à}} \blank +\blank \showotfcomposition{lmroman10regular*default at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{à a\utfchar{"0300} à}} \blank +\blank \showotfcomposition{lucidabrightot*default at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{à a\utfchar{"0300} à}} \blank +\blank \showotfcomposition{texgyrepagellaregular*default at 24pt}{}{\disabletrackers[otf.analyzing]\color[maincolor]{à a\utfchar{"0300} à}} \blank + +You can imagine that when marks are bound to characters that have become +ligatures the anchoring is more complex as the font machinery has to keep track +of onto which component the mark goes. For this purpose marks as well as base +characters and base ligatures have anchors and feature lookups can explicitly +refer to them. + +\stopsubsection + +\startsubsection[title={Contextual analysis}] + +What actually happens when turning a list of characters into a list of glyphs can +range from real simple to pretty complex. For instance the \type {smcp} feature +only has to run over the list and relate characters to a smallcaps shape. A +slightly more complex feature might also demand some positioning. One step further +is the use of contextual analysis, i.e. looking at previous, current and following +characters (or glyphs). Because features can range from simple to complex the actual +processing is not per feature! A font comes with a sequence of so called lookups that +relate to a feature, script and language. Also, each feature can use one||to||one, +multiple||to||one and many||to||many replacements as well as relative positioning. + +So, what actually happens is not that a feature is processed, but that all features +are dealt with at the same time, in the order that the font prescribes. Enabling a +specific feature means that a step is executed, while a disabled feature skips all +steps that are tagged as belonging to that feature. And, as each feature can use +contextual analysis, you can imagine that the effective sequence of actions can be +a complex mix. + +A nice example of a contextual substitution is the centered period character in +catalan in \type {ebgaramond}: + +\startbuffer +\definefontfeature + [example] + [default] + [locl=yes,script=latn,language=cat] + +\definedfont[file:ebgaramond12-regular.otf*default at 40pt]l·l\quad +\definedfont[file:ebgaramond12-regular.otf*example at 40pt]l·l +\stopbuffer + +\typebuffer + +We show the boundingbox of the glyphs. The centered period between two l's is +is replaced by a raised variant with no width. + +\blank \start \showglyphs \maincolor \midaligned{\getbuffer} \stop \blank + +It will be clear that in order to use such features you need to know what the font +provides. For some fonts you need to explicitly enable the latin script (while others +use default). Such a feature can be part of localized support but that is no rule. +In that respect \OPENTYPE\ features are a rather unpredictable mess. For instance, +nothing prevents such a feature to be a ligature, and in case you find that strange, +especially ligature features are often abused for any purpose. + +\stopsubsection + +\startsubsection[reference=ligatures:hyphenation,title=Ligatures and hyphenation] + +In this section we will say a few words on how hyphenation interferes with +(especially) ligature building. For this you need to know that: + +\starttyping +effe +\stoptyping + +But when hyphenation is permitted between the two \type{s}'s we actually have +internally: + +\starttyping +ef{-}{}{}fe +\stoptyping + +The first snippet comes at the end of a line, the second at the beginning of a +the next line and the last snippet is used when no hyphenation is needed. Such +triplets need to be taken into account when we do replacements and positioning +and also when we do contextual lookups. + +An \OPENTYPE\ font is just a container that collects the following: + +\startitemize[packed] +\startitem + graphic representations of characters and symbols +\stopitem +\startitem + information about what characters the shapes represent +\stopitem +\startitem + rules about converting (sequences of) characters into one or more + representations +\stopitem +\startitem + rules about positioning representations relative to each other +\stopitem +\stopitemize + +Although the way this information is stored is standardized, the rules are not. +You can imagine that there would be some standard way to turn an \type {f} and +\type {i} into an \quote{fi} but we already saw that this is not the case. Here +are some possibilities: + +\startitemize[packed] +\startitem + The two characters get their own standard glyph, maybe with some kerning. +\stopitem +\startitem + The two characters are combined into one shape. +\stopitem +\startitem + The \type{f} gets a narrow representation and is kept close to the standard + \type{i}. +\stopitem +\startitem + A standard \type {f} is kerned with a dotless \type{i} (not to be confused + with the \UNICODE\ character). +\stopitem +\startitem + A special \type {f} is combined with a special \type {i}. +\stopitem +\stopitemize + +% maybe mark lig components when separate chars so that we can do spacing + +If the two characters are represented by their own shape, some contextual +analysis takes place. Again there are several approaches to this: + +\startitemize[packed] +\startitem + When an \type{f} is seen in the input, the next character is checked and one + or both gets replaced. +\stopitem +\startitem + When an \type{i} is seen in the input, the previous character is checked and + the \type {i} gets replaced. +\stopitem +\startitem + When an \type{f} several following characters are checked, for instance to + see if we need to take \type {ij} into account. +\stopitem +\stopitemize + +Traditionally the \type {f} followed by an \type{f}, \type{l} and \type{i} get a +treatment, but some fonts also combine the \type {f} with \type {k}, \type {j}, +\type {b}, \type {t} and more. + +The \MKIV\ font handler is rather generic in the sense that it support what the +font requires. However, a complication is that the scripts (languages) that use +these diverse methods also expect hyphenation within such a ligature. Script like +Arabic that are more demanding don't hyphenate so there interference with +hyphenation is not a problem. + +Some ligatures are sensitive for languages. In languages that have compound words +it might be undesirable to have a ligature at a word boundary, or in the Dutch +word \type {fijn} we like to have a nice glyph (or combinations) for \type {ij} +but no \type {fi} ligature. In a similar way hyphenation patterns can have +rules and it will be no surprise that the hyphenation mechanism can compete with +the ligature building for the best solution. This gets complicated by the fact +that there is no real way to recognize in the font handler if we really are +dealing with ligature building. Not only is the \type {liga} feature (and deep +down the ligature gsub handling) not bound to ligatures (but simply a +many|-|to|-|one mapper), some of the mentioned pseudo ligature builders use simple +substitution and kerning and there is no way to recognize that as a ligature. + +Although it is possible to come up with a solution that is acceptable for many cases, +there is no way to predict what kind of tricks font designers will use. A hyphenation +point can be seen as follows: + +\starttabulate[||||] +\NC \type{effe} \NC \type{ef-fe} \NC \type{e{f-}{f}{ff}e} \NC \NR +\NC \type{efficient} \NC \type{ef-fi-cient} \NC \type{e{ffi-}{}{ffi}cient} \NC \NR +\stoptabulate + +In the second case the larger ligatures has replaced the previous one. We could +have kept the first one because there are ways to manage two|-|step bounding +ligatures but it's not worth the trouble (read: way more complex code and +increased runtime for the whole mechanism). Here the \type {{ff}} and \type +{{ffi}} can be individual shapes or just one shape. + +The three components of a hyphenation point: the pre, post and replacement text +need to be looked at independently so that we get the proper kerning with the +preceding and following characters. Also, in more complex (chained) lookups we +need to compare each element with its surrounding. A fully expanded solution tree +is too time consuming so we take some shortcuts and limits the checks to the +level that it has no big impact on performance. The occasionally needed +backtracking and inspection of components is currently quite reasonable. We need +to trade quality with convenience: the result should look okay but processing +speed should also be as high as possible. There is no need to let other scripts +or regular fonts suffer too much from excessive script demands of fonts that +could have be done better. + +The complication is that we not only need to check and replace but also need to +check the kerning with preceding and following characters. We also need to take +the hyphen into account (here one, but there can also be one after the break. + +It is for this reason that in \MKIV\ we have a (we think) acceptable mix of +heuristics around hyphenation points that deal with single and multiple +substitution as well as kerning. It will never be 100\% pertect but we consider +it better to drop an occasional hyphenation in favor of proper font handling. In +practice \TEX\ is clever enough to break a paragraph in lines within these +restrictions. + +In \CONTEXT\ we have the traditional \TEX\ hyphenator but also provide an +extensible \LUA\ reimplementation. That one might become the default in future +versions. In traditional \TEX\ there are several low level hyphenation +representations: simple hyphen only points, injected by the hyphenator, +explicitly injected by the user or originating from a hyphen character. Then +there is the generic (pre, post, replace) discretionary that can be explicitly +injected by the user (or a macro). In \MKIV\ all hyphenation points get +normalized to this generic discretionary. There is no need for old|-|time +optimizations and a consistent (expanded) representation is easier to deal with +in other extensions. However, because the font handler is supposed to also work +outside \CONTEXT\ we need to deal with traditional cases too. But \unknown\ the +results might differ a bit. + +\stopsubsection + +\startsubsection[title=Color] + +% TODO: use emojionecolor-svginot-archived.ttf + +A recent new (and evolving) addition to \OPENTYPE\ is colored glyphs. One variant +(by \MICROSOFT) uses overlays and this method is quite efficient. + +\startbuffer +\definefontfeature[colored][colr=yes] +\definefontsynonym[Emoji][file:seguiemj.ttf*default,colored] + +\definesymbol[bug][\getglyphdirect{Emoji}{\char"1F41B}] +\definesymbol[ant][\getglyphdirect{Emoji}{\char"1F41C}] +\definesymbol[bee][\getglyphdirect{Emoji}{\char"1F41D}] +\stopbuffer + +\typebuffer \getbuffer + +Here we see a \symbol[bug], \symbol[ant] and \symbol[bee], and they come in +color! Once \UNICODE\ started adding such symbols (and more get added) the +distinction between characters and symbols get even fuzzier. Of course one +can argue that we communicate in pictograms but even then, given that +mankind lasts a while, the \UNICODE\ repertoire will explode. + +\startplacefigure[title={A few emojis from \type {seguiemj.ttf}}] + \startcombination [3*1] + {\scale[width=.3\textwidth]{\symbol[bug]}} {\type{U+1F41B}: bug} + {\scale[width=.3\textwidth]{\symbol[ant]}} {\type{U+1F41C}: ant} + {\scale[width=.3\textwidth]{\symbol[bee]}} {\type{U+1F41D}: bee} + \stopcombination +\stopplacefigure + +Here we use \type {seguiemj.ttf}, a font that comes with \MSWINDOWS. Colors are +achieved by combining glyphs rendered in different colors. A variant that uses +\SVG\ instead of overlays is \type {emojionecolor-svginot.ttf}: + +\startbuffer +\definefontfeature[svg][svg=yes] +\definefontsynonym[Emoji][file:emojionecolor-svginot.ttf*default,svg] +\stopbuffer + +\typebuffer \getbuffer + +This time we get \symbol[bug], \symbol[ant] and \symbol[bee] and they look +quite different. Both fonts also have ligatures and you can wonder what sense +that makes. It makes it impossible to swap fonts and as there is no standard +one never knows what to expect. + +\startplacefigure[title={A few emojis from \type {emojionecolor-svginot.ttf}}] + \startcombination [3*1] + {\scale[width=.3\textwidth]{\symbol[bug]}} {\type{U+1F41B}: bug} + {\scale[width=.3\textwidth]{\symbol[ant]}} {\type{U+1F41C}: ant} + {\scale[width=.3\textwidth]{\symbol[bee]}} {\type{U+1F41D}: bee} + \stopcombination +\stopplacefigure + +\definefont[emoji][file:emojionecolor-svginot.ttf*default,svg] + +\def\FourFaces{\char128104\zwj\char128105\zwj\char128102\zwj\char128102\relax} + +\def\Man {\char"1F468\relax} +\def\Woman{\char"1F469\relax} +\def\Boy {\char"1F466\relax} +\def\Girl {\char"1F467\relax} + +How do we know what faces add up to the ligature {\emoji\Man \zwj \Woman \zwj +\Girl \zwj \Boy} and how are we supposed to know that there should {\darkgray +\type {zwj}} in between? When we input four faces seoarated by zero width +joiners, we get a four face symbol instead. The reason for having the joiners in +between is probably to avoid unexpected ligatures. The sequence \type {man}, +\type {woman}, \type {boy}, \type {boy} gives \type {family}: +% +{\emoji\Man} + {\darkgray \type {zwj}} +{\emoji\Woman} + {\darkgray \type {zwj}} +{\emoji\Boy} + {\darkgray \type {zwj}} +{\emoji\Boy} = {\emoji\Man \zwj \Woman \zwj \Boy \zwj \Boy}, +% +but two girls also work: +% +{\emoji\Man} + {\darkgray \type {zwj}} +{\emoji\Woman} + {\darkgray \type {zwj}} +{\emoji\Girl} + {\darkgray \type {zwj}} +{\emoji\Girl} = {\emoji\Man \zwj \Woman \zwj \Girl \zwj \Girl}, +% +so does a mixture of kids: +% +{\emoji\Man} + {\darkgray \type {zwj}} +{\emoji\Woman} + {\darkgray \type {zwj}} +{\emoji\Girl} + {\darkgray \type {zwj}} +{\emoji\Boy} = {\emoji\Man \zwj \Woman \zwj \Girl \zwj \Boy}, +% +although (at least currently): +% +{\emoji\Man} + {\darkgray \type {zwj}} +{\emoji\Woman} + {\darkgray \type {zwj}} +{\emoji\Boy} + {\darkgray \type {zwj}} +{\emoji\Girl} = {\emoji\Man \zwj \Woman \zwj \Boy \zwj \Girl}, +% +gives twin boys. Of course the real family emoj is {\emoji\char"1F46A}. + +In our times for sure many combinations are possible, so: +% +{\emoji\Man} + {\darkgray \type {zwj}} +{\emoji\Man} + {\darkgray \type {zwj}} +{\emoji\Girl} + {\darkgray \type {zwj}} +{\emoji\Girl} = {\emoji\Man \zwj \Man \zwj \Girl \zwj \Girl}, +% +indeed gives a family, but I wonder at what point cultural bias will creep into +font design. One can even wonder how clothing and haircut will demand frequent +font updates: {\emoji\char"1F46B}, {\emoji\char"1F46C}, {\emoji\char"1F46D}. + +In the math alphabets we have a couple of annoying holes because some characters +were already present in \UNICODE. The bad thing here is that we now always have +to deal with these exceptions. But not so with emojis because here eventually all +variants will show up. Where a character \type {A} in red or blue uses the same +code point, a white telephone {\emoji\char"1F57E} and black telephone +{\emoji\char"1F57F} have their own. And because obsolete scripts are already +supported in \UNICODE\ and more get added, we can expect old artifacts also +showing up at some time. Soon the joystick {\emoji\char"1F579} will be an unknown +item to most of us, while the \MICROSOFT\ hololens migth get its slot. + +\startplacefigure[title={Will all animals come in stages of development?}] + \startcombination [3*1] + {\scale[width=.3\textwidth]{\emoji\char"1F423}} {\type{U+1F423}: hatching chick} + {\scale[width=.3\textwidth]{\emoji\char"1F424}} {\type{U+1F424}: baby chick} + {\scale[width=.3\textwidth]{\emoji\char"1F425}} {\type{U+1F425}: front-facing baby chick} + \stopcombination +\stopplacefigure + +For sure these mechanisms will evolve and to what extent we support them depends +on what users want. At least we have the basics implemented. + +\stopsubsection + +\stopsection + +\startsection[title=Extras] + +\startnotabene + Todo. +\stopnotabene + +\stopsection + +\startsection[reference=goodies,title=Goodies] + +Goodies range from simple to complex. They share that they are defined in files +and loaded at runtime. There is a good change that when you read this, that there +are already more goodies than mentioned here. Here we will just mention a couple +of goodies. More details can be found in the files that ship with \CONTEXT\ and +have suffix \type {lfg}. + +A goodie file is a regular \LUA\ file and is supposed to return a table. This +table collects data that is used for implementing the goodie or relates to a +regular feature. It can also provide information that is used for patching a +font. An example of a simple goodie file is the ones that accompanies the first +release of the \OPENTYPE\ Lucida fonts. + +\starttyping +return { + name = "lucida-opentype-math", + version = "1.00", + comment = "Goodies that complement lucida opentype.", + author = "Hans Hagen", + copyright = "ConTeXt development team", + mathematics = { + alternates = { + italic = { + feature = 'ss01', + value = 1, + comment = "Mathematical Alternative Italic" + }, + } + } +} +\stoptyping + +This goodie file is only providing information about the meaning of a stylistic +alternate. These have abstract tags like \type {ss01} and in this case this +category collects alternative italic (calligraphic) shapes. Because math does +not follow the same rules as text, this feature is enabled explicitly. + +In the goodie file of Xits math the alternates table has more entries: + +\startnarrowtyping +alternates = { + cal = { ... comment = "Mathematical Calligraphic Alphabet" }, + greekssup = { ... comment = "Mathematical Greek Sans Serif Alphabet" }, + greekssit = { ... comment = "Mathematical Italic Sans Serif Digits" }, + monobfnum = { ... comment = "Mathematical Bold Monospace Digits" }, + mathbbbf = { ... comment = "Mathematical Bold Double-Struck Alphabet" }, + mathbbit = { ... comment = "Mathematical Italic Double-Struck Alphabet" }, + mathbbbi = { ... comment = "Mathematical Bold Italic Double-Struck Alphabet" }, + upint = { ... comment = "Upright Integrals" }, + vertnot = { ... comment = "Negated Symbols With Vertical Stroke" }, +} +\stopnarrowtyping + +An alternate is triggered at the \TEX\ end with: + +\starttyping +$ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$ +\stoptyping + +This is an example of a dynamic feature that gets applied when enabled at a +specific location in the input. The \type {cal} is only recognized when it +is defined in a goodies file, where the value is defined (in all of the above cases +the value is~\type {1}). + +The Xits math fonts has a goodie files that starts with: + +\starttyping +return { + name = "xits-math", + version = "1.00", + comment = "Goodies that complement xits (by Khaled Hosny).", + author = "Hans Hagen", + copyright = "ConTeXt development team", + mathematics = { + italics = { + ["xits-math"] = italics, + }, + alternates = { +\stoptyping + +Here the \type {italics} variable is a table defined before the \type {return} +that looks as follows: + +\starttyping +local italics = { + defaultfactor = 0.025, + disableengine = true, + corrections = { + -- [0x1D44E] = 0.99, -- a (fraction of quad) + -- [0x1D44F] = 100, -- b (font points) + [0x1D453] = -0.0375, -- f + } +} +\stoptyping + +This rather specific table tells \CONTEXT\ that (when enabled) it has to apply +italic correction. It disables support built into the \TEX\ engine (which in the +case of \LUATEX\ is close to absent anyway). It will apply a default italic +correction of \type {0.025} but for some shapes a different value is used. Again +we have some commands at the \TEX\ end: + +\starttyping +\setupmathematics[italics=1] % fontitalics +\setupmathematics[italics=2] % fontdata +\setupmathematics[italics=3] % quad based +\setupmathematics[italics=4] % combination of 1 and 3 +\stoptyping + +Because (definitely at the start of the \LUATEX\ project) we had no +proper \OPENTYPE\ math fonts, but at the same time wanted to move on +to \OPENTYPE\ and \UNICODE\ math and no longer struggle with all +those math families and definitions. The way out of this problem +is to define a virtual math font. The code for doing this is built +into the \MKIV\ core but is controlled by a goodie definition. Take +for instance Antykwa Math: + +\startnarrowtyping +return { + name = "antykwa-math", + version = "1.00", + comment = "Goodies that complement antykwa math.", + author = "Hans, Mojca, Aditya", + copyright = "ConTeXt development team", + mathematics = { + mapfiles = { + "antt-rm.map", + "antt-mi.map", + "antt-sy.map", + "antt-ex.map", + "mkiv-base.map", + }, + virtuals = { + ["antykwa-math"] = { + { name = "file:AntykwaTorunska-Regular", features = "virtualmath", main = true }, + { name = "mi-anttri.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "mi-anttri.tfm", vector = "tex-it", skewchar=0x7F }, + { name = "sy-anttrz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , + { name = "ex-anttr.tfm", vector = "tex-ex", extension = true } , + { name = "msam10.tfm", vector = "tex-ma" }, + { name = "msbm10.tfm", vector = "tex-mb" }, + }, +\stopnarrowtyping + +Normally users will not define such tables but the keys give an indication of +what is involved. The same is true for the previously shown tables: they are just +provided in the \CONTEXT\ distribution. + +Text fonts also can have goodies. We start with a rather dumb one and there +will be not that many of those. This one is needed to turn a \TYPEONE\ font +with a rather special encoding into a \UNICODE\ font. The next mapping is +possible because the dingbats are part of \UNICODE. + +\starttyping +return { + name = "dingbats", + version = "1.00", + comment = "Goodies that complement dingbats (funny names).", + author = "Hans Hagen", + copyright = "ConTeXt development team", + remapping = { + tounicode = true, + unicodes = { + a1 = 0x2701, + a10 = 0x2721, + a100 = 0x275E, + a101 = 0x2761, + a102 = 0x2762, +\stoptyping + +Applying this encoding happens in two steps. Because goodies like this are just +features, we need to define a proper font feature set: + +\starttyping +\definefontfeature + [dingbats] + [mode=base, + goodies=dingbats, + unicoding=yes] +\stoptyping + +We have a base mode font, so no special processing takes place. The \type {goodies} +key is used to communicate the goodies file. The \type {unicoding} key is used +to apply the encoding. Of course this only works because the remapper code is present +in the core and is hooked in to the font initialization code. The \type {dingbats} +feature set is predefined, just as the font definition: + +\starttyping +\definefontsynonym [ZapfDingbats] [file:uzdr] [features=dingbats] +\stoptyping + +Here is a goodie file that I made a while ago: + +\starttyping +return { + name = "oxoniensis", + version = "1.00", + comment = "Oxoniensis test file for Thomas Schmitz.", + author = "Hans Hagen", + copyright = "ConTeXt development team", + features = { + lunatesigma = { + type = "substitution", + data = { + sigma = 0x03F2, + sigma1 = 0x03F2, + Sigma = 0x03F9, + phi = phi1, + }, + } + }, +} +\stoptyping + +There is not that much to say about this, apart from that it's a sort of fake +feature that gets enabled as regular one: + +\starttyping +\definefontfeature[test] + [mode=node, + kern=yes, + lunatesigma=yes, + goodies=oxoniensis] + +\definefont[somefont][file:oxoniensis*test] +\stoptyping + +A complete different kind of goodie is the following. At one of the \CONTEXT\ meetings +Mojca Miklavec discussed the possibility to have an additional mechanism for +defining combinations of fonts. Often fonts come in a set of four (regular, italic, +bold and bold italic). In \MKII\ the complexity of typescripts depends on the amount of +encodings that need to be supported but in \MKIV\ things are easier. For a set of four fonts +a typescript looks as follows: + +\starttyping +\starttypescript [sans] [somesansfont] [name] + \setups[font:fallback:sans] + \definefontsynonym [Sans] [file:somesans] [features=default] + \definefontsynonym [SansBold] [file:somesansb] [features=default] + \definefontsynonym [SansItalic] [file:somesansi] [features=default] + \definefontsynonym [SansBoldItalic] [file:somesansz] [features=default] +\stoptypescript +\stoptyping + +We still have the abstract notion of a \type {Sans} font so that we can refer to +the regular shape without knowing the real name but the number of lines needed +is small. Such a definition can then be referred to using: + +\starttyping +\starttypescript[somefontset] + \definetypeface [somefontset] [rm] [serif] [someserif] [default] + \definetypeface [somefontset] [ss] [sans] [somesans] [default] + \definetypeface [somefontset] [tt] [mono] [somemono] [default] + \definetypeface [somefontset] [mm] [math] [somemath] [default] +\stoptypescript +\stoptyping + +So far things look simple. Given that many fonts follow a similar naming scheme +Wolfgang made a module that avoids such definitions altogether. However, being +involved in the development of the Antykwa fonts, Mojca ran into the situation +that not just four fonts were part of the set but many more. There are several +weight (think of light and heavy variants) as well as condensed variants and of +course the whole set is not per se a multiple of four. + +In the meantime, in addition to the \type {file:} and \type {name:} accessors, +\CONTEXT\ had an additional one tagged \type {spec:} where a string made out of +weight, style, width etc.\ is turned into a (best guessed) font name. Therefore +the most natural way to deal with the many|-|fonts|-|in|-|a|-|set dilemma was to +provide an additional interface between this specification and the font set and +the most robust method was to define all in a goodie file. + +In this case the goodies are loaded independent of the font, that is: not +as a feature. For instance: + +\starttyping +\loadfontgoodies[antykwapoltawskiego] +\stoptyping + +This file maps obscure fontnames onto the \type {spec:} interface so that +we can access them in a robust way. + +\starttyping +\definefont + [MyFontA] + [file:Iwona-Regular*smallcaps] +\definefont + [MyFontB] + [file:AntykwaTorunska-Regular*smallcaps] +\definefont + [MyFontC] + [file:antpoltltcond-regular*smallcaps] +\definefont + [MyFontD] + [spec:antykwapoltawskiego-bold-italic-condensed-normal*smallcaps] +\definefont + [MyFontE] + [spec:antykwapoltawskiego-bold-italic-normal] +\stoptyping + +The goodies file looks as follows: + +\starttyping +return { + name = "antykwa-poltawskiego", + version = "1.00", + comment = "Goodies that complement Antykwa Poltawskiego", + author = "Hans & Mojca", + copyright = "ConTeXt development team", + files = { + name = "antykwapoltawskiego", -- shared + list = { + ["AntPoltLtCond-Regular.otf"] = { + weight = "light", + style = "regular", + width = "condensed", + }, + ... + ["AntPoltExpd-BoldItalic.otf"] = { + weight = "bold", + style = "italic", + width = "expanded", + }, + }, + }, + typefaces = { + ["antykwapoltawskiego-light"] = { + shortcut = "rm", + shape = "serif", + fontname = "antykwapoltawskiego", + normalweight = "light", + boldweight = "medium", + width = "normal", + size = "default", + features = "default", + }, + ... + }, +} +\stoptyping + +In addition to the files|-|to|-|specification mapping, there is +also a typeface specification table. This permits the definition +of a typeface in the following way: + +\starttyping +\definetypeface + [name=mojcasfavourite, + preset=antykwapoltawskiego, + normalweight=light, + boldweight=bold, + width=expanded] + +\setupbodyfont + [mojcasfavourite] +\stoptyping + +When resolving the definition, the best possible match will be taken from the +typeface table in the goodie file. Of course this is not something that we expect +the average user to deliver and deal with. + +As the Antykwa font is somewhat atypical and not used in everyday typesetting, +you might wonder if all this overhead makes sense. However, there are type +foundries that do ship their fonts in many weights and for those using a \LUA\ +goodie file instead of many typescripts in \TEX\ coding makes sense. Take for +instance TheMix: + +\starttyping +\loadfontgoodies + [themix] + +\definetypeface + [name=themix, + preset=themix-light] + +\definetypeface + [name=themix, + preset=themixmono-light] + +\setupbodyfont + [themix] +\stoptyping + +In this case the goodie file can serve as a template for more such fonts. +In order to be efficient this goodie file uses a couple of local +tables (we could have used metatables instead). + +\starttyping +local themix = { + name = "themix", + shortcut = "ss", + shape = "sans", + fontname = "themix", + width = "normal", + size = "default", + features = "default", +} + +local themixmono = { + name = "themixmono", + shortcut = "tt", + shape = "mono", + fontname = "themixmono", + width = "normal", + size = "default", + features = "default", +} +\stoptyping + +The main goodie table defines a lot of weights: + +\startnarrowtyping +return { + name = "themix", + version = "1.00", + comment = "Goodies that complement TheMix (by and for sale at www.lucasfonts.com).", + author = "Hans Hagen", + copyright = "ConTeXt development team", + files = { + list = { + ["TheMixOsF-ExtraLight"] = { + name = "themix", + weight = "extralight", + style = "regular", + width = "normal" + }, + ["TheMixOsF-ExtraLightItalic"] = { + ... + }, + ... + ["TheMixOsF-Black"] = { + ... + }, + ["TheMixOsF-BlackItalic"] = { + ... + }, + ... + -- + ["TheMixMono-W2ExtraLight"] = { + name = "themixmono", + weight = "extralight", + style = "regular", + width = "normal" + }, + ... + ["TheMixMono-W9BlackItalic"] = { + ... + }, + }, + }, + typefaces = { + ["themix-extralight"] = table.merged(themix, { + normalweight = "extralight", + boldweight = "semilight" + }), + ["themix-light"] = table.merged(themix, { + normalweight = "light", + boldweight = "normal" + }), + ... + ["themixmono-bold"] = table.merged(themixmono, { + normalweight = "bold", + boldweight = "black" + }), + }, +} +\stopnarrowtyping + +It's now time for some generic goodies. In the \CONTEXT\ distribution there +is a goodie file that (at the time of this writing) looks as follows: + +\starttyping +local default = { + analyze = "yes", + mode = "node", + language = "dflt", + script = "dflt", +} + +local smallcaps = { + smcp = "yes", +} + +local function statistics(tfmdata) + commands.showfontparameters(tfmdata) +end + +local function squeeze(tfmdata) + for k, v in next, tfmdata.characters do + v.height = 0.75 * (v.height or 0) + v.depth = 0.75 * (v.depth or 0) + end +end + +return { + name = "demo", + version = "1.01", + comment = "An example of goodies.", + author = "Hans Hagen", + featuresets = { + default = { + default, + }, + smallcaps = { + default, smallcaps, + }, + }, + colorschemes = { + default = { + [1] = { + "one", "three", "five", "seven", "nine", + }, + [2] = { + "two", "four", "six", "eight", "ten", + }, + }, + all = { + [1] = { + "*", + }, + }, + some = { + [1] = { + "0x0030:0x0035", + }, + }, + }, + postprocessors = { + statistics = statistics, + squeeze = squeeze, + }, +} +\stoptyping + +This demo file implements several goodies: featuresets, colors and +postprocessors. Keep in mind that a goodie file can provide whatever information +it wants but of course only known subtables will be dealt with. + +The coloring of glyphs can happen by name, which assumes that glyph names are +used, or by number. Here we use generic glyph names, but for a specific font one +might need to provide a special goodie file. For instance, the color section of +the goodie file for the husayni font has entries like: + +\startnarrowtyping +[3] = { + "Ttaa.waqf", "SsLY.waqf", "QLY.waqf", "Miim.waqf", "LA.waqf", "Jiim.waqf", + "Threedotsabove.waqf", "Siin.waqf", "Ssaad.waqf", "Qaaf.waqf", "SsL.waqf", + "QF.waqf", "SKTH.waqf", "WQFH.waqf", "Kaaf.waqf", "Ayn.ruku", "Miim.nuun_high", + "Siin.Ssaad", "Nuunsmall", "emptydot_low", "emptydot_high", "Sifr.fill", + "Miim.nuun_low", "Nuun.tanwiin", +}, +\stopnarrowtyping + +Of course such a definition can only be made when the internals of the font are +known and in this case it concerns a pretty complex font. + +\startbuffer +\definefontfeature + [demo-colored] + [goodies=demo, + colorscheme=default, + featureset=default] + +\definefontfeature + [demo-colored-all] + [goodies=demo, + colorscheme=all, + featureset=default] + +\definefontfeature + [demo-colored-some] + [goodies=demo, + colorscheme=some, + featureset=default] + +\definefont[DemoFontA][MonoBold*demo-colored at 10pt] +\definefont[DemoFontB][MonoBold*demo-colored-all at 10pt] +\definefont[DemoFontC][MonoBold*demo-colored-some at 10pt] +\stopbuffer + +\typebuffer \getbuffer + +% \definecolor[colorscheme:1:1][s=.75] +% \definecolor[colorscheme:1:2][r=.75] +% \definecolor[colorscheme:1:3][g=.75] +% \definecolor[colorscheme:1:4][b=.75] +% \definecolor[colorscheme:1:5][c=.75] +% \definecolor[colorscheme:1:6][m=.75] +% \definecolor[colorscheme:1:7][y=.75] + +% \definecolor[colorscheme:2:7][s=.75] +% \definecolor[colorscheme:2:6][r=.75] +% \definecolor[colorscheme:2:5][g=.75] +% \definecolor[colorscheme:2:4][b=.75] +% \definecolor[colorscheme:2:3][c=.75] +% \definecolor[colorscheme:2:2][m=.75] +% \definecolor[colorscheme:2:1][y=.75] + +\startbuffer +\starttabulate[||||] +\NC + \DemoFontA \resetfontcolorscheme test 1234567890 \NC + \DemoFontA \setfontcolorscheme [1]test 1234567890 \NC + \DemoFontA \setfontcolorscheme [2]test 1234567890 \NC +\NR +\NC + \DemoFontB \resetfontcolorscheme test 1234567890 \NC + \DemoFontB \setfontcolorscheme [1]test 1234567890 \NC + \DemoFontB \setfontcolorscheme [2]test 1234567890 \NC +\NR +\NC + \DemoFontC \resetfontcolorscheme test 1234567890 \NC + \DemoFontC \setfontcolorscheme [1]test 1234567890 \NC + \DemoFontC \setfontcolorscheme [2]test 1234567890 \NC +\NR +\stoptabulate +\stopbuffer + +\typebuffer \getbuffer + +Here is an example that I made at the TUG 2013 conference in Japan, +after a presentation by Chof. The font (adapted by by Dohyun Kim) can +be downloaded from: \hyphenatedurl {http://ftp.ktug.org/KTUG/hcr-lvt/1.910_nomac/}. + +\startbuffer[korean-demo] +\definefontfeature + [korean-composed] + [goodies=hanbatanglvt, + colorscheme=default, + mode=node, + ljmo=yes, + tjmo=yes, + vjmo=yes, + script=hang, + language=kor] + +\definefont + [KoreanJMO] + [hanbatanglvt*korean-composed] + +\definecolor[colorscheme:100:1][r=.75] +\definecolor[colorscheme:100:2][g=.75] +\definecolor[colorscheme:100:3][b=.75] + +\definecolor[colorscheme:101:1][g=.75,b=.75] +\definecolor[colorscheme:101:2][r=.75,b=.75] +\definecolor[colorscheme:101:3][r=.75,g=.75] +\stopbuffer + +\typebuffer[korean-demo] \getbuffer[korean-demo] + +\startbuffer + % Hunminjeongeum: http://en.wikipedia.org/wiki/Hunminjeongeum + 나랏말ᄊᆞ미中듕國귁에달아문ᄍᆞᆼ와로서르ᄉᆞᄆᆞᆺ디아니ᄒᆞᆯᄊᆡ% + 사ᄅᆞᆷ마다ᄒᆡᅇᅧ수ᄫᅵ니겨나...% ᆯ로ᄡᅮ메便뼌安ᅙᅡᆫ킈ᄒᆞ고져ᄒᆞᇙᄯᆞᄅᆞ미니라 +\stopbuffer + +\startlinecorrection +\startcombination[1*3] + {\framed{\startscript[hangul]\KoreanJMO \getbuffer\stopscript}} {no colorscheme} + {\framed{\startscript[hangul]\KoreanJMO\setfontcolorscheme[100]\getbuffer\stopscript}} {colorscheme 100} + {\framed{\startscript[hangul]\KoreanJMO\setfontcolorscheme[101]\getbuffer\stopscript}} {colorscheme 101} +\stopcombination +\stoplinecorrection + +The goodie definition looks as follows (watch how we use ranges): + +\starttyping +return { + name = "hanbatanglvt", + version = "1.00", + comment = "Goodies that complement the hanbatanglvt fonts.", + author = "Hans Hagen", + colorschemes = { + default = { + { "0x01100:0x0115F" }, -- jamo_initial (r/c) + { "0x01160:0x011A7" }, -- jamo_medial (g/m) + { "0x011A8:0x011FF" }, -- jamo_final (b/y) + } + } +} +\stoptyping + +This is much shorter (and efficent) that defining a whole vector, as in: + +\starttyping +local f_uni_base = string.formatters["uni%04X"] +local f_uni_plus = string.formatters["uni%04X.y%s"] + +local function range(first,last) + local t = { } + for i=first,last do + t[#t+1] = f_uni_base(i) + for j=0,19 do + t[#t+1] = f_uni_plus(i,j) + end + end + return t +end + +return { + name = "hanbatanglvt", + version = "1.00", + comment = "Goodies that complement the hanbatanglvt fonts.", + author = "Hans Hagen", + colorschemes = { + default = { + range(0x01100,0x0115F), -- jamo_initial (r/c) + range(0x01160,0x011A7), -- jamo_medial (g/m) + range(0x011A8,0x011FF), -- jamo_final (b/y) + } + } +} +\stoptyping + +By using names we don't depend on \UNICODE\ which sometimes is needed when glyphs +have ended up in the private space. However, by default, after glyphs have been +mapped to colors, an extra pass will make sure that characters pushed into +private space will get the same mapping as their regular \UNICODE\ has gotten +(given that the number is known). Of course explicitly assigned colors will be +preserved. + +Another generic demo feature is postprocessing. In principle one can +add additional postprocessors but for that the source code needs to +be consulted which in turn assumes some knowledge of fonts and \CONTEXT\ +internals. + +\startbuffer +\definefontfeature + [justademoa] + [default] + [goodies=demo, + postprocessor=squeeze] + +\definefontfeature + [justademob] + [default] + [goodies=demo, + postprocessor=statistics] + +\definefontfeature + [justademoc] + [default] + [goodies=demo, + postprocessor={statistics,squeeze}] +\stopbuffer + +\typebuffer \getbuffer + +The statistics just print some font parameters to the log so that one +is not showing up here. The squeeze looks as follows: + +\startbuffer +\definefont[DemoFontD][Serif*default at 30pt] +\definefont[DemoFontE][Serif*justademoa at 30pt] +\stopbuffer + +\typebuffer \getbuffer + +\startlinecorrection +\hbox\bgroup + \ruledhbox{\color[maincolor]{DemoFontD height \& depth}}\quad + \ruledhbox{\color[maincolor]{DemoFontE height \& depth}} +\egroup +\stoplinecorrection + +The squeezer just makes the height and depth of glyphs a bit smaller and it is +not that hard to imagine other manipulations. The demo goodie file is good +place to start playing with such things. + +Because there is less standardization with respect to features than one might +suspect, goodie files provide a mean to define featuresets. We can use such a set +in another definition: + +\starttyping +\definefontfeature + [demo-smallcaps] + [goodies=demo, + featureset=smallcaps] +\stoptyping + +Of course this only makes sense for more complex combinations. The already mentioned +husayni font comes with many features and most of these work together. + +The basic goodie table looks as follows: + +\startnarrowtyping +return { + name = "husayni", + version = "1.00", + comment = "Goodies that complement the Husayni font by Idris Samawi Hamid.", + author = "Idris Samawi Hamid and Hans Hagen", + featuresets = { }, + solutions = { }, + stylistics = { }, + colorschemes = { }, +} +\stopnarrowtyping + +We already saw the color schemes and now we will fill in the other tables. First +we define a couple of sets: + +\startnarrowtyping +local basics = { + analyze = "yes", + mode = "node", + language = "dflt", + script = "arab", +} + +local analysis = { + ccmp = "yes", + init = "yes", medi = "yes", fina = "yes", +} + +local regular = { + rlig = "yes", calt = "yes", salt = "yes", anum = "yes", + ss01 = "yes", ss03 = "yes", ss07 = "yes", ss10 = "yes", ss12 = "yes", + ss15 = "yes", ss16 = "yes", ss19 = "yes", ss24 = "yes", ss25 = "yes", + ss26 = "yes", ss27 = "yes", ss31 = "yes", ss34 = "yes", ss35 = "yes", + ss36 = "yes", ss37 = "yes", ss38 = "yes", ss41 = "yes", ss42 = "yes", + ss43 = "yes", js16 = "yes", +} + +local positioning = { + kern = "yes", curs = "yes", mark = "yes", mkmk = "yes", +} + +local minimal_stretching = { + js11 = "yes", js03 = "yes", +} + +local medium_stretching = { + js12="yes", js05="yes", +} +local maximal_stretching= { + js13 = "yes", js05 = "yes", js09 = "yes", +} + +local wide_all = { + js11 = "yes", js12 = "yes", js13 = "yes", js05 = "yes", js09 = "yes", +} + +local shrink = { + flts = "yes", js17 = "yes", ss05 = "yes", ss11 = "yes", ss06 = "yes", + ss09 = "yes", +} + +local default = { + basics, analysis, regular, positioning, -- xxxx = "yes", yyyy = 2, +} +\stopnarrowtyping + +Next we define some featuresets and we use the default as starting point: + +\startnarrowtyping + featuresets = { + default = { + default, + }, + minimal_stretching = { + default, js11 = "yes", js03 = "yes", + }, + medium_stretching = { + default, js12="yes", js05="yes", + }, + maximal_stretching= { + default, js13 = "yes", js05 = "yes", js09 = "yes", + }, + wide_all = { + default, js11 = "yes", js12 = "yes", js13 = "yes", js05 = "yes", + js09 = "yes", + }, + shrink = { + default, flts = "yes", js17 = "yes", ss05 = "yes", ss11 = "yes", + ss06 = "yes", ss09 = "yes", + }, + } +\stopnarrowtyping + +When defining the font at the \TEX\ end we can now refer to for instance \type +{wide_all} which saves us some typing. However, it does not stop here. In a later +paragraph we will see how fonts can work in tandem with the parbuilder. For that +purpose the goodie table has a \type {solutions} subtable: + +\startnarrowtyping +solutions = { + experimental = { + less = { + "shrink" + }, + more = { + "minimal_stretching", "medium_stretching", "maximal_stretching", "wide_all" + }, + }, +} +\stopnarrowtyping + +Here we define an experimental solution for optimizing the lines in a paragraph: +we can narrow words or we can widen them according to a specific featureset. In +order to reach the optimal solution the text will be retypeset under a different +feature regime. + +{\em TODO: show how to apply.} + +%D \starttyping +%D \setupfontsolutions[method={random,preroll},criterium=1,randomseed=101] +%D +%D \definefontsolution % actually only the last run needs to be done this way +%D [FancyHusayni] +%D [goodies=husayni, +%D solution=experimental] +%D +%D \definedfont[husayni*husayni-default at 24pt] +%D \setupinterlinespace[line=36pt] +%D \righttoleft +%D \enabletrackers[parbuilders.solutions.splitters.colors] +%D \setfontsolution[FancyHusayni] +%D alb alb alb \par +%D \resetfontsolution +%D \disabletrackers[parbuilders.solutions.splitters.colors] +%D \stoptyping + +Because there are a some 55 stylistic and 21 justification variants the +goodie file also provides a \type {stylistics} table and for tracing purposes +the {colorschemes} table is populated. + +Yet another demonstration of manipulation is the following. Not all fonts come +with all combined glyphs. Although we have an auto|-|compose feature in \CONTEXT\ +it sometimes helps to be specific with respect to some combinations. This is +where the \type {compositions} goodie kicks in: + +\starttyping +local compose = { + [0x1E02] = { + anchored = "top", + }, + [0x1E04] = { + anchored = "bottom", + }, + [0x0042] = { -- B + anchors = { + top = { + x = 300, + y = 700, + }, + bottom = { + x = 300, + y = -30, + }, + }, + }, + [0x0307] = { + anchors = { + top = { + x = -250, + y = 550, + }, + }, + }, + [0x0323] = { + anchors = { + bottom = { + x = -250, + y = -80, + }, + }, + }, +} + +return { + name = "lm-compose-test", + version = "1.00", + comment = "Goodies that demonstrate composition.", + author = "Hans and Mojca", + copyright = "ConTeXt development team", + compositions = { + ["lmroman12-regular"] = compose, + } +} +\stoptyping + +Of course this assumes some knowledge of the font metrics (in base points) and +\UNICODE\ slots, but it might be worth the trouble. After all, one only needs to +figure it out once. But keep in mind that it will always be a kludge. + +A slightly different way to define such compositions is the following: + +\starttyping +local defaultunits = 193 - 30 + +local compose = { + DY = defaultunits, + -- [0x010C] = { DY = defaultunits }, -- Ccaron + -- [0x02C7] = { DY = defaultunits }, -- textcaron +} + +-- fractions relative to delta(X_height - x_height) + +local defaultfraction = 0.85 + +local compose = { + DY = defaultfraction, -- uppercase compensation +} + +return { + name = "lucida-one", + version = "1.00", + comment = "Goodies that complement lucida.", + author = "Hans and Mojca", + copyright = "ConTeXt development team", + compositions = { + ["lbr"] = compose, + ["lbi"] = compose, + ["lbd"] = compose, + ["lbdi"] = compose, + } +} +\stoptyping + +Of course no one really needs this because \OPENTYPE\ Lucida fonts +have replaced the \TYPEONE\ versions. + +The next goodie table is dedicated to the de facto standard \TEX\ font Latin +Modern. There is a bit of history behind this file. When we started writing +\CONTEXT\ there were not that many fonts available and so we ended up with a font +system that was rather well suited for the predecessor of Latin Modern, called +Computer Modern. And because these fonts came in design sizes the font system +was made such that it could cope efficiently with many files in a font set. Although +there is no additional overhead compared to small font sets, apart from more files, +there is some burden in defining them. And, as they are the default fonts, these +definitions slow down the initialization of \CONTEXT\ (which is due to the fact that +the large typescript definitions were loaded and parsed). So, at some point +the decision was made to kick out these definitions and move the burden of figuring +out the right size to \LUA. When Latin Modern is chosen as font the effect is the +same when design sizes are enabled. But, instead of many definitions (one for each +combination of size and style) we now have an option. A non|-|designsize typeface +is defined as follows: + +\startnarrowtyping +\starttypescript [modern,modern-base] + \definetypeface [\typescriptone] [rm] [serif] [modern] [default] + \definetypeface [\typescriptone] [ss] [sans] [modern] [default] + \definetypeface [\typescriptone] [tt] [mono] [modern] [default] + \definetypeface [\typescriptone] [mm] [math] [modern] [default] + \quittypescriptscanning +\stoptypescript +\stopnarrowtyping + +The designsize variant looks like this: + +\startnarrowtyping +\starttypescript [modern-designsize] + \definetypeface [\typescriptone] + [rm] [serif] [latin-modern-designsize] [default] [designsize=auto] + \definetypeface [\typescriptone] + [ss] [sans] [latin-modern-designsize] [default] [designsize=auto] + \definetypeface [\typescriptone] + [tt] [mono] [latin-modern-designsize] [default] [designsize=auto] + \definetypeface [\typescriptone] + [mm] [math] [latin-modern-designsize] [default] [designsize=auto] + \quittypescriptscanning +\stoptypescript +\stopnarrowtyping + +Of course there are accompanying typescripts that map the sans, serif, mono +and math styles onto files. The \type {designsize} magic uses the following +table. We show only part of the file, as it is in the \CONTEXT\ distribution. + +\starttyping +return { + name = "latin modern", + version = "1.00", + comment = "Goodies that complement latin modern.", + author = "Hans Hagen", + copyright = "ConTeXt development team", + mathematics = { + tweaks = { + aftercopying = { + mathematics.tweaks.fixbadprime, -- prime is too low + }, + }, + }, + designsizes = { + ["LMMathRoman-Regular"] = { + ["4pt"] = "LMMath5-Regular@lmroman5-math", + ... + ["12pt"] = "LMMath12-Regular@lmroman12-math", + default = "LMMath10-Regular@lmroman10-math" + }, + ["LMMathRoman-Bold"] = { -- not yet ready + ... + }, + ["LMRoman-Regular"] = { + ["4pt"] = "file:lmroman5-regular", + ... + ["12pt"] = "file:lmroman12-regular", + default = "file:lmroman10-regular", + }, + ["LMRoman-Bold"] = { + ... + }, + ["LMRoman-Demi"] = { + default = "file:lmromandemi10-regular", + }, + ["LMRoman-Italic"] = { + ... + }, + ... + ["LMRoman-Unslanted"] = { + default = "file:lmromanunsl10-regular", + }, + ["LMSans-Regular"] = { + ... + }, + ["LMTypewriter-Regular"] = { + ... + }, + ... + ["LMTypewriterVarWd-DarkOblique"] = { + default = "file:lmmonoproplt10-boldoblique", + }, + ... + ["LMTypewriter-CapsOblique"] = { + default = "file:lmmonocaps10-oblique", + }, + } +} +\stoptyping + +The \type {auto} option will choose a best fit compatible to the +\MKII\ implementation. When \type {default} is used instead, the +default filename will be taken. Of course one might wonder if +there will ever be similar goodie files because design sizes +are not that popular nowadays. + +Not all fonts are perfect and of course the \LUATEX\ engine can have flaws as +well. For this reason we can implement patches. Here is another example of a +goodie file that has some more code than just a table: + +\starttyping +local patches = fonts.handlers.otf.enhancers.patches + +local function patch(data,filename,threshold) + local m = data.metadata.math + if m then + local d = m.DisplayOperatorMinHeight or 0 + if d < threshold then + patches.report("DisplayOperatorMinHeight(%s -> %s)",d,threshold) + m.DisplayOperatorMinHeight = threshold + end + end +end + +patches.register("after","analyze math","asana", + function(data,filename) patch(data,filename,1350) end) + +local function less(value,target,original) + return 0.25 * value +end + +local function more(value,target,original) + local o = original.mathparameters.DisplayOperatorMinHeight + if o < 2800 then + return 2800 * target.parameters.factor + else + return value -- already scaled + end +end + +return { + name = "asana-math", + version = "1.00", + comment = "Goodies that complement asana.", + author = "Hans Hagen", + copyright = "ConTeXt development team", + mathematics = { + parameters = { + DisplayOperatorMinHeight = more, + StackBottomDisplayStyleShiftDown = less, + StackBottomShiftDown = less, + StackDisplayStyleGapMin = less, + StackGapMin = less, + StackTopDisplayStyleShiftUp = less, + StackTopShiftUp = less, + StretchStackBottomShiftDown = less, + StretchStackGapAboveMin = less, + StretchStackGapBelowMin = less, + StretchStackTopShiftUp = less, + } + } +} +\stoptyping + +In fact, in addition to already mentioned \type {mapfiles} and +\type {virtuals} subtables, we can pass variables and +overload parameters. + +\starttyping +return { + name = "lm-math", + ... + mathematics = { + mapfiles = { + ... + }, + virtuals = { + ... + variables = { + joinrelfactor = 3, -- default anyway + }, + parameters = { -- test values + -- FactorA = 123.456, + -- FactorB = false, + -- FactorC = function(value,target,original) + -- return 7.89 * target.factor + -- end, + -- FactorD = "Hi There!", + }, + } +} +\stoptyping + +This kind of goodie functionality is typical for the development of \LUATEX\ and +experimental math fonts and no user should ever be bothered with it. However, it +demonstrates that we're not stuck with only features built in the fonts. + +% mathdimensions + +It can be that a user is not satisfied by some aspects of a math font design. +There is not much that we can do about the shapes, but we can manipulate for +instance dimensions. + +For this there are two mechanism available: automatically applied dimensional +fixes and a \type {mathdimensions} feature. Both work with the same goody +specification. + +\starttyping +mathematics = { + ... + dimensions = { + }, + ... +} +\stoptyping + +The entries in a dimensions table are tables themselves. There can be many +of them so one can organize dimensional tweaks in groups. The \type {default} +group is always applied, while others are applied on demand. Say that want +to tweak all \type {±} and \type {∓}. \footnote {In fact, this mechanism is a +a response to a mail on the \CONTEXT\ mailing list.} + +\starttyping +mathematics = { + dimensions = { + default = { + [0x00B1] = { -- ± + height = 500, + depth = 0, + }, + [0x2213] = { -- ∓ + height = 500, + depth = 0, + }, + }, + }, +} +\stoptyping + +This will give these two characters a different height and depth. However, this +will not have much effect in rendering (much larger dimensions might have). + +\starttyping +mathematics = { + dimensions = { + default = { + [0x00B1] = { -- ± + yoffset = 100, + }, + [0x2213] = { -- ∓ + yoffset = -100, + }, + }, + }, +} +\stoptyping + +This will raise and lower the glyphs in their bounding boxes and give them +an appearance more close to their ancestors. But defined this way, they are +always applied and that might not be what we want. So, we can do this: + +\starttyping +mathematics = { + dimensions = { + signs = { + [0x00B1] = { -- ± + yoffset = 100, + }, + [0x2213] = { -- ∓ + yoffset = -100, + }, + }, + }, +} +\stoptyping + +This time the application is feature driven. As with all features, setting them +up has to happen {\em before} fonts are loaded. This will do the trick: + +\starttyping +\definefontfeature [lm-math] [mathdimensions=signs] +\stoptyping + +The \type {lm-math} feature is not defined by default but can be used for such +purposes. It {\em is} defined with the fontname: + +\starttyping +\definefontsynonym + [LMMathRoman-Regular] + [file:latinmodern-math-regular.otf] + [features={math\mathsizesuffix,lm-math}, + goodies=lm] +\stoptyping + +A rather specialized goodie is the one that is used to specify math cut|-|ins. A +good quality math font has these kerns already defined but even then you might +want to add or replace some by your own. Here is an example of such a patch. +Normally there are multiple goodies defined in one file but we only show kerns +here: + +\starttyping +local kern_200 = { bottomright = { { kern = -200 } } } +local kern_100 = { bottomright = { { kern = -100 } } } + +return { + name = "pagella-math", + version = "1.00", + comment = "Goodies that complement pagella.", + author = "Hans Hagen", + copyright = "ConTeXt development team", + mathematics = { + kerns = { + [0x1D449] = kern_200, -- math italic V + [0x1D44A] = kern_100, -- math italic W + }, + }, +} +\stoptyping + +As with other goodies the file is loaded with: + +\starttyping +\definefontsynonym + [MathRoman] % names used in definitions + [file:texgyrepagella-math.otf] % the file to be loaded + [features=math\mathsizesuffix, % size dependent features + goodies=pagella-math] % the goodie file to be applied +\stoptyping + +This is typically a goodie that is always applied and not driven by a feature. +After all, the values given are passed to the engine (after being scaled). + +Most goodies are bound to fonts of collections of fonts. This is different for +treatments. These ship with the distribution but you can also provide your own. +As this is still somewhat experimental we just mention a few aspects. The entries +are filenames that point to tables. + +\starttyping +return { + name = "treatments", + version = "1.00", + comment = "Goodies that deals with some general issues.", + author = "Hans Hagen", + copyright = "ConTeXt development team", + treatments = { + ["adobeheitistd-regular.otf"] = { + embedded = false, -- not yet used + comment = "this font is part of acrobat", + }, + ["crap.ttf"] = { + ignored = true, + comment = "a text file with suffix ttf", + }, + ["latinmodern-math.otf"] = { + comment = "experimental", + }, + ["rubish-regular.ttf"] = { + comment = "check output for missing à and á", + } + }, +} +\stoptyping + +The comment entry in such a table becomes part of the message at the end +of a run: + +\startnarrowtyping +mkiv lua stats > loaded fonts: 2 files: latinmodern-math.otf (experimental), lmroman12-regular.otf +\stopnarrowtyping + +The ignored flag signals the font name database builder to ignore the file. This +means that the font can still be known as file, but that its (name based) +properties are not collected. As you asked explicitly for a file, the file can +still be loaded. You can use this trick to avoid issues with the database builder +in case of a problematic file, but a real run will still try to load the file. After +all, you get what you ask for. If loading and usage is successful you get at least +the message reported at the end of the run. + +\stopsection + +\startsection[title=Analyzers] + +An \OPENTYPE\ font is kind of special in the sense that it provides some +information on how to turn sequences of characters into sequences of glyphs. In +fact, if all fonts had a reasonable repertoire of glyphs most of the information +that concerns combining, remapping and shuffling the input and|/|or mapping onto +glyphs could as well happen in the renderer. This means that fonts have many of +their internal features tables in common, or more precisely could share many gsub +related issues, if only there had been some predefined sets of substitutional +features. + +So, for most of the time, a feature processor just does what the font demands and +the font provides the information. There are however a few cases where font only +provide part of the logic. Take for instance the \type {init}, \type {medi}, +\type {fina} and \type {isol} features that relate to positions in the word: the +start, the end, in the middle or isolated. For these features to work the engine +has to provide information about the state of a character (glyph) and this is where +analysis kicks in. Just watch this: + +\startbuffer +\definefontfeature + [default-with-analyze] + [default] + [script=latn,mode=node, + init=yes,medi=yes,fina=yes,isol=yes] + +\showotfcomposition + {dejavu-serif*default-with-analyze at 24pt} + {} + {I don't wanna know tha\utfchar{"300}t!} +\stopbuffer + +\typebuffer + +In the tracer the different categories are colored. This kind of information is +especially important for typesetting Arabic. Normally \CONTEXT\ can figure out +itself when this is needed so you don't have to worry too much about this kind of +additional actions. + +\blank \getbuffer \blank + +\stopsection + +\startsection[title=Processors] + + \startnotabene + Todo. + \stopnotabene + +\stopsection + +\startsection[title=Optimizing] + + \startnotabene + Todo. + \stopnotabene + +\stopsection + +\startsection[title=Tracing] + +There are a lot of tracing options in \MKIV, but most will never be seen by users. Most +are enabled using the tracker mechanism. Some have a bit more visibility and have a dedicated +command to trigger them. + +When something is going terribly wrong, you will always get a message but sometimes even an +end|-|user has to request for more information. An example are missing characters. There are +several ways to get them reported: + +\starttyping +\enabletrackers[fonts.missing=replace] +\enabletrackers[fonts.missing=remove] +\enabletrackers[fonts.missing] +\stoptyping + +For historic reasons we also have: + +\starttyping +\checkcharactersinfont +\removemissingcharacters +\replacemissingcharacters +\stoptyping + +which happens automatically when you enable the tracker. There is some extra +overhead involved so you might want to turn on this feature on only if you really +expect characters not to be present. + +Say that we use Latin Modern fonts and ask for some of the rare fractions: + +\startbuffer +\definedfont[lmroman10-regular*default-with-missing at 10pt] +a b c ½ ⅓ ¼ ⅕ ⅙ ⅛ Ɣ ɣ ʤ ʭ ʮ α β γ +\stopbuffer + +\typebuffer + +\enabletrackers[fonts.missing=replace] +We get this: \start \getbuffer \stop +\removeunwantedspaces . \space +In the log file you will find something like this: +\par \disabletrackers[fonts.missing] + +\starttyping +fonts > characters > start missing characters: lmroman10-regular.otf + +missing > U+00194 Ɣ LATIN CAPITAL LETTER GAMMA +missing > U+00263 ɣ LATIN SMALL LETTER GAMMA +missing > U+002A4 ʤ LATIN SMALL LETTER DEZH DIGRAPH +missing > U+002AD ʭ LATIN LETTER BIDENTAL PERCUSSIVE +missing > U+002AE ʮ LATIN SMALL LETTER TURNED H WITH FISHHOOK +missing > U+003B1 α GREEK SMALL LETTER ALPHA +missing > U+003B2 β GREEK SMALL LETTER BETA +missing > U+003B3 γ GREEK SMALL LETTER GAMMA +missing > U+02153 ⅓ VULGAR FRACTION ONE THIRD +missing > U+02155 ⅕ VULGAR FRACTION ONE FIFTH +missing > U+02159 ⅙ VULGAR FRACTION ONE SIXTH +missing > U+0215B ⅛ VULGAR FRACTION ONE EIGHTH + +fonts > characters > stop missing characters +\stoptyping + +If you're lucky your editor will use a font that shows the missing characters (dejavu +monospace is a good candidate). + +The replacement characters can help you to locate the spots where something is missing +so that an alternative can be considered. The replacements resemble the category +of the missing character. + +\showmissingcharacterslegend + +You can call up this legend after loading an extra module: + +\starttyping +\usemodule[s][fonts-missing] + +\showmissingcharacterslegend + +\showmissingcharacters +\stoptyping + +The last command shows a detailed list of missing characters + +\showmissingcharacters + +Here the characters are shown, because we use a monospaced font that happens to +have them. Of course this example uses characters that are rarely used and are +unlikely to show up in future versions of the Latin Modern fonts. + +\startnotabene + Here a few more relevant trackers will be mentioned. +\stopnotabene + +\stopsection + +\startsection[title=Some remarks] + +If you talk about features and fonts it is not difficult to end up speaking +\OPENTYPE . However, in \CONTEXT\ we use the term in a more general way, if only +because we provide more features. In traditional \TEX\ we have a few features: +ligatures, smallcaps and kerns, and to some extent we can see oldstyle numerals +also as feature. It is however important to notice that in \OPENTYPE\ ligatures +are just a synonym for combining multiple characters into on. From the user +interface point of view these operations are grouped into \type {liga}, \type +{dlig}, \type {clig} and \type {rlig} and for \TEX ies we have \type {tlig}. The +distinction is not as clear as one might think: any feature can use the ligature +builder. And as a consequence we see that happen too, for instance some fonts use +\type {ccmp} for constructing mandatory ligatures. + +Some of these interpretations (or maybe even tricks) are side effects of for +instance user interfaces. If one can for instance not turn on or off the \type +{ccmp} feature, but can do that for \type {liga}, then one way to keep some +ligatures in for instance letter spaced text, is to put them into \type {ccmp}, +assuming that this one will always be enabled. Eventually that then becomes a +sort of standard. Personally I don't like such pseudo standards but we have to +live with them. + +Another example of such a standard is the used of non breakable spaces to +influence treatment of some Devanagari characters. Where \UNICODE\ has special +characters to influence mechanisms that combine and replace characters, the lack +of some triggers others to be used and eventually that becomes a standard. +Similar ambiguities arise with math: we have no way to indicate math (while we do +have ways to indicate a change in writing order). + +Talking of math, take \OPENTYPE\ math: at some point there is a draft, that then +gets implemented in one word processor using one font, but omissions or +imperfections that surface (maybe because more fonts and engines are developed) +stay around because the initial implementation is published and frozen, simply +because there are many users that stick to expectations. Where \TEX ies accept a +few years of development, this is not true for commercial applications. \footnote +{Of course \HTML\ is the biggest example of this: we're stuck forever with open +tags without close tags, mixed uppercase and lowercase tags, attributes without +value or values without quotes.} + +So, although there is without doubt progress, some annoyances stay. The \TEX\ +community has always been able to adapt, and this is one reason why a \LUA\ +implementation is nice: it gives room for experiments, extensions, variants, etc. +Of course it also makes a bit more independent, although one may wonder if that +matters any longer in a rapidly changing world. The original idea behind \TEX, +that it should be useable for ages, will survive, but users might see more +changes in a lifetime than foreseen when \TEX\ showed up. + +\stopsection + +\stopchapter + +\stopcomponent diff --git a/doc/context/sources/general/fonts/fonts/fonts-formats.tex b/doc/context/sources/general/fonts/fonts/fonts-formats.tex new file mode 100644 index 000000000..dc98ee486 --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-formats.tex @@ -0,0 +1,873 @@ +% language=uk + +\startcomponent fonts-formats + +\environment fonts-environment + +\startchapter[title=Font formats][color=darkred] + +\startsection[title=Introduction] + +In this chapter the font formats as we know them will be introduced. The +descriptions will be rather general but more details can be found in the +appendix. Although in \MKIV\ we do support all these types eventually the focus +will be on \OPENTYPE\ fonts but it does not hurt to see where we are coming from. + +\stopsection + +\startsection[title=Glyphs] + +A typeset text is mostly a sequence of characters turned into glyphs. We talk of +characters when you input the text, but the visualization involves glyphs. When +you copy a part of the screen in an open \PDF\ document or \HTML\ page back to +your editor you end up with characters again. In case you wonder why we make this +distinction between these two states we give an example. + +\startplacefigure [location=here,reference=fig:character-glyph,title=From characters to glyphs.] + \startcombination + {\color[maincolor]{\definedfont[Serif*default at 30pt]affiliation}} {upright} + {\color[maincolor]{\definedfont[SerifItalic*default at 30pt]affiliation}} {italic} + \stopcombination +\stopplacefigure + +We see here that the shape of the \type {a} is different for an upright serif and +an italic. We also see that in \type {ffi} there is no dot on the \type {i}. The +first case is just a stylistic one but the second one, called a ligature, is +actually one shape. The 11 characters are converted into 9 glyphs. Hopefully the +final document format carries some extra information about this transformation so +that a cut and paste will work out well. In \PDF\ files this is normally the +case. In this document we will not be too picky about the distinction as in most +cases the glyph is rather related to the character as one knows it. + +So, a font contains glyphs and it also carries some information about +replacements. In addition to that there needs to be at least some information +about the dimensions of them. Actually, a typesetting engine does not have to +know anything about the actual shape at all. + +\startplacefigure [location=here,reference=fig:glyph-dimension-normal,title=The boundingbox of some normal glyphs.] + \startcombination[9*1] + {\ruledhbox{\color[maincolor]{\definedfont[Serif*default at 30pt]a}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[Serif*default at 30pt]b}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[Serif*default at 30pt]g}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[Serif*default at 30pt]l}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[Serif*default at 30pt]q}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[Serif*default at 30pt].}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[Serif*default at 30pt];}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[Serif*default at 30pt]?}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[Serif*default at 30pt]ffi}}} {} + \stopcombination +\stopplacefigure + +\startplacefigure [location=here,reference=fig:glyph-dimension-italic,title=The boundingbox of some italic glyphs.] + \startcombination[9*1] + {\ruledhbox{\color[maincolor]{\definedfont[SerifItalic*default at 30pt]a}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[SerifItalic*default at 30pt]b}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[SerifItalic*default at 30pt]g}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[SerifItalic*default at 30pt]l}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[SerifItalic*default at 30pt]q}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[SerifItalic*default at 30pt].}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[SerifItalic*default at 30pt];}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[SerifItalic*default at 30pt]?}}} {} + {\ruledhbox{\color[maincolor]{\definedfont[SerifItalic*default at 30pt]ffi}}} {} + \stopcombination +\stopplacefigure + +The rectangles around the shapes \in {figure} [fig:glyph-dimension-normal] and \in +{figure} [fig:glyph-dimension-italic] are called boundingbox. The dashed line +reflects the baseline where they eventually are aligned onto next to each other. +The amount above the baseline is called height, and below is called depth. The +piece of the shape above the baseline is the ascender and the bit below the +descender. The width of the bounding box is not by definition the width of the +glyph. In \TYPEONE\ and \OPENTYPE\ fonts each shape has a so called advance width +and that is the one that will be used. + +\usemodule[fnt-40] + +\startplacefigure [location=here,reference=fig:glyph-kerns,title={Kerning in Latin Roman, Cambria, Pagella and Dejavu.}] + \scale[width=\textwidth]{\startcombination[1*4] + {\color[maincolor]{\definedfont[name:lmroman10-regular*default sa 1]\ShowKernedHBox{Very often glyphs get very small spaces inserted horizontally.}}} {} + {\color[maincolor]{\definedfont[name:cambria*default sa 1]\ShowKernedHBox{Very often glyphs get very small spaces inserted horizontally.}}} {} + {\color[maincolor]{\definedfont[name:texgyrepagellaregular*default sa 1]\ShowKernedHBox{Very often glyphs get very small spaces inserted horizontally.}}} {} + {\color[maincolor]{\definedfont[name:dejavuserif*default sa 0.9]\ShowKernedHBox{Very often glyphs get very small spaces inserted horizontally.}}} {} + \stopcombination} +\stopplacefigure + +Another traditional property of a font is kerning. In \in {figure} +[fig:glyph-kerns] you see this in action. These examples +demonstrate that not all fonts need (or provide) the same kerns +(in points). + +So, as a start, we have now met a couple of properties of a font. +They can be summarized as follows: + +\starttabulate[|l|p|] +\NC mapping to glyphs \EQ characters are represented by a shapes that have recognizable + properties so that readers know what they mean \NC \NR +\NC ligature building \EQ a sequence of characters gets mapped onto one glyph \NC \NR +\NC dimensions \EQ each glyph has a width, height and depth \NC \NR +\NC inter-glyph kerning \EQ optionally a bit of positive or negative space has to be inserted between glyphs \NC \NR +%NC italic correction \EQ a correction is applied between an oblique shape and what follows \NC \NR +\stoptabulate + +Regular font kerning is hardly noticeable and improves the overall look of the +page. Typesetting applications sometimes are capable of inserting additional +spaces between shapes. This more excessive kerning is not that much related to +the font and is used for special purposes, like making a snippet of text stand +out. In \CONTEXT\ this kind of kerning is available but it is a font independent +feature. Keep in mind that when applying that kind of rather visible kerning +you'd better not have ligatures and fancy replacements enabled as \CONTEXT\ +already tries to deal with that as good as possible. + +\stopsection + +\startsection[title=The basic process] + +In \TEX\ a font is an abstraction: the engine only needs to know about the +mapping from characters to glyphs, what the width, height and depth is, what +sequences need to be translated into ligatures and when kerning has to be +applied. If for the moment we forget about math, these are all the properties +that matter and this is what the \TEX\ font metric files that we see in the next +section provide. + +Because one of the principles behind \LUATEX\ is that the core engine (the +binary) stays small and that new functionality is provided in \LUA\ code, the +font subsystem largely looks like it always has been. As users will normally use +a macro package most of the loading will be hidden from the user. It is however +good to give a quick overview of how for instance \PDFTEX\ deals with fonts using +traditional metric files. + +\startFLOWchart[pdftex] + \startFLOWcell + \name {source} + \location {1,1} + \shape {action} + \text {input} + \connection [rl] {parser} + \stopFLOWcell + \startFLOWcell + \name {parser} + \location {2,1} + \shape {action} + \text {characters} + \connection [rl] {builder} + \stopFLOWcell + \startFLOWcell + \name {builder} + \location {3,1} + \shape {action} + \text {glyphs} + \connection [rl] {backend} + \stopFLOWcell + \startFLOWcell + \name {backend} + \location {4,1} + \shape {action} + \text {subset} + \stopFLOWcell +\stopFLOWchart + +\startplacefigure [location=here,reference=fig:tfm-pdftex,title={Several translation steps in a traditonal \TEX\ flow.}] + \FLOWchart[pdftex] +\stopplacefigure + +The input (bytes) gets translated into characters by the input parser. Normally +this is a one|-|to|-|one translation but there are examples of some translation +taking place. You can for instance make characters active and give them a +meaning. So, the eight bit represention of an editors code page \type {ë} can +become something else internally, for instance a regular \type {e} with an \type +{¨} overlayed. It can also become another character, which in the code page +would be shown as \type {á} but the user will not know this as by then this byte +is already tokenized. Another example is multibyte translation, for instance +\UTF\ sequences can get remapped to something that is known internally as being a +character of some kind. The \LUATEX\ engine expects \UTF\ so a macro package has +to make sure that translation to this encoding happens beforehand, for instance +using a callback that intercepts the input from file. \footnote {In \CONTEXT\ we +talk of input regimes and these can be mixed, although in practice most users +will stick to \UTF\ and never use regimes.} + +So, the input character (sequence) becomes tokens representing a character. From +these tokens \TEX\ will start building a (linked) node list where each character +becomes a node. In this node there is a reference to the current font. If you +know \TEX\ you will understand that a list can have more than characters: there +can be skips, kerns, rules, references to images, boxes, etc. + +At some point \TEX\ will handle this list over to a routine that will turn them +into something that resembles a paragraph or otherwise snippet of text. In that +stage hyphenation kicks in, ligatures get built and kerning is added. Character +references become glyph indices. This list can finally be broken into lines. + +It is no secret that \TEX\ can box and unbox material and that after unboxing +some new formatting has to happen. The traditional engine has some optimizations +that demand a partial reconstruction of the original list but in \LUATEX\ we +removed this kind of optimization so there the process is somewhat simpler. We +will see more of that later. + +When \TEX\ ships out a page, the backend will load the real font data and merge +that into the final output. It will now take the glyph index and build the right +data structures and references to the real font. As a font gets subset only the +used glyphs end up in the final output. + +There is one tricky aspect involved here: re|-|encoding. In so called map files +one can map a specific metric filename onto a real font name. One can also +specify an encoding vector that tells what a given index really refers to. This +makes it possible to use fonts that have more than 256 glyphs and refer to any of +them. This is also the trick that makes it possible to use \TRUETYPE\ fonts in +\PDFTEX: the backend code filters the right glyphs from the font, remapping +\TEX's glyph indices onto real entries in the font happens via the encoding +vector. In \in {figure} [fig:tfm-bytes] we show a possible route for input byte +68. + +\startFLOWchart[bytes] + \startFLOWcell + \name {source} + \location {1,1} + \shape {action} + \text {bytes (68)} + \connection [rl] {parser} + \stopFLOWcell + \startFLOWcell + \name {parser} + \location {2,1} + \shape {action} + \text {bytes (31)} + \connection [rl] {builder} + \stopFLOWcell + \startFLOWcell + \name {builder} + \location {3,1} + \shape {action} + \text {index (31)} + \connection [rl] {backend} + \stopFLOWcell + \startFLOWcell + \name {backend} + \location {4,1} + \shape {action} + \text {index (88)} + \stopFLOWcell +\stopFLOWchart + +\startplacefigure [location=here,reference=fig:tfm-bytes,title={From bytes to indices.}] + \FLOWchart[bytes] +\stopplacefigure + +As \LUATEX\ carries much of the bagage of older engines, you can still do it this +way but in \CONTEXT\ \MKIV\ we have made our live much simpler: we use unicode as +much as possible. This means that we effectively have removed two steps (see \in +{figure} [fig:tfm-luatex]). + +\startFLOWchart[luatex] + \startFLOWcell + \name {source} + \location {1,1} + \shape {action} + \text {input} + \connection [rl] {builder} + \stopFLOWcell + \startFLOWcell + \name {builder} + \location {2,1} + \shape {action} + \text {glyphs} + \stopFLOWcell +\stopFLOWchart + +\startplacefigure [location=here,reference=fig:tfm-luatex,title={Simplified mapping in \LUATEX.}] + \FLOWchart[luatex] +\stopplacefigure + +There is of course still some work to do for the backend, like subsetting, but +the nasty dependency on the input encoding, font encoding (that itself relates to +hyphenation) and backend re|-|encoding is gone. But keep in mind that the +internal data structure of the font is still quite traditional. + +Before we move on to font formats I like to point out that there is no space in +\TEX. Spaces in the input are converted into glue, either or not with some +stretch and|/|or shrink. This also means that accessing character 32 in +traditional \TEX\ will not end up as space in the output. + +\stopsection + +\startsection[title=\TEX\ metrics] + +\appendixdata{\in[fontdata:tfm]} +\appendixdata{\in[fontdata:vf]} + +Traditional font metrics are packaged in a binary format. Due to the limitations +of that time a font has at most 256 characters. In books dedicated to \TEX\ you +will often find tables that show what glyphs are in a font, so we will not repeat +that here as after all we got rid of that limitation in \LUATEX. + +Because 256 is not that much, especially when you mix many scripts and need lots +of symbols from the same font, there are quite some encodings used in traditional +\TEX, like \type {texnansi}, \type {ec} and \type {qx}. When you use \LUATEX\ +exclusively you can do with way less font files. This is easier for users, +especially because most of those files were never used anyway. It's interesting +to notice that some of the encodings contain symbols that are never used or used +only once in a document, like the copyright or registered symbols. They are often +accessed by symbolic names and therefore easily could have been omitted and +collected in a dedicated symbol font thereby freeing slots for more useful +characters anyway. The lack of coverage is probably one of the reasons why new +encodings kept popping up. In the next table you see how many files are involved +in Latin Modern which comes in a couple of design sizes. \footnote {The original +Computer Modern fonts have \METAFONT\ source files and (runtime) generated bitmap +files in whatever resolutions are needed for previewing and printing. The +\TYPEONE\ follow|-|up came in several sets, organized by language support. The +Latin Modern fonts have a few more weights and variants than Computer Modern.} + +\starttabulate[|l|c|r|r|r|] +\HL +\NC \bf font format \NC \bf type \NC \bf \# files \NC \bf size in bytes \NC \bf \CONTEXT \NC \NR +\HL +\NC type 1 \NC tfm \NC 380 \NC 3.841.708 \NC \NC \NR +\NC \NC afm \NC 25 \NC 2.697.583 \NC \NC \NR +\NC \NC pfb \NC 92 \NC 9.193.082 \NC \NC \NR +\NC \NC enc \NC 15 \NC 37.605 \NC \NC \NR +\NC \NC map \NC 9 \NC 42.040 \NC \NC \NR +\HL[darkgray] +\NC \NC \NC 521 \NC 15.812.018 \NC mkii \NC \NR +\HL +\NC opentype \NC otf \NC 73 \NC 8.224.100 \NC mkiv \NC \NR +\HL +\stoptabulate + +A \TFM\ file can contain so called italic corrections. This is an additional kern +that can be added after a character in order to get better spacing between an +italic shape and an upright one. As this is manual work, it's a not that advanced +mechanism, but in addition to width, height, depth, kerns and ligatures it is +nevertheless a useful piece of information. But, it's a rather \TEX\ specific +quantity. + +Since \TEX\ showed up many fonts have been added. In addition support for +commercial fonts was provided. In fact, for that to happen, one only needs +accompanying metric files for \TEX\ itself and map files and encoding vectors +for the backend. Because a metric file also has some general information, like +spacing (including stretch and shrink), the ex|-|height and em|-|width, this +means that sometimes guesses must be made when the original font does not come +with such parameters. + +At some point virtual fonts were introduced. In a virtual font a \TFM\ file has +an accompanying \VF\ file. In that file each glyph has a specification that tells +where to find the real glyph. It is even possible to construct glyphs from other +glyphs. In traditional \TEX\ this only concerns the backend, which in \PDFTEX\ is +built in. In \LUATEX\ this mechanism is integrated into the frontend which means +that users can construct such virtual fonts themselves. We will see more of that +later, but for now it's enough to know that when we talk about the representation +of font (the \TFM\ table) in \LUATEX, this includes virtual functionality. + +An important limitation of \TFM\ files cq.\ traditional \TEX\ is that the number +of depths and heights is limited to 16 each. Although this results in somewhat +inaccurate dimensions in practice this gets unnoticed, if only because many +designs have some consistency in this. On the other hand, it is a limitation when +we start thinking of accents or even multiple accents which lead to many more +distinctive heights and depths. + +Concerning ligatures we can remark that there are quite some substitutions +possible although in practice only the multiple to one replacement has been used. + +Some fonts that are used in \TEX\ started out as bitmaps but rather soon +\TYPEONE\ outline fonts became the fashion. These are supported using the map +files that we will discuss later. First we look into \TYPEONE\ fonts. + +\stopsection + +\startsection[title=\TYPEONE] + +\appendixdata{\in[fontdata:afm]} +\appendixdata{\in[fontdata:enc]} +\appendixdata{\in[fontdata:map]} + +For a long time \TYPEONE\ fonts have dominated the scene. These are \POSTSCRIPT\ +fonts that can have more that 256 glyphs in the file that defines the shapes, but +only 256 of them can be used at one time. Of course there can be multiple subsets +active in one document. + +In traditional \TEX\ a \TYPEONE\ font is used by making a \TFM\ file from a so +called Adobe metric file (\AFM) that come with such a font. There are several +tool chains for doing this and \CONTEXT\ \MKII\ ships with one that can be of +help when you need to support commercial fonts. Projects like the Latin Modern +Fonts and \TEX\ Gyre have normalized a whole lot of fonts that came in several +more or less complete encodings into a consistent package of \TYPEONE\ fonts. +This already simplified live a lot but still users had to choose a suitable input +and font encoding for their language and|/|or script. As \TEX\ only cares about +metrics and not about the rendering, it doesn't consider \TYPEONE\ fonts as +something special. Also, as \TEX\ and \POSTSCRIPT\ were developed about the same +time support for \TYPEONE\ fonts is rather present in \TEX\ distributions. + +You can still follow this route but for \CONTEXT\ \MKIV\ this is no longer the +recommended way because there we have changed the whole subsystem to use +\UNICODE. As a result we no longer use \TFM\ files derived from \AFM\ files, but +directly interpret the \AFM\ data. This not only removes the 256 limitation, but +also brings more resolution in height and depth as we no longer have at most 16 +alternatives. There can also be more kerns. Of course we need some heuristics to +determine for instance the spacing but that is not different from former times. + +Because most \TEX\ users don't use commercial fonts, they will not notice that +\CONTEXT\ \MKIV\ treats \TYPEONE\ fonts this way. One reason is that the free +fonts also come as wide fonts in \OPENTYPE\ format and whenever possible +\CONTEXT\ prefers \OPENTYPE\ over \TYPEONE\ over \TFM. + +In the beginning \LUATEX\ only could load a \TFM\ file, which is why loading +\AFM\ files is implemented in \LUA. Later, when the \OPENTYPE\ loaded was added, +loading \PFB\ and \AFM\ files also became possible but it's slower and we see no +reason to rewrite the current code in \CONTEXT. We also do a couple of extra +things when loading such a file. As more \TYPEONE\ fonts move on to \OPENTYPE\ we +don't expect that much usage anyway. + +\stopsection + +\startsection[title=\OPENTYPE] + +\appendixdata{\in[fontdata:otf]} + +When an engine can deal with \UNICODE\ directly it also means that internally it +uses pretty large numbers for storing characters and glyph indices. The first +\TEX\ descendent that went wide was \OMEGA, later replaced by \ALEPH. However, this +engine never took off and still used its own extended \TFM\ format: \OFM. In fact, +as \LUATEX\ uses some of the \ALEPH\ code, it can also use these extended metric +files but I don't think that there are any useful fonts around so we can forget +about this. + +We use the term \OPENTYPE\ for a couple of font formats that share the same +principles: \OPENTYPE\ (\OTF), \TRUETYPE\ (\TTF) and \TRUETYPE\ containers +(\TTC). The \LUATEX\ font reader presents them in a similar format. In the case +of a \TRUETYPE\ container, one does not load the whole font but selects an +instance from it. Internally an \OPENTYPE\ font can have the glyphs organized in +subfonts. + +The first \TEX\ descendent to really go wide from front to back is \XETEX. This +engine can use \OPENTYPE\ fonts directly and for a whole category of users this +opened up a new world. Hoever, it is still mostly a traditional engine. The +transition from characters to glyphs is accomplished by external libraries, while +in \LUATEX\ we code in \LUA. This has the disadvantage that it is slower +(although that depends on the job) but the advantage is that we have much more +control and can extend the font handler as we like. + +An \OPENTYPE\ font is much more complex than a \TYPEONE\ one. Unless it is a +quick and dirty converted existing font, it will have more glyphs to start with. +Quite likely it will have kerns and ligatures too and of course there are +dimensions. However, there is no concept of a depth and height. These need to be +deduced from the bounding box instead. There is an advance width. This means that +we can start right away using such fonts if we map those properties onto the +\TFM\ table that \LUATEX\ expects. + +But there is more, take ligatures. In a traditional font the sequence \type {ffi} +always becomes a ligature, given that the font has such a glyph. In \LUATEX\ +there is a way to disable this mechanism, which is sometimes handy when dealing +with mono|-|spaced fonts in verbatim. It's pretty hard to disable that. For +instance one option is to insert kerns manually. In an \OPENTYPE\ font ligatures +are collected in a so called feature. There can be many such features and even +kerning is a feature. Other examples are old style numerals, fractions, +superiors, inferiors, historic ligatures and stylistic alternates. + +\starttabulate[|lT|l|l|l|l|] +\NC \type{onum} \NC \ruledhbox{\maincolor\DemoOnumLM\char45 1} + \NC \ruledhbox{\maincolor\DemoOnumLM1234567890} + \NC \ruledhbox{\maincolor\DemoOnumLM\char"A2} + \NC \ruledhbox{\maincolor\DemoOnumLM\char"24} \NC \NR +%NC \type{lnum} \NC \ruledhbox{\maincolor\DemoLnumLM\char45 1} +% \NC \ruledhbox{\maincolor\DemoLnumLM1234567890} +% \NC \ruledhbox{\maincolor\DemoLnumLM\char"A2} +% \NC \ruledhbox{\maincolor\DemoLnumLM\char"24} \NC \NR +\NC \type{tnum} \NC \ruledhbox{\maincolor\DemoTnumLM\char45 1} + \NC \ruledhbox{\maincolor\DemoTnumLM1234567890} + \NC \ruledhbox{\maincolor\DemoTnumLM\char"A2} + \NC \ruledhbox{\maincolor\DemoTnumLM\char"24} \NC \NR +\NC \type{pnum} \NC \ruledhbox{\maincolor\DemoPnumLM\char45 1} + \NC \ruledhbox{\maincolor\DemoPnumLM1234567890} + \NC \ruledhbox{\maincolor\DemoPnumLM\char"A2} + \NC \ruledhbox{\maincolor\DemoPnumLM\char"24} \NC \NR +\stoptabulate + +To this all you need to add that features operate in two dimensions: languages +and scripts. This means that when ligatures are enabled for Dutch the \type {ij} +sequence becomes a single glyph but for German it gets mapped onto two glyphs. +And, to make it even more complex, a substitution can depend on circumstances, +which means that for Dutch \type {fijn} becomes \type {f ij n} but \type {fiets} +becomes \type {fi ets}. It will be no surprise that not all \OPENTYPE\ fonts come +with a complete and rich repertoire of rules. To make things worse, there can be +rules that turn \type {1/2} into one glyph, or transfer the numbers into superior +and inferior alternatives, but leaves us with an unacceptable rendered \type +{1/a}, given that the \type {frac} features is enabled. It looks like features +like this are to be applied to a manually selected range of characters. + +The fact that an \OPENTYPE\ font can contain many features and rules to apply +them makes it possible to typeset scripts like Arabic. And this is where it gets +vague. A generic \OPENTYPE\ sub|-|engine can do clever things using these rules, +but if you read the specification for some scripts additional intelligence has to +be provided by the typesetting engine. + +While users no longer have to care about encodings, map files and back|-|end +issues, they do have to carry knowledge about the possibilities and limitations +of features. Even worse, he or she needs to be aware that fonts can have bugs. +Also, as font vendors have no tradition of providing updates this is something +that we might need to take care of ourselves by tweaking the engine. + +One of the problems with the transition from \TYPEONE\ to \OPENTYPE\ is that font +designers can take an existing design and start from that basic repertoire of +shapes. If such a design had oldstyle figures only, there is a good chance that +this will be the case in the \OPENTYPE\ variant too. However, such a default +interferes with the fact that the \type {onum} feature is one that we explicitly +have to enable. This means that writing a generic style where a font is later +plugged in becomes somewhat messy if it assumes that features need to be turned +on. + +\TEX\ users expect more control, which means that in practice just an \OPENTYPE\ +engine is not enough, but for the average font the \TEX\ model using the +traditional approach still is quite acceptable. After all, not all users use +complex scripts or need advanced features. And, in practice most readers don't +notice the difference anyway. + +\stopsection + +\startsection[title=\LUA] + +\appendixdata{\in[fontdata:lua]} + +As mentioned support for virtual fonts is built into \LUATEX\ and loading the so +called \VF\ files happens when needed. However, that concerns traditional fonts +that we already covered. In \CONTEXT\ we do use the virtual font mechanism for +creating missing glyphs out of existing ones or add fallbacks when this is not +possible. But this is not related to some kind of font format. + +In 2010 and 2011 the first public \OPENTYPE\ math fonts showed up that replace +their \TYPEONE\ originals. In \CONTEXT\ we already went forward and created +virtual \UNICODE\ fonts out of traditional fonts. Of course eventually the +defaults will change to the \OPENTYPE\ alternatives. The specification for such a +virtual font is given in \LUA\ tables and therefore you can consider \LUA\ to be +a font format as well. In \CONTEXT\ such fonts can be defined in so called +goodies files. As we use these files for much more tuning, we come back to that +in a later chapter. In a virtual font you can mix real \TYPEONE\ fonts and real +\OPENTYPE\ fonts using whatever metrics suit best. + +An extreme example is the virtual \UNICODE\ Punk font. This font is defined in +the \METAPOST\ language (derived from Don Knuths \METAFONT\ sources) where each +glyph is one graphic. Normally we get \POSTSCRIPT, but in \LUATEX\ we can also +get output in a comparable \LUA\ table. That output is converted to \PDF\ +literals that become part of the virtual font definitions and these eventually +end up in the \PDF\ page stream. So, at the \TEX\ end we have regular (virtual) +characters and all \TEX\ needs is their dimensions, but in the \PDF\ each glyph +is shown using drawing operations. Of course the now available \OPENTYPE\ variant +is more efficient, but it demonstrates the possibilities. + +\stopsection + +\startsection[title=Files] + +We summarize these formats in the following table where we explain what the file +suffixes stand for: + +\starttabulate[|Tl|p|] +\HL +\NC tfm \NC This is the traditional \TEX\ font metric file format and it reflects + the internal quantities that \TEX\ uses. The internal data structures + (in \LUATEX) are an extension of the \TFM\ format. \NC \NR +\NC vf \NC This file contains information about how to construct and where to + find virtual glyphs and is meant for the backend. With \LUATEX\ this + format gets more known. \NC \NR +\NC pk \NC This is the bitmap format used for the first generation of \TEX\ + fonts but the typesetter never deals with them. Bitmap files are more + or less obselete. \NC \NR +\HL +\NC ofm \NC This is the \OMEGA\ variant of the \type {tfm} files that caters for + larger fonts. \NC \NR +\NC ovf \NC This is the \OMEGA\ variant of the \type {vf}. \NC \NR +\HL +\NC pfb \NC In this file we find the glyph data (outlines) and some basic + information about the font, like name|-|to|-|index mappings. A + differently byte|-|encoded variant of this format is \type {pfa}.\NC + \NR +\NC afm \NC This file accompanies the \type {pfb} file and provides additional + metrics, kerns and information about ligatures. A binary variant of + this is the \PFA\ format. For \MSWINDOWS\ there is a variant that has the + \type {pfm} suffix. \NC \NR +\NC map \NC The backend will consult this file for mapping metric file names onto + real font names. \NC \NR +\NC enc \NC The backend will include (and use) this encoding vector to map + internal indices to font indices using glyph names, if needed. \NC + \NR +\HL +\NC otf \NC This binary format describes not only the font in terms of metrics, + features and properties but also contains the shapes. \NC \NR +\NC ttf \NC This is the \MICROSOFT\ variant of \OPENTYPE. \NC \NR +\NC ttc \NC This is the \MICROSOFT\ container format that combines multiple fonts + in one. \NC \NR +\HL +\NC fea \NC A (\FONTFORGE) feature definition file. Such a file can be loaded and + applied to a font. This is no longer supported in \CONTEXT\ as we have + other means to achieve the same goals. \NC \NR +\NC cid \NC A glyph index (name) to \UNICODE\ mapping file that is referenced + from an \OPENTYPE\ font and is shared between fonts. \NC \NR +\HL +\NC lfg \NC These are \CONTEXT\ specific \LUA\ font goodie files providing + additional information. \NC \NR +\HL +\stoptabulate + +If you look at how files are organized in a \TEX\ distribution, you will notice +that these files all get their own place. Therefore adding a \TYPEONE\ font to +the distribution is not that trivial if you want to avoid clashes. Also, files +are simply not found when they are not in the right spot. Just to mention a few +paths: + +\starttyping +<root>/fonts/tfm/vendor/typeface +<root>/fonts/vf/vendor/typeface +<root>/fonts/type1/vendor/typeface +<root>/fonts/truetype/vendor/typeface +<root>/fonts/opentype/vendor/typeface +<root>/fonts/fea +<root>/fonts/cid +<root>/fonts/dvips/enc +<root>/fonts/dvips/map +\stoptyping + +There can be multiple roots and the right locations are specified in a +configuration file. Currently all engines can use the \DVIPS\ encoding and map +files, so luckily we don't need to duplicate this. For some reason \TRUETYPE\ and +\OPENTYPE\ fonts have different locations and you need to be aware of the fact +that some fonts come in both formats (just to confuse users) so you might end up +with conflicts. + +In \CONTEXT\ we try to make live somewhat easier by also supporting a simple path +structure: + +\starttyping +<root>/fonts/data/vendor/typeface +\stoptyping + +This way files are kept together and installing commercial fonts is less complex +and error prone. Also, in practice we only have one set of files now: one of the +other \OPENTYPE\ formats. + +If you want to see the difference between a traditional (\PDFTEX\ or \XETEX\ plus +\CONTEXT\ \MKII) setup or a modern one (\LUATEX\ with \CONTEXT\ \MKIV) you can +install the \CONTEXT\ suite (formerly known as minimals). If you explicitly +choose for a \LUATEX\ only setup, you will notice that far less files get +installed. + +\stopsection + +\startsection[title=Text] + +This is not an in|-|depth explanation of how to define and load fonts in +\CONTEXT. First of all this is covered in other manuals, but more important is +that we assume that the reader is already familiar with the way \CONTEXT\ deals +with fonts. Therefore we limit ourselves to some remarks and expand on this a bit +in later chapters. + +The font subsystem has evolved over years and when you look at the low level code +you will probably find it complex. This is true, although in some aspects it is +not as complex as in \MKII\ where we also had to deal with encodings due to the +eight bit limitations. In fact, setting up fonts is easier due the fact that we +have less files to deal with. + +The main properties of a (modern) font subsystem for typesetting text are the +following: + +\startitemize[n] + \startitem + We need to be able to switch the look and feel efficiently and + consistently, for instance going from regular to bold or italic. So, + when we load a font family we not only load one file, but often + at least four: regular, bold, italic (oblique) and bolditalic + (boldoblique). + \stopitem + \startitem + When we change the size we also need to make sure that these related + sets are changed accordingly. You really want the bold shapes to scale + along with the regular ones. + \stopitem + \startitem + Shapes are organized in serif, sans serif, mono spaced and math and for + proper working of a typesetter that has math all over you need always + need the math. Again, when you change size, all these shapes need to + scale in sync. + \stopitem + \startitem + In one document several families can be combined so the subsystem should + make it possible to switch from one to the other without too much + overhead. + \stopitem + \startitem + Because section heads and other structural elements have their own sizes + there has to be a consistent way to deal with that. It should also be + possible to specify exceptions for them. + \stopitem +\stopitemize + +In the next chapters we will cover some details, for instance font features. You +can actually control these when setting up a body font, simply by redefining +the \type {default} feature set, but not all features are dealt with this way. +So let's continue the demands put on a font subsystem. + +\startitemize[continue] + \startitem + Sometimes inter|-|character kerning is needed. In \CONTEXT\ this is not a + property of a font because glyphs can be mixed with basically anything. + This kind of features is applied independent of a font. + \stopitem + \startitem + The same is true for casing (like uppercasing and such) which is not + related to a font but applied to a selected (or marked) piece of the + input stream. + \stopitem + \startitem + Using so called \quotation {small caps} or \quotation {old style} + numerals or \unknown\ can be dealt with by setting the default features + but often these are applied selectively. As these are applied using the + information in a font they do belong to the font subsystem but in + practice they can be seen as independent (assuming that the font supports + them at all). + \stopitem + \startitem + Protrusion (into margins) and expansion (to improve whitespace) are + applied to the font at load time because the engine needs to know about + them. But they two can selectively be turned on and off. They are more + related to line break handling than font defining. + \stopitem + \startitem + Slanting (to fake oblique) and expanding (to fake bold) are regular + features but are applied to the font because the engine needs to know + about them. They permanently influence the shape. + \stopitem +\stopitemize + +We will discuss these in this manual too. What we will not discuss in depth is +spacing, even when it depends on the (main body) font size. These use properties +of fonts (like the ex|-|height or em|-|width and maybe the width of the space, +but normally they are controlled by the spacing subsystem. We will however +mention some rather specific possibilities: + +\startitemize[continue] + \startitem + The \CONTEXT\ font subsystem provides ways to combine multiple fonts + into one. + \stopitem + \startitem + You can construct artificial fonts, using existing fonts or \METAPOST\ + graphics. + \stopitem + \startitem + Fonts can be fixed (dimensions) and completed (for instance accented + characters) when loading/ + \stopitem + \startitem + There are extensive tracing options, not only for applied features but + also for loading, checking etc. There is a set of styles that can be + used to study fonts. + \stopitem +\stopitemize + +Sometimes users ask for very special trickery and it no surprise then that some +of that is now widely know (or even discussed in detail). When we get notice of +that we can mention it in this manual. + +So how does this all relate to font formats? We mentioned that when loading we +basically load some four files per family (and more if we use specific fonts for +titling). These files just provide the data: metric information, shapes and ways +to remap characters (or sequences) into glyphs, either of not positioned relative +to each other. In traditional \TEX\ only dimensions, kerns and ligatures +mattered, but in nowadays we also deal with specific \OPENTYPE\ features. But +still, as you can deduce from the above, this is only part of the story. You need +a complete and properly integrated system. It is no big deal to set up some +environment that uses font files to achieve some typesetting goal, but to provide +users with some consistent and extensible system is a bit more work. + +There are basically three font formats: good old bitmaps, \TYPEONE\ and +\OPENTYPE. All need to be supported and expectations are that we also support +their features. But is should be noticed that whatever font you use, the quality +of the outcome depends on what information the font can provide. We can improve +processing but are often stuck with the font. There are many thousands of +fonts out there and we need to be able to use them all. + +\stopsection + +\startsection[title=Math] + +In the previous section we already mentioned math fonts. The fonts are just one +aspect of typesetting math and math fonts are special in the sense that they have +to provide the relevant information. For instance a parenthesis comes in several +sizes and at some point turns in a symbol made out of pieces (like a top curve, +middle lines and bottom curve) that overlap. The user never sees such details. In +fact, there are ot that many math fonts and these are already set up so there is +not much to mess up here. Nevertheless we mention: + +\startitemize [n] + \startitem + Math fonts are loaded in three sizes: text, script and scriptscript. The + optimal relative sizes ar defined in the font. + \stopitem + \startitem + There are direction aware math fonts and we support this in \CONTEXT. + \stopitem + \startitem + Bold math is in fact a bolder version of a regular math font (that can + have bold symbols too). Again this is supported. + \stopitem +\stopitemize + +The way math is dealt with in \CONTEXT\ is different from the way it is done +traditionally. Already when we started with \MKIV\ we moved to \UNICODE\ and +the setup at the font level is kept simple by delegating some of the work to +the \LUA\ end. We will see some of the mentioned aspects in more detail later. + +Because of it's complexity and because in a math text there can be many times +activation of math fonts (and related settings) quite some effort has been put in +making it efficient. But you need to keep in mind that when we discuss math +related topics later on, this is hardly of concern. Math fonts are loaded only +once so manipulating them a bit has no penalty. And using them later on is hardly +related to the font subsystem. + +Concerning formats we can notice that traditional \TEX\ comes with math fonts +that have properties that the engine can use. Because there were not many math +fonts, this was no problem. The \OPENTYPE\ math fonts however are also used in +other applications and therefore are a bit more generic. \footnote {Their +internals are now defined in the \OPENTYPE\ specification.} For this we not only +had to adapt the math engine in \LUATEX\ (although we kept that to the minimum) +but we also had to think different about loading them. In later chapters we will +see that in the transition to \UNICODE\ math fonts we implemented a mechanism for +combining \TYPEONE\ fonts into virtual \UNICODE\ fonts. We did that because it +made no sense to keep an old and new loader alongside. + +There will not be thousands of math fonts flying around. A few dozen is already a +lot and the developers of macro packages can set them up for the users. So, in +practice there is not much that a user needs to know about math font formats. + +\stopsection + +\startsection[title=Caching] + +Because fonts can be large and because we use \LUA\ tables to describe them +a bit of effort has been put into managing them efficiently. Once converted +to the representation that we need they get cached. You can peek into the cache +which is someplace on your system (depending on the setup): + +\starttabulate[|l|p|] +\NC \type{fonts/afm} \NC type one fonts, converted from \type {afm} and \type + {pfb} files \NC \NR +\NC \type{fonts/data} \NC font name databases \NC \NR +\NC \type{fonts/mp} \NC fonts created using \METAPOST \NC \NR +\NC \type{fonts/otf} \NC open type fonts, converted from \type {ttf}, \type {otf}, + \type {ttc} and \type {ttx} files loaded using the + \FONTFORGE\ loader \NC \NR +\NC \type{fonts/otl} \NC open type fonts, converted from \type {ttf}, \type {otf}, + \type {ttc} and \type {ttx} files loaded using the + \CONTEXT\ \LUA\ loader \NC \NR +\NC \type{fonts/shapes} \NC outlines of fonts (for instance for use in \METAFUN) \NC \NR +\stoptabulate + +There can be three types of files there. The \type{tma} files are just \LUA\ +tables and they can be large. These files can be compiled to bytecode where \type +{tmc} is for stock \LUATEX\ and \type {tmb} for \LUAJITTEX. The \type {tma} files +are optimized for space and memory (aka: packed) but you can expand them with +\type {mtxrun --script font}. + +Fonts in the cache are automatically updated when you install new versions of a +font or when the \CONTEXT\ font loader has been updated. + +\stopsection + +\stopchapter + +\stopcomponent diff --git a/doc/context/sources/general/fonts/fonts/fonts-hooks.tex b/doc/context/sources/general/fonts/fonts/fonts-hooks.tex new file mode 100644 index 000000000..9be69d6b8 --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-hooks.tex @@ -0,0 +1,585 @@ +% language=uk + +\startcomponent fonts-hooks + +\environment fonts-environment + +\startchapter[title=Hooks][color=darkcyan] + +\startsection[title=Introduction] + +One of the virtues of \TEX\ is its flexibility. Because we cannot predict what +users want to mess around with, much of the underlying code has hooks. And because +it's not too hard to add functionality that will break things we will not advocate +all of it. Of course you can study the code and figure out what can be done and +there is no problem with that. It's just that you shouldn't expect much support. + +In this chapter we collect some of these hooks. If you run into interesting ones +that are worth mentioning, you can always ask us to add description here. + +\stopsection + +\startsection[title=Safe hooks] + +\startsubsection[title=Trimming fonts] + +Because we store font related information in \LUA\ tables there can be situations +where the resources used outgrow memory. An example of such a font is \type +{lastresort} that basically defined the whole \UNICODE\ range. The font is +actually not that large as it uses similar placeholders for glyphs in a range, +but it has rather verbose (redundant) names. As we normally don't need these, you +can decide to strip them away. + +\starttyping +\startluacode + fonts.handlers.otf.readers.registerextender { + name = "remove names from lastresort", + action = function(fontdata) + if fontdata.metadata.fullname == "LastResort" then + for k, v in next, fontdata.descriptions do + v.name = nil + end + end + end + } +\stopluacode + +\definedfont[LastResort][lastresort*default sa 1] +\stoptyping + +This will result in a much smaller font, one that has less change to crash the +engine due to lack of memory. Extenders like this are applied once the font has +been loaded but before it gets saved. + +\stopsubsection + +\stopsection + +\startsection[title=Loading] + +\startsubsection[title=Introduction] + +We basically have to deal with three font formats that can easily be recognized +by the suffix of the files involved: \type {tfm} and \type {vf} files that +describe 8 bit fonts, traditionally bitmap fonts, but as they carry only metric +information, any 8 bit font can be described. Then there are \type {afm} files +that contain metrics related to \TYPEONE\ fonts (stored in \type {pfb} files). +Although such fonts could contain more than 256 shapes, the implementation was +limited to 8 bits too. By converting \type {afm} files to \type {tfm} files, +traditional \TEX\ can deal with \TYPEONE\ given that the backend can include them +in the final result. + +In this section we will discuss some aspects of the \OPENTYPE\ font reader. As +\TEX\ only deals with metrics (in the frontend) we need to parse them, filter +information from it and pass the metrics to \TEX. In addition, we can use all +kind of extra information to manipulate the so called node list but in the end +\TEX\ is only interested in font id's (that point to a font resource) and glyph +indexes. + +To overcome the 256 limitation of \TYPEONE\ fonts, in \CONTEXT\ we moved away +from \type {tfm} files (we can of course still deal with them) and turn \type +{afm} files into so called wide fonts. Basically we turn them in a more rich +format that looks similar to the internal \OPENTYPE\ format we use. We will not +go into much detail about that because \TYPEONE\ is kind of obsolete and being +replaced by \OPENTYPE, but we will of course support the old formats simply +because we have all these fonts around. + +Already early in the development of \LUATEX\ a font loader library was created +that can turn an \OPENTYPE\ (but also a \TYPEONE) font into a \LUA\ table. This +library is derived from \FONTFORGE\ which makes it possible to look into a font +using that editor and at the same time get a similar view on the font in \LUA, +which is quite handy. However, at some point in \CONTEXT\ we wanted to play with +outlines in \METAPOST\ and for that purpose an \OPENTYPE\ reader was written in +\LUA\ that could extract the data. Because \TYPEONE\ fonts already were done in +\LUA\ it was a logical step to also do \OPENTYPE\ in \LUA\ so now we use an +alternative loader that doesn't depend in the \FONTFORGE\ library. This not only +gives more flexibility but also makes it possible to avoid some conversions +needed to provide the \CONTEXT\ font handler with the needed information in an +efficient way. + +\stopsubsection + +\startsubsection[title=Loading \OPENTYPE\ fonts] + +As with most binary media formats today an \OPENTYPE\ font file is a linked list +of records. The top level structure is called table. There are two flavours of +\OPENTYPE\ where the main difference is in the way the shapes are defined: they +can be \TRUETYPE\ outlines using quadratric bezier curves or cff files using +cubic bezier curves. The last variant is the same as \POSTSCRIPT\ \TYPEONE\ +fonts. Simplified, a quadratic curve defines the shape in points with a control +point in between, while a quadratic one also has points but each with two control +points (as in \METAPOST). + +An \OPENTYPE\ font can be large: there can be upto 65536 glyphs and lots of extra +properties and features. In order to save space the data is rather packed using +different numeric data types. Of course one can wonder if size really matters now +that most bandwidth is taken by audio, video and pictures but we have to live +with it. + +The definition of \OPENTYPE\ can be found on the \MICROSOFT\ website: +\hyphenatedurl {https://www.microsoft.com/typography/otspec}. Most tables then +could make sense for us are mentioned in the following list: + +\starttabulate[|Bl|l|l|] +\NC required \NC cmap \NC character to glyph mapping \NC \NR +\NC \NC head \NC font header \NC \NR +\NC \NC hhea \NC horizontal header \NC \NR +\NC \NC hmtx \NC horizontal metrics \NC \NR +\NC \NC maxp \NC maximum profile \NC \NR +\NC \NC name \NC naming table \NC \NR +\NC \NC os/2 \NC os/2 and windows specific metrics \NC \NR +\NC \NC post \NC postScript information \NC \NR +\NC truetype \NC glyf \NC glyph data \NC \NR +\NC \NC loca \NC index to location \NC \NR +\NC postscript \NC cff \NC compact font format \NC \NR +\NC \NC vorg \NC vertical origin \NC \NR +\NC typographic \NC base \NC baseline data \NC \NR +\NC \NC gdef \NC glyph definition data \NC \NR +\NC \NC gpos \NC glyph positioning data \NC \NR +\NC \NC gsub \NC glyph substitution data \NC \NR +\NC \NC jstf \NC justification data \NC \NR +\NC \NC math \NC math layout data \NC \NR +\NC extras \NC kern \NC kerning \NC \NR +\NC \NC ltsh \NC linear threshold data \NC \NR +\NC \NC vhea \NC vertical metrics header \NC \NR +\NC \NC vmtx \NC vertical metrics \NC \NR +\NC \NC colr \NC color table \NC \NR +\NC \NC cpal \NC color palette table \NC \NR +\stoptabulate + +When we read these tables it depends on what we want to do with the result how +much we will really read. For instance when we only want to identify a font and +get some basic information we don't need to read all tables and certainly don't +need to read them completely. If we want to have the outlines we need to read the +\type {glyf} or \type {cff} table. If we also want to boundingbox of \POSTSCRIPT\ +shapes we even need to process the shapes so that we know the dimensions of the +result. There is no need to summarize the format here in detail because you can +find it on the \MICROSOFT\ site. Here I only cover some aspects that influence +the way \TEX\ can use the fonts. + +One of the main differences between the readers is that the \FONTFORGE\ reader +has a lot of (recovery) heuristics for bad fonts. Nowadays most fonts are quite +okay, and in \CONTEXT\ we prefer to just reject bad ones. In the process of +loading the built|-|in loader gives each glyph a name (it makes them up for +variants needed for features). It also tries to figure out some font properties, +like the weight. If does a pretty good job on that but it is also hard to repair +at the \LUA\ end when it makes a bad guess. The \LUA\ variants stays closer to +the specification, but delegates more to the final user, which is good because we +need and want that level of control as controls is what \TEX\ is about. It also +made it possible to support for instance colored fonts without too much effort. + +So what data needs to be collected? If we look at what we get eventually the list +of glyphs is the bulk. For each glyph we collect some metric information. For +instance we fetch the (advance) width of the glyph but also the boundingbox, +which gives us the the height and depth. + +In the font file the list of glyphs starts at zero and runs up tot the total +number of glyphs. The index in this table is used in for instance the tables that +define the font features, for instance kerning between glyphs, or multiple glyphs +that are turned into ligatures. Each glyph gets a name. That can be a meaningful +one but also a rather dumb one, for instance the index number. + +Eventually (at least in \CONTEXT) we don't order by glyph index but by \UNICODE. +The font file contains information about the mapping from index to \UNICODE. In +principle other encodings are possible but we stick to \UNICODE. But, because +many glyphs can refer to one \UNICODE\ slot, for instance a regular shape as well +as a smallcaps or oldstyle variant. These extra glyphs we let end up in the +private \UNICODE\ areas. This also means that with each glyph in the final table +there is also a field that has the \UNICODE. Because we order by \UNICODE\ we +also need to store the index. An example from a Latin Modern font is: + +\starttyping +[97] = { + boundingbox = { 34, -10, 474, 446 }, + index = 28, + name = "a", + unicode = 97, + width = 490, +} +\stoptyping + +Another example is the following. Here we end up in private space: + +\starttyping +[983059] = { + boundingbox = { 30, -10, 734, 446 }, + index = 19, + name = "oe.dup", + unicode = 339, + width = 762, +} +\stoptyping + +Yet another entry is: + +\starttyping +[306] = { + boundingbox = { 28, -22, 790, 683 }, + index = 357, + name = "I_J", + unicode = { 73, 74 }, + width = 839, + }, +\stoptyping + +Here you see two \UNICODE\ numbers. That kind of information is deduced from the +name of the glyph, using knowledge on how such names are supposed to be +constructed, or, when that is not possible, from ligature information in the +fonts. + +It makes no sense to discuss the whole font table in detail, if only because most users +will never (need to) see it. But if your curious you can have a look at the fonts +in the cache tree, in the \CONTEXT\ distribution from the \CONTEXT\ garden this is + +\starttyping +.../tex/texmf-cache/luatex-cache/context/<somehash>/fonts/otl +\stoptyping + +There can be three kind of files there, with suffixes \type {tma}, \type {tmc} +and \type {tmb}. The first one is the table as converted from the binary font +file. The second and third variants are just bytecode compilations of this file +(for \LUATEX\ and|/|or \LUAJITTEX). The bytecode variants are smaller but more +important, they load a bit faster. On my disk the largest \type{tma} file is just +below 10 MByte (an extensive \CJK\ font) but normally they are in the few hundred +KByte range (some are real small), with the bytecode files of course being +relatively small to their original. + +However, there is a bit of cheating here. If we run the command: + +\starttyping +mtxrun --script font --convert lmroman10-regular.otf +\stoptyping + +A \LUA\ file is generated: \type {lmroman10-regular.lua}. This file is much larger +than the \type {tma} file in the cache: + +\starttabulate[|T|T|] +\NC 643.924 \NC lmroman10-regular.lua \NC 0.029 \NR +\NC 209.950 \NC lmroman10-regular.tma \NC 0.010 \NR +\NC 121.541 \NC lmroman10-regular.tmb \NC \NR +\NC 134.564 \NC lmroman10-regular.tmc \NC 0.003 \NR +\stoptabulate + +The reason for this is the following. Most information is stored in tables. +Especially tables that describe font features can be the same all over the place. +This is why we pack the table in a more compact format before saving it in the +cache, and unpack it after loading. The effects on loading are neglectable but +and it has the benefit that it saves a lot of memory. By looking at such numbers +one should be careful with conclusions, but (assuming proper garbage collection) +we see a memory footprint of the \type {lua} file of 2836 Kbyte, while the +unpacked variant takes 704 Kbyte. You can imagine what happens with large \CJK\ +fonts. Loading the (larger unpacked) \type {lua} file currently costs me 0.029 +seconds, while loading and unpacking the \type {tma} file takes 0.010 seconds and +the bytecode variant \type {tmc} 0.003 seconds. + +\stopsubsection + +\startsubsection[title=Loading \TYPEONE\ fonts] + +When we started with \CONTEXT\ \MKIV\ (which is shortly after we started with +\LUATEX) the only \TFM\ files that were loaded, were those to make virtual +\UNICODE\ math fonts, awaiting real \OPENTYPE\ math fonts. Math fonts are kind +of special with respect to metrics and such. + +For \TYPEONE\ text fonts we didn't use the \TFM\ files but went for parsing \AFM\ +files. That way we could use all the glyphs provided by fonts and not be limited +to 256 slots. So, effectively we made them \UNICODE\ and similar to \OPENTYPE. Of +course the only features were ligatures, kerns and some special ones like \TEX\ +ligatures and replacements. With the old loader code, we always made them base +mode fonts, which means that processing was delegated to \TEX. In the new loader +we implement ligatures and kerns as node mode features, which means that we can +use those fonts in base mode as well as node mode. The last options therefore +permits to add or adapt features to \TYPEONE\ fonts as well. + +In the next sections we will focus on \OPENTYPE\ but as the \TYPEONE\ fonts are +organized in a similar way, some of it also applies to this older type. The most +important to keep in mind is that we only have \type {liga}, \type {kern} and a +few \CONTEXT\ specific features. + +\stopsubsection + +\stopsection + +\startsection[title=The tables] + +\startsubsection[title=Structure] + +Getting a font read for \TEX\ happens in stages. The original \OPENTYPE\ file is +read only once. At that moment the shapes are described in the \type +{descriptions} subtable while by the time that we pass the information to \TEX\ +they are in \type {characters}. The reason is that we go from dimensions in font +units to dimensions in scaled points. We start with the following table: + +\ctxlua{context.tocontext(fonts.tables.data.original,"original_table")} + +The table passed \TEX\ is constructed from this one and looks like: + +\ctxlua{context.tocontext(fonts.tables.data.scaled,"scaled_table")} + +There might be a few more (often obscure) fields for special purposes. The +characters subtable conforms to what \TEX\ expects, while the descriptions stays +closer to \OPENTYPE. The \type {kerns} and \type {ligatures} subtables are there +for base mode and are not present in \type {node} mode. The \type {commands} and +\type {fonts} subtables relate to virtual fonts. + +\startitemize[packed] +\startitem + Start with the (already) loaded \OPENTYPE\ table. +\stopitem +\startitem + Copy relevant information from \type {descriptions} to \type {characters} etc. +\stopitem +\startitem + Construct \type {properties} and \type {parameters} tables. +\stopitem +\startitem + Apply additional manipulators, for instance extend the \type {characters} + table, with expansion and protrusion. +\stopitem +\startitem + Scale the \type {characters}, \type {properties} and \type {parameters}. +\stopitem +\startitem + Apply additional manipulators. +\stopitem +\startitem + Pass the table to \TEX, but keep it around for later access. +\stopitem +\stopitemize + +One of the things you need to be aware of is that all references to glyphs are +\UNICODE\ slots, either natural ones (representing a character) or a private one +(representing an alternative representation). In \OPENTYPE\ features are defined +in terms of glyph indices but we prefer \UNICODE\ because that is easier to deal +with when we run over the node list. Before font processing the character field +in a glyph node is a \UNICODE\ slot and afterwards it's still a \UNICODE\ but +when it's a private one it can always be resolved to a non private slot of +sequence of slots. Of course that could also be done with indices but it's just +more natural this way. + +Another thing to note is that in the descriptions we're still working with font +units ranging from $-1000$ to $+1000$, $-2048$ to $+2048$ or similar ranges. At +the \TEX\ end we need scaled points which are much larger numbers. + +The question is: how often do users need to access the raw data in a font? After +a decade of \MKIV\ and \LUATEX\ hardly any user has requested such access, +probably because when needed easier interfaces were provided. Also, in the +\CONTEXT\ distrubution there are some examples of manipulations that can be +copied and adapted to personal use. There's also a danger is messing with the +fonts (similar messing with the node lists): you never know how it interferes +with other (maybe future) features. + +If you still want to do it, best is probably to start with saving the +to|-|be|-|passed|-|to|-|\TEX\ table in a file and have a look at it. The most +prominent subtable is the \type {characters} table and messing a bit with +dimensions is rather harmless. You could add characters, for instance virtual +ones, which again is harmless unless you use invalid commands. You probably want +to stay away from the resources subtable, if only because some of its subtables +are shared and therefore adapting them can have side effects. The top level \type +{shared} and \type {unscaled} subtable are off limits as is the \type +{specification}. + +You can save a font by consulting one of the hashes but for a specific font +you need to know its id. You can do this by using low level accessors but better +is to use the helpers made for this, because they prevent saving redundant +data. + +% \starttyping +% \startluacode +% local nullfont = fonts.hashes.identifiers[false] +% local currentfont = fonts.hashes.identifiers[true] +% +% local id, tfmdata = fonts.definers.define { +% name = "dejavusansmono*default", +% size = tex.sp("6pt") +% } +% +% table.save("temp-nullfont.lua", nullfont) +% table.save("temp-currentfont.lua",currentfont) +% table.save("temp-definedfont.lua",tfmdata) +% table.save("temp-definedfont.lua",fonts.hashes.identifiers[id]) +% \stopluacode +% \stoptyping + +\starttyping +\startluacode +fonts.tables.save { + filename = "temp-font-scaled.lua", + fontname = "dejavusansmono*default", + method = "original", +} +\stopluacode +\stoptyping + +At the \TEX\ end you can use: + +\starttyping +\savefont + [name=dejavusansmono*default, + file=temp-o.lua, + method=original] +\savefont + [name=dejavusansmono*default, + file=temp-s.lua, + method=scaled] +\stoptyping + +When no \type {name} is given, the current font is used and when no \type {file} +is given a filename is made up. The default \type {method} is \type {scaled}. The +saved name is reported. + +\stopsubsection + +\startsubsection[title=Plug-ins] + +There are several places where you can hook in code: before scaling +(initalizers), after scaling (manipulators) and while processing (processors). +Only the first two are meant for tweaks. + +\starttyping +local do_something = { + name = "something", + description = "doing something", + initializers = { + -- position = 1, + base = function(tfmdata,value,features) ... end, + node = function(tfmdata,value,features) ... end, + }, + manipulators = { + -- position = 1, + base = function(tfmdata,feature,value) ... end, + node = function(tfmdata,feature,value) ... end, + }, + processors = { + -- position = 1, + base = function(tfmdata,font,attr) ... end, + node = function(tfmdata,font,attr) ... end, + } +} + +fonts.constructors.features.register.otf(so_something) +fonts.constructors.features.register.afm(so_something) +\stoptyping + +A \type {initializer} is applied just before the font gets scaled. This means +that the characterm properties and parameters are unscaled! Initializers can for +instance be used to add extra features to fonts. You can provide an \type +{position} key with a number to force a place in the list of initializers but of +course you can never be sure of interference. + +A \type {manipulator} is applied when the font is scaled but before it gets +passed to \TEX. It's a good place to tweak dimensions. Here you can also probide +a \type {position}. + +The processors are applied when the node list gets processed, hence the \type +{font} and optional \type {attr} arguments. The action is only applied to the +specified font (id) and when an attribute gets passed, this is tested for a +value. When an attribute is used, an unset attribute on the node will skip the +action. + +If adapting characters and their properties is your main objetive, then there is a +better plugin mechanism using sequencers. We illustrate this with a fake example: + +\starttyping +\startluacode + +function document.b_copying(tfmdata) + logs.report("fonts","before copying: %s",tfmdata.properties.filename) +end +function document.a_copying(tfmdata) + logs.report("fonts","after copying: %s",tfmdata.properties.filename) +end + +function document.b_math(tfmdata) + logs.report("fonts","before math: %s",tfmdata.properties.filename) +end +function document.a_math(tfmdata) + logs.report("fonts","after math: %s",tfmdata.properties.filename) +end + +utilities.sequencers.appendaction( + "beforecopyingcharacters", + "before", + "document.a_copying" +) + +utilities.sequencers.appendaction( + "aftercopyingcharacters", + "after", + "document.b_copying" +) + +utilities.sequencers.appendaction( + "mathparameters", + "before", + "document.b_math" +) + +utilities.sequencers.appendaction( + "mathparameters", + "after", + "document.a_math" +) +\stopluacode +\stoptyping + +When we call the next command: + +\starttyping +\definedfont[MathRoman at 3pt] +\stoptyping + +we get this reported: + +\starttyping +fonts > before math: ...../public/dejavu/texgyredejavu-math.otf +fonts > after math: ...../public/dejavu/texgyredejavu-math.otf +fonts > after copying: ...../public/dejavu/texgyredejavu-math.otf +fonts > before copying: ...../public/dejavu/texgyredejavu-math.otf +\stoptyping + +In between \type {before} and \type {after} we have \type {system} which is +reserved for \CONTEXT\ actions. These actions are executed in the scaler +function. The function get two tables passed: the original data as well as the +target. If you ever need these hooks, you can probably best run an \type +{inspect} on these arguments to see what you're dealing with. + +Fonts get reused when possible and for that a hash is calculated depending on the +enabled features and size. If for some reason you want to adapt that hash you can +use postprocessors. When the \type {tfmdata} table has a subtable \type +{postprocessors}, then the actions in that subtable will be applied. When an +action returns a string, the string will be combined with the hash. You can set +(o rextend) the postprocessors table using the previopusly mentioned commands. +However, in \CONTEXT\ you can best stay away from this as it might interfere. This +mechanism is mostly provided for generic use. + +\stopsubsection + +\stopsection + +\startsection[title=Goodies] + +The font goodies are already discussed as an official mechanism to extend or enhance +fonts with additional features. There are quite some goodies defined and for sure more will +show up. Here is the full repertoire: + +\ctxlua{context.tocontext(fonts.tables.data.goodies,"goodie_table")} + +Of course you will never use all the options at the same time. The best place to +look for examples are the \type {lfg} files in the \CONTEXT\ distribution. +\footnote {At some point we might decide to also support goodies in the generic +version.} + +\stopsection + +% - features +% - subfonts +% - outlines +% - math +% - hashes + +\stopsection + +\stopchapter + +\stopcomponent diff --git a/doc/context/sources/general/fonts/fonts/fonts-introduction.tex b/doc/context/sources/general/fonts/fonts/fonts-introduction.tex new file mode 100644 index 000000000..0ca91ee9f --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-introduction.tex @@ -0,0 +1,95 @@ +% language=uk + +\startcomponent fonts-introduction + +\environment fonts-environment + +\startchapter[title=Introduction][color=darkgray] + +You sit in a cave and wonder how to keep track of your winter stock. While +playing with some burned wood you end up with vertical strokes on the wall +representing how much you have in store. + +You walk through the woods and wonder how to find your way back. Suddenly it +strikes you that you can put markers on trees. Years from that moment the whole +forest is marked with routes. Different symbols carry different meanings. + +The next thing you want to do is to carry around information and pass it onto +following generations. So, you turn those symbols into shapes that make up the +scripts that can be used to express your languages in. + +For ages scripts have evolved and the rendering of them on stone or wood and +later paper has resulted in a multitude of coherent collections of so called +glyphs. Manual labour turned into (semi) automated mass production and once that +took off, developments went fast. But the quality was still somewhat dubious, +especially when for instance specialized scripts like math had to be dealt with. + +Some 30 years ago Don Knuth wrote a book, and in the process invented the \TEX\ +typesetting system, the graphical language \METAFONT\ and a bunch of fonts. He +made it open and free of charge. He was well aware that the new ideas were built +on older ones that had evolved from common sense: how to keep track of things on +paper. + +It is no surprise that an active community formed around these goodies. First of +all the system has no strings attached: the licence is generous and there are no +patents involved. There is also a network of user groups that takes care of +coordinated updates to the whole machinery. Of course it helps that it all +relates to Don Knuth. + +Since \TEX\ showed up several open and closed source typesetting systems have +surfaced and only some of them survived. Also regular word processing has become +more clever and still become better. The \TEX\ typesetting system also moved on. +Some of its ideas have been used in other programs and some of the ideas of other +programs made their way into \TEX. However, its main property is still there: you +can tweak and tune it to your needs and are not hampered by too many limitations. + +Don Knuth had this chicken or egg problem: once you can typeset a source you need +fonts but you can only make fonts if you can use them in a typesetting program. +As a result \TEX\ came with its own fonts and it has special ways to deal with +them. Given the limitations of that time \TEX\ puts some limitations on fonts and +also expects them to have certain properties, something that is most noticeable +in math fonts. + +Rather soon from the start it has been possible to use third party fonts in \TEX, +for instance \TYPEONE. As \TEX\ only needs some information about the shapes, it +was the backend that integrated the font resources in the final document. One of +its descendants, \PDFTEX, had this backend built in and could do some more clever +things with fonts in the typesetting process, like protrusion and expansion. The +integration of front- and backend made live much easier. Another descendant, +\XETEX\ made it possible to move on to the often large \OPENTYPE\ fonts. On the +one hand this made live even more easy but at the other end it introduced users +to the characteristics of such fonts and making the right choices, i.e.\ not fall +in the trap of too fancy font usage. + +In this manual we will look at fonts from the perspective of yet another +descendant, \LUATEX. It inherits the font technology from traditional \TEX, but +also extends it so that we can deal with modern font technologies. Of course it +offers much more, but in practice much relates to fonts one way or the other. + +Of course this exploration will be from the perspective of the \CONTEXT\ macro +package but this is not a manual about how to use fonts in \CONTEXT\ as we have +another manual for that. Much of what we say here applies to the generic font +code as well, although some more advanced control is \CONTEXT\ specific. There is +nothing real new here, and it all evolved from common sense and dealing with +\TEX\ for many years. The perspective is mostly that of being a user myself so +don't complain too loudly if things look complicated and unclear. + +There is some overlap between the chapters. This is because each chapter is +written from another perspective and this document quite certainly will not be +read as a whole but more by looking at examples. + +\startnotabene + This document will probably have an \quote {still under construction} state + for a long time. The functionality discussed here will stay and more might + show up. Of course there are errors, and they're all mine. +\stopnotabene + +\startlines +Hans Hagen +PRAGMA ADE, Hasselt NL +Summer 2011 \endash\ Spring 2016 +\stoplines + +\stopchapter + +\stopcomponent diff --git a/doc/context/sources/general/fonts/fonts/fonts-lookups.tex b/doc/context/sources/general/fonts/fonts/fonts-lookups.tex new file mode 100644 index 000000000..7f1128302 --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-lookups.tex @@ -0,0 +1,347 @@ +% language=uk + +\startcomponent fonts-lookups + +\environment fonts-environment + +\startchapter[title=Lookups][color=darkblue] + +\startsection[title=Introduction] + +In traditional \TEX\ a font is defined by referring to its filename. A +definition looks like this: + +\starttyping +\font \MyFontA = lmr10 +\font \MyFontB = lmr10 at 20pt +\font \MyFontC = lmr10 scaled 1500 +\stoptyping + +The first definition defines the command \type {MyFontA} as a reference to the +font stored in the file \type {lmx10}. No scaling takes place so the natural size +is taken. This so called designsize is in no way standardized. Just look at these +three specimen: + +\startlines +{\definedfont[file:dejavuserif*default]Design Size (Dejavu)} +{\definedfont[file:cambria*default]Design Size (Cambria)} +{\definedfont[file:lmroman10-regular*default]Design Size (Latin Modern)} +\stoplines + +The designsize is normally 10 point, but as there is no real reference for this a +designer decides how to translate this into a visual representation. As a +consequence the \type {20pt} in the second line of the example definitions only +means that the font is scaled to (normally) twice the designsize. The third line +scaled by a factor \type {1.5} and the reason for using a value thousand times +larger is that \TEX's numbers are integers. + +The next three lines are typical for Latin Modern (derived from Computer Modern) +because this family comes in different design sizes. + +\starttyping +\font \MyFontD = lmr12 +\font \MyFontE = lmr12 at 20pt +\font \MyFontF = lmr12 scaled 1500 +\stoptyping + +Because the designsize is part of the font metrics the second line (\type +{\MyFontE}) is of similar size as \type {\MyFontB} although the 12~point variant +is visually better suited for scaling up. + +These definitions refer to files, but what file? What gets loaded is the file +with name \type {name.tfm}. Eventually for embedding in the (let's assume \PDF) +file the outlines are taken from \type {name.pfb}. At that stage, when present, a +\type {name.vf} is consulted in order to resolve characters that are combinations +of others (potentially from other \type {pfb} files). The mapping from \type +{name.tfm} to \type {name.pfb} filename happens in the so called map file. This +means that one can also refer to another file, for instance \type {name.ttf}. + +All this logic is hard coded in the engine and because the virtual font mechanism +was introduced later without extending the \type {tfm} format, it can be hard at +times to figure out issues when a (maybe obsolete) virtual file is present (this +can be the case if you have generated the \type {tfm} file from an \type {afm} +file that comes with the \type {pfb} file when you buy one. + +But, in \LUATEX\ we no longer use traditional fonts and as a consequence we have +more options open. Before we move on to them, we mention yet another definition: + +\starttyping +\font \MyFontG = lmr12 sa 1.2 +\stoptyping + +This method is not part of \TEX\ but is provided by \CONTEXT, \MKII\ as well as +\MKIV. It means as much as \quotation {scale this font to 1.2 times the +bodyfontsize}. As this involves parsing the specification, it does not work +as advertised here, but the next definition works okay: + +\starttyping +\definefont[MyFontG][lmr12 sa 1.2] +\stoptyping + +This indicates that we already had a parser for font specifications on board +which in turn made it relatively easy to do even more parsing, for instance for +font features as introduced in \XETEX\ and \LUATEX. + +\stopsection + +\startsection[title=Specifications] + +In \LUATEX\ we intercept the font loader. We do so for several reasons. + +\startitemize[packed] + +\startitem We want to make decisions on what file to load, this is needed when +for instance there are files with the same name but different properties. \stopitem + +\startitem We want to be able to lookup by file, by name, and by more abstract specification. +In doing so, we want to be as tolerant as possible. \stopitem + +\startitem We want to support several scaling methods, as discussed in the previous section. \stopitem + +\startitem We want to implement several strategies for passing features and defining non +standard approaches. \stopitem + +\stopitemize + +The formal specification of a font is as follows: + +\starttyping +\definefont[PublicReference][filename] +\definefont[PublicReference][filename at dimension] +\definefont[PublicReference][filename scaled number] +\stoptyping + +We already had that extended to: + +\starttyping +\definefont[PublicReference][filename] +\definefont[PublicReference][filename at dimension] +\definefont[PublicReference][filename scaled number] +\definefont[PublicReference][filename sa number] +\stoptyping + +So let's generalize that to: + +\starttyping +\definefont[PublicReference][filename scaling] +\stoptyping + +And in \MKIV\ we now have: + +\starttyping +\definefont[PublicReference][filename*featurenames scaling] +\definefont[PublicReference][filename:featurespecication scaling] +\definefont[PublicReference][filename@virtualconstructor scaling] +\stoptyping + +The second variant is seldom used and is only provided because some users +have fonts defined in the \XETEX\ way. Users are advised not to use this +method. The last method is special in the sense that it's used to define +fonts that are constructed using the built in virtual font constructors. This +method is for instance used for defining virtual math fonts. + +The first method is what we use most. It is really important not to forget the +feature specification. A rather safe bet is \type {*default}. In a next chapter +we will discuss the difference between these two; here we focus on the name part. + +The \type {filename} is in fact a symbolic name. In \CONTEXT\ we have always used +an indirect reference to fonts. Look at this: + +\starttyping +\definefont[TitleFont][SerifBold*default sa 2] +\stoptyping + +A reference like \type {SerifBold} makes it possible to define styles independent +of the chosen font family. This reference eventually gets resolved to a real +name and there can be a chain of references. + +Font definitions can be grouped into a larger setup using typescripts. In that +case, we can set the features for a regular, italic, bold and bolditalic for the +whole set but when a fontname has a specific feature associated (as in the +previous examples) that one takes precedence. + +so far we talked about fonts being files, but in practice a lookup happens by +file as well as by name as known to the system. In the next section this will be +explained in more detail. + +\stopsection + +\startsection[title=File] + +You can force a file lookup with: + +\starttyping +\definefont[TitleFont][file:somefilename*default sa 2] +\stoptyping + +If you use more symbolic names you can use the \type {file:} prefix in the +mapping: + +\starttyping +\definefontsynonym[SerifBold][file:somefile] +\definefont[TitleFont][SerifBold*default sa 2] +\stoptyping + +In projects that are supposed to run for a long time I always use the file based +lookup, because filenames tend to be rather stable. Also, as the lookup happens +in the \TEX\ directory structure, file lookups will rely on the general file +search routines. This has the benefit that case is ignored. When no match is found +the lookup will also use the font name database. Spaces and special characters are +ignored. + +The name alone is not enough as there can be similar filenames with different +suffixes. Therefore the lookup will happen in the order \ctxcommand { +concatcommalist { list = fonts.readers.sequence, separator = ", ", last = " and +", command = "type" } }. You can force a lookup by being more explicit, like: + +\starttyping +\definefont[TitleFont][file:somefilename.ttf*default sa 1] +\stoptyping + +\stopsection + +\startsection[title=Name] + +Say that we want to use a Dejavu font and that instead of filenames we want to +use its given name. The best way to find out what is available is to call for a +list: + +\starttyping +mtxrun --script font --list --all dejavu +\stoptyping + +This produces the following list: + +\startnarrowtyping +dejavusans dejavusans dejavusans.ttf +dejavusansbold dejavusansbold dejavusans-bold.ttf +dejavusansboldoblique dejavusansboldoblique dejavusans-boldoblique.ttf +dejavusanscondensed dejavusanscondensed dejavusanscondensed.ttf +dejavusanscondensedbold dejavusanscondensedbold dejavusanscondensed-bold.ttf +dejavusanscondensedboldoblique dejavusanscondensedboldoblique dejavusanscondensed-boldoblique.ttf +dejavusanscondensednormal dejavusanscondensed dejavusanscondensed.ttf +dejavusanscondensedoblique dejavusanscondensedoblique dejavusanscondensed-oblique.ttf +dejavusansextralight dejavusansextralight dejavusans-extralight.ttf +dejavusanslight dejavusansextralight dejavusans-extralight.ttf +dejavusansmono dejavusansmono dejavusansmono.ttf +dejavusansmonobold dejavusansmonobold dejavusansmono-bold.ttf +dejavusansmonoboldoblique dejavusansmonoboldoblique dejavusansmono-boldoblique.ttf +dejavusansmononormal dejavusansmonooblique dejavusansmono-oblique.ttf +dejavusansmonooblique dejavusansmonooblique dejavusansmono-oblique.ttf +dejavusansnormal dejavusans dejavusans.ttf +dejavusansoblique dejavusansoblique dejavusans-oblique.ttf +dejavuserif dejavuserif dejavuserif.ttf +dejavuserifbold dejavuserifbold dejavuserif-bold.ttf +dejavuserifbolditalic dejavuserifbolditalic dejavuserif-bolditalic.ttf +dejavuserifcondensed dejavuserifcondensed dejavuserifcondensed.ttf +dejavuserifcondensedbold dejavuserifcondensedbold dejavuserifcondensed-bold.ttf +dejavuserifcondensedbolditalic dejavuserifcondensedbolditalic dejavuserifcondensed-bolditalic.ttf +dejavuserifcondenseditalic dejavuserifcondenseditalic dejavuserifcondensed-italic.ttf +dejavuserifcondensednormal dejavuserifcondensed dejavuserifcondensed.ttf +dejavuserifitalic dejavuserifitalic dejavuserif-italic.ttf +dejavuserifnormal dejavuserif dejavuserif.ttf +\stopnarrowtyping + +The first two columns mention the names that we can use to access a font. These +are normalized names in the sense that we only kept letters and numbers. The next three +definitions are equivalent: + +\starttyping +\definefont[TitleFont][name:dejavuserif*default sa 1] +\definefont[TitleFont][name:dejavuserifnormal*default sa 1] +\definefont[TitleFont][name:dejavuserif.ttf*default sa 1] +\stoptyping + +In the list you see two names that all point to \type {dejavusans-extralight.ttf}: + +\starttyping +dejavusansextralight +dejavusanslight +\stoptyping + +There are some heuristics built into \CONTEXT\ and we do some cleanup as well. +For instance we interpret \type {ital} as \type {italic}. In a font there is +sometimes information about the weight and we look at those properties as well. +Unfortunately font names (even within a collection) are often rather inconsistent +so you still need to know what you're looking for. The more explicit you are, the +less change of problems. + +\stopsection + +\startsection[title=Spec] + +There is often some logic in naming fonts but it's not robust and really depends on +how consistent a font designer or typefoundry has been. In \CONTEXT\ we can +access names by using a normalized scheme. + +\starttyping +name-weight-style-width-variant +\stoptyping + +The following values are valid: + +\starttabulate[|Bl|Tp|] +\NC weight \NC \ctxcommand { concatcommalist { list = fonts.names.knownweights } } \NC \NR +\NC style \NC \ctxcommand { concatcommalist { list = fonts.names.knownstyles } } \NC \NR +\NC width \NC \ctxcommand { concatcommalist { list = fonts.names.knownwidths } } \NC \NR +\NC variant \NC \ctxcommand { concatcommalist { list = fonts.names.knownvariants } } \NC \NR +\stoptabulate + +The four specifiers are optional but the more you provide, the better the match. Let's +give an example: + +\starttyping +mtxrun --script fonts --list --spec dejavu +\stoptyping + +This reports: + +\startnarrowtyping +dejavuserifcondensed normal normal normal normal dejavuserifcondensed dejavuserifcondensed.ttf +dejavuserif normal normal normal normal dejavuserif dejavuserif.ttf +dejavusansmono normal normal normal normal dejavusansmono dejavusansmono.ttf +dejavusanscondensed normal normal normal normal dejavusanscondensed dejavusanscondensed.ttf +dejavusans normal normal normal normal dejavusans dejavusans.ttf +\stopnarrowtyping + +We can be more specific, for instance: + +\starttyping +mtxrun --script fonts --list --spec dejavu-bold +\stoptyping + +\startnarrowtyping +dejavuserif bold normal normal normal dejavuserifbold dejavuserif-bold.ttf +dejavusansmono bold normal normal normal dejavusansmonobold dejavusansmono-bold.ttf +dejavusans bold normal normal normal dejavusansbold dejavusans-bold.ttf +\stopnarrowtyping + +We add another specifier: + +\starttyping +mtxrun --script fonts --list --spec dejavu-bold-italic +\stoptyping + +\startnarrowtyping +dejavuserif bold italic normal normal dejavuserifbolditalic dejavuserif-bolditalic.ttf +dejavusansmono bold italic normal normal dejavusansmonoboldoblique dejavusansmono-boldoblique.ttf +dejavusans bold italic normal normal dejavusansboldoblique dejavusans-boldoblique.ttf +\stopnarrowtyping + +As the first hit is used we need to be more specific with respect to the +name, so lets do that in an example definition: + +\starttyping +\definefont[TitleFont][spec:dejavuserif-bold-italic*default sa 1] +\stoptyping + +Watch the prefix \type {spec}. Wolfgang Schusters \type {simplefonts} module +nowadays uses this method to define sets of fonts based on a name only +specification. Of course that works best if a fontset has well defined +properties. + +\stopsection + +\stopchapter + +\stopcomponent diff --git a/doc/context/sources/general/fonts/fonts/fonts-math.tex b/doc/context/sources/general/fonts/fonts/fonts-math.tex new file mode 100644 index 000000000..7f226cb68 --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-math.tex @@ -0,0 +1,998 @@ +% language=uk + +\startcomponent fonts-math + +\environment fonts-environment + +\startchapter[title=Math][color=darkmix-3] + +\startsection[title=Introduction] + +As one can expect, math support in \CONTEXT\ is to some extend modelled after +what plain \TEX\ provides, plus what was later decided to be standard. This +mostly concerns the way fonts behave and what names are used to access glyphs or +special constructs. It means that when you come from another macro package you +can stick to coding math the way you did before, at least the basic coding. In +addition to this, \CONTEXT\ gives control over fonts, structure and rendering and +most of that was either driven by personal need or user demand. To be honest, +many of the options are probably of not much interest to the average user. + +As we focus on fonts we will only touch this aspect of math here. Right from when +we started with developing \LUATEX, cleaning op the math part of \CONTEXT\ was +part of the game. Some primitives were added that would make it possible to avoid +unnecessary complex macros to get certain glyphs rendered, like radicals, accents +and extensibles. This was made easy because we also support \OPENTYPE\ math and +because we knew that eventually the Latin Modern and Gyre fonts would also +support \OPENTYPE. In order to move forward and get rid of traditional eight bit +fonts \CONTEXT\ \MKIV\ can construct a virtual \OPENTYPE\ font from traditional +math fonts. It makes not much sense to discuss that here as by now this method is +only provided for reasons of compatibility and a reference to the past. As a lot +of time went into this it will always stay around if only to remind us of what +we went through to get where we are now. + +\stopsection + +\startsection[title=\UNICODE\ math] + +Due to the limited amount of glyphs in a \TYPEONE\ font a macro package has to +jump through loops in order to get traditional \TEX\ engines behave well. As a +practical consequence these fonts are often a mixture of characters, symbols, +punctuation and snippets that make up larger shapes. The font dimensions in these +files have often special meanings too. + +This has all changed considerably with math being part of \UNICODE. It was however +\MICROSOFT\ where the real action took place: the development of the first font that +combined \UNICODE\ with \OPENTYPE\ technology. The Cambria font can be considered +the benchmark for fonts that surfaced later. The characteristic of a math font are +the following: + +\startitemize[packed] + \startitem All math alphabets are present: latin as well as greek, in regular, + italic, bold, fraktur and script variants as well as some combinations of these. \stopitem + \startitem The symbols that make sense are present (read: the more obscure shapes + can be omited). \stopitem + \startitem For the characters that make sense, there are two variants that render well + at smaller sizes: script and scriptscript. In the font they have the same size but + the application will scale them down. This feature is named \type {ssty}. \stopitem + \startitem Characters that can extend horizontally (for instance accents and arrows) or vertically + (like radicals and fences) have associated larger variants and carries information about + how to grow indefinitely. \stopitem + \startitem There is a whole lot of special math dimensions. Most of the ones + already used in \TEX\ are present. \stopitem + \startitem Some glyphs come in variants in order to please special usage. There + can also be variants for script or fraktur alphabets. \stopitem +\stopitemize + +This means that in practice an \OPENTYPE\ math font is quite large. We easily +have thousands of glyphs. It also means that creating such a font involves some +expertise and this is one of the reasons why \TEX\ usergroups have joined forces +in developing a suite of fonts. There are also other initiatives in the \TEX\ +community, of which Xits is an example. \footnote {This is a useable +variant of Stix fonts with proper math features, some extra glyphs and +experimental right||to||left shapes.} The well known Lucida Bright math font +package has also been upgraded to a set of \OPENTYPE\ math fonts. + +The fact that there are not that many math fonts out there has a positive side as +well: \CONTEXT\ comes with them pre|-|configured. Because during the development +of \LUATEX\ we needed to have at least a couple of fonts for testing, and because +it makes no sense to waste time on traditional fonts, the Latin Modern, Palatino, +Times and a few more fonts were (and still are) provided as virtual \UNICODE\ +fonts. + +In a regular text font, what you key in is what you get out. So, when you've +chosen a font with an italic shape, you get italic shapes, even if the smallcaps +feature is enabled. In math, if you use the right unicodes you also get the shape +you expect. Because in this case italic shapes are situated in one of the +alphabets you explicitly choose a rendering. You can enter the right codepoints +directly, so for instance if you enter \UNICODE\ character \type {U+1D434} you +will get \mathematics {\utfchar {"1D434}}. In practice something like \type {$\bi +A$} should also give that character if only because that is what we have been +doing for over three decades. This means that the engine has to map a regular +\type {A} onto the bold italic alphabet. In a traditional approach you will use +math families for this, but in \CONTEXT\ \MKIV\ we simply use one font and one +family and let the \MKIV\ machinery do the rest. + +In text mode we switch fonts styles in the following way: + +\startbuffer +regular {\it italic} {\bf bold} {\bi bold italic} and so on +\stopbuffer + +\typebuffer + +The three commands shown here are shortcuts for font switches. This input is +converted into an internal representation and after whatever manipulations +are applied end up as: + +\blank \getbuffer \blank + +If we look at what fonts we end up with we get: + +\blank \markfonts{\getbuffer} \blank + +Now lets do the same in math mode: + +\startbuffer +$regular {\it italic} {\bf bold} {\bi bold italic} and so on$ +\stopbuffer + +\typebuffer + +This time we get a different result: + +\blank \getbuffer \blank + +If again we analyze the fonts you see this: + +\blank \markfonts{\getbuffer} \blank + +All glyphs come from the same font. Instead of regular we get italic simply because +math characters are italic by nature. The two character style switches are not +really font switches but just make sure that the given input is mapped onto the +right alphabet. + +A traditional approach using \TYPEONE\ fonts is to use a so called math family for +each alphabet. In that case each alphabet maps one||to||one onto the font: when +we switch to a bold family we just take the glyph that sits in that slot. In \MKIV\ +we have all characters in one family so behind the screens a given character is +remapped. + +Now take a look at the following example: + +\startbuffer +$text^{script^{scriptscript}}$ +\stopbuffer + +\typebuffer + +This renders to this, with the characters marked by font: + +\blank \markfonts{\getbuffer} \blank + +This time we have three different fonts: one for each of the three math sizes. +But this representation is not entirely honest, because indeed we have three font +instances for math, but the glyphs come from the same \OPENTYPE\ math font. We +just load the same font three times, once for each size. In fact we load the +font once, but use three copies, scaled accordingly to the relative scale the +font prescribes. + +There is a whole bunch of commands to choose specific characters in math mode +using a regular input. These are state switching commands. + +\def\SampleLine#1#2#3% + {\NC \type{#1}\space + \ifx#2\empty\else\type{#2}\fi\space + \ifx#3\empty\else\type{#3}\fi + \NC $#1 a$ + \NC $#1 A$ + \NC \NR} + +\starttabulate[|||||] +\HL +\SampleLine \mr \empty \empty +\HL +\SampleLine \mathdefault \empty \empty +\SampleLine \mathscript \empty \empty +\SampleLine \mathfraktur \empty \empty +\SampleLine \mathblackboard\empty \empty +\HL +\SampleLine \rm \mathrm \empty +\SampleLine \ss \mathss \empty +\SampleLine \tt \mathtt \empty +\HL +\SampleLine \tf \mathtf \tfmath +\SampleLine \sl \mathsl \slmath +\SampleLine \it \mathit \itmath +\HL +\SampleLine \bf \mathbf \bfmath +\SampleLine \bs \mathbs \bsmath +\SampleLine \bi \mathbi \bimath +\HL +\stoptabulate + +As you can see here, some commands have synonyms. The short commands adapt +themselves to text and mathmode, the longer ones are meant for use in math mode +only. + +In text mode distinctive shapes are either a font property (the whole font looks +that way) or a stylistic alternate (an extra feature of a font). In math mode we +can have alternates, but in addition to the previously mentioned alphabet +switchers we have a few more: + +\starttabulate[|||||] +\HL +\SampleLine \frak \empty \empty +\SampleLine \cal \empty \empty +\SampleLine \bbd \empty \empty +\SampleLine \blackboard \empty \empty +\SampleLine \fraktur \empty \empty +\SampleLine \gothic \empty \empty +\HL +\stoptabulate + +This chapter is not meant as an introduction to math but it is good to know +that math font support in \CONTEXT\ is rather flexible. There are several +mechanisms for remapping and converting characters and sequences into +others and more is possible. Here is one: + +\startbuffer +\startformula +\reals {\mathbf R} \utfchar{"0211D} \utfchar{"1D411} +\stopformula +\stopbuffer + +\typebuffer \blank \getbuffer \blank + +Compare this to: + +\startbuffer +\setupmathematics[symbolset=blackboard-to-bold] +\startformula +\reals {\mathbf R} \utfchar{"0211D} \utfchar{"1D411} +\stopformula +\stopbuffer + +\typebuffer \blank \start \getbuffer \stop \blank + +Greek is always troublesome because instead of regular text shapes math uses a +few variants. Because in \UNICODE\ characters are only included once, we have +gaps in the math alphabets but \MKIV\ will take care of this. \footnote {This is +a typical example of where exceptions in a standard force all applications that +deal with it have to implement tweaks.} Depending on the field an author has to +choose between upright and italic greek: + +\startbuffer +$\nabla \alpha \mathgreekupright \nabla \alpha \mathgreekitalic \nabla \alpha$ +\stopbuffer + +\typebuffer \blank \start \getbuffer \stop \blank + +By default \CONTEXT\ is set up as follows: + +\starttyping +\setupmathematics + [sygreek=normal, + lcgreek=italic, + ucgreek=normal] +\stoptyping + +Again, these are not features of a font. The font just provides the glyphs and +the \TEX\ engine, controlled by \CONTEXT\ takes care of mapping characters to +glyphs and building special constructs. The same is true for spacing. Although +math fonts do have kerning information, most of the math spacing is controlled +by properties of characters and not by the font. + +\unexpanded\def\SampleLine#1% + {\NC + \type{$a #1{+} b$} + \NC + \ruledhbox{$\mathsurround\zeropoint a#1{+}b$} + \NC \NR} + +\starttabulate[|||] +\SampleLine \mathord +\SampleLine \mathpunct +\SampleLine \mathinner +\SampleLine \mathop +\SampleLine \mathalpha +\SampleLine \mathnothing +\SampleLine \mathbin +\SampleLine \mathrel +\stoptabulate + +As a user you don't have to worry about these issues because characters are tagged +according to their usage. \footnote {There are a few more commands, like \type +{\mathlimop}, \type {\mathnolop} and \type {mathbox} but these are used +differently.} + +With \TEX\ being the oldest and still dominant math renderer it is no surprise +that \MICROSOFT\ modelled its math renderer after \TEX\ and Cambria quite well +suits the concept. In retrospect it is somewhat unfortunate that we're still +stuck with some left overs (or compromises) from the past with respect to spacing +built into the font. However, as long as this is consistent over fonts it's not +that relevant. You can always influence the spacing with the commands mentioned. + +If you look at the low level definitions in for instance plain \TEX\ but also in +\CONTEXT\ \MKII\ that relate to prime symbols it probably takes a while before you +figure out what happens there. For instance, the prime symbol is triggered by a +quote and multiple in a row results in primes that are spaced tightly. In +\UNICODE\ we have slots for single, double and tripple primes. Therefore, in +\MKIV\ we have a mechanism that accepts different kinds of input that eventually +all end up in one of these three glyphs. + +\unexpanded\def\SampleLine#1% + {\NC \type{#1} \NC #1 \NC \NR} + +\starttabulate[|||] +\SampleLine{$f^2$} +\SampleLine{$f\prime^2$} +\SampleLine{$f\prime\prime^2$} +\SampleLine{$f\prime\prime\prime^2$} +\SampleLine{$f{\prime}^2$} +\SampleLine{$f{\prime\prime}^2$} +\SampleLine{$f{\prime\prime\prime}^2$} +\SampleLine{$f'(x)$} +\SampleLine{$f''(x)$} +\SampleLine{$f'''(x)$} +\SampleLine{$f\utfchar{0x2032}(x)$} +\SampleLine{$f\utfchar{0x2033}(x)$} +\SampleLine{$f\utfchar{0x2034}(x)$} +\SampleLine{$f\utfchar{0x2032}\utfchar{0x2032}(x)$} +\SampleLine{$f\utfchar{0x2032}\utfchar{0x2032}\utfchar{0x2032}(x)$} +\SampleLine{$f\utfchar{0x2033}\utfchar{0x2032}(x)$} +\SampleLine{$f\utfchar{0x2032}\utfchar{0x2033}(x)$} +\stoptabulate + +Again, this is not the same as ligature building features in text fonts, but +handled in a different way. + +The \TEX\ engine understands the concept of italic correction. When an italic +shape is followed by for instance an upright shape, you can insert a \type {\/} +and the engine will add a correction as defined in the font. In \OPENTYPE\ we +don't have such corrections available but we can fake it, which is what the \type +{itlc} feature in \CONTEXT\ does. However, you need to enable this feature +explicitly. An example of a setup is: + +\starttyping +\definefontfeature + [default] + [default] + [itlc=yes,textitalics=yes] + +\setupitaliccorrection + [global,always] +\stoptyping + +This will make sure that the right amount of correction is added between +italic shapes and non italics or boxes. Using \type {text} instead of +\type {always} would limit the correction to glyphs only and leaving out +the \type {global} would permit selective (grouped) usage at the cost +of more runtime. There is no need for the \type {\/} here. + +In math we also can have italic correction but there it is built into the engine +and in traditional \TEX\ no directives are needed. Italic correction properties +in math fonts are somewhat troublesome as their application depends on what we're +dealing with: symbols, super- and subscripts, etc. Because early versions of +\LUATEX\ didn't handle all of it well, if only because the fonts were not yet okay, +the \MKIV\ math handler provides a bit of control. + +\def\SampleLine#1#2% + {\NC #1 + \NC \setupmathematics[italics=#1]\ruledhbox{$m$ t} + \NC \setupmathematics[italics=#1]\ruledhbox{$m$ {\it t}} + \NC \setupmathematics[italics=#1]\ruledhbox{t $m$ t $m$ {\it t}} + \NC #2 + \NC \NR} + +\starttabulate[||||||] +\SampleLine0{no correction} +\SampleLine1{only apply italics when the font carries them} +\SampleLine2{apply italics provided by the font or automatically calculated} +\SampleLine3{apply italics based on an emwidth and character properties} +\SampleLine4{use method 1 but fall back on 3 if needed} +\stoptabulate + +Because we cannot rely on fonts too much, we default to method~3 which in practice +works out well, so the setup is: + +\starttyping +\setupmathematics + [italics=3] +\stoptyping + +There are all kind of commands that can be used to build math constructs in such a +way that super- and subscripts are consistently rendered. It goes beyond this +chapter to discuss them and most users will never see or use those commands. The +main message of the examples above is that text and math use different fonts and +properties and therefore also different methods in rendering text or a formula. +Even if the names of mechanisms are the same (like italics) you cannot assume +that both modes do exactly the same. + +\stopsection + +\startsection[title=Bold math] + +If you look at what \UNICODE\ provides you will notice that there are quite some +bold characters. First of all there are a bunch of alphabets and because bold is +not present in the text part of \UNICODE\ these alphabets have no holes. Then +there are some symbols that have special meaning. + +\startluacode +local find = string.find +local NC, NR = context.NC, context.NR + +context.starttabulate { "|Tl||l|" } +for unicode, entry in table.sortedhash(characters.data) do + local description = entry.description + if find(description,"^MATHEMATICAL BOLD") then + NC() context("U+04X",unicode) + NC() context.mathematics(utf.char(unicode)) + NC() context(description) + NC() NR() + end +end +context.stoptabulate() +\stopluacode + +The biggest mistake one can make when discussing bold math is the assumption that +these bold alphabets are meant for section titles and other structural elements +that need some emphasis. This is not true, in that case we would expect the whole +formula to be bold and the bold symbols or variables would be even more bold. +Bold math boils down to {\em all} math being bold. The reason why we show the +list of bold characters on the previous pages is that it gives a good impression of +fact that we're mostly given alphabets in an otherwise regular font. + +As Latin Modern (being derived from Computer Modern) has some bold extras in +\MKII\ to some extend we do support a complete bold math switch but mixing bold +formulas with regular ones has some limitations. Math typesetting consists of two +phases: first the input is translated into a special list where references to +fonts are not yet resolved. Instead families are used and each family has three +sizes: text, script and scriptscript. In a second pass the formula is typeset and +the families get translated into fonts. So, if we change the definition of a +family, say math italic into bold math italic, then the definition that is actual +when the second pass takes place is used. + +Although \LUATEX\ provides for many more families and as a consequence we could +have replaced the \MKII\ mechanism with a more complete one, instead we just +forgot about it and stuck to one family for regular math and another one for bold +math. Okay, this is not entirely true as later on we added some more in order to +deal with bidirectional typesetting. + +Only a few math fonts come with a bold variant. One of the objectives of the \TEX +Gyre math font project is to explore the possibilities of bold math companions, +but such a font will probably have less coverage, simply because no real complex +math will end up in for instance section titles. + +When I wrote this down there were not that many math fonts that come with a real +(complete) bold variant. The \CONTEXT\ math font subsystem tries to fill this gap +as good as possible by using pseudo fonts. When a typeface doesn't define a math +bold variant a pseudo setup is used. When a real bold font is used, it could be +that not all alphabets are supported in which case a suitable alternative is +tried. + +The Xits font, assembed from Stix and enhanced by Khaled Hosny, comes with a bold +variant but the coverage is not complete, at least not when I wrote this +paragraph. This can go unnoticed because \CONTEXT\ tries to work around this. On +the other hand, it definitely has bold properties, which can be seen from the +next example. You switch between regular and bold math with the \type {\mr} and +\type {\mb} commands. + +\startbuffer +\switchtobodyfont[xitsbidi] + +$ \sqrt{x } \quad + \mb \sqrt{mb} \quad + \mathupright \sqrt{u } \quad + \mr \sqrt{mr} \quad + \mathupright \sqrt{u } \quad + \mathdefault \sqrt{d } +$ +\stopbuffer + +\typebuffer \blank \start \getbuffer \stop \blank + +You can track some of what happens with: + +\starttyping +\enabletrackers[math.remapping,math.families] +\stoptyping + +You will get some information about remapping or when it fails if fallback +remapping is used. But no matter what happens with glyphs, you will notice in +this example that the radical symbol is bold indeed. + +\stopsection + +\startsection[title=Bidirectional math] + +There is not that much to tell about bidirectional math typesetting, simply +because the fonts are still in development. However, Khaled Hosny added +some support to the Xits font. Of course you need to load this font first: + +\starttyping +\switchtobodyfont[xitsbidi] +\stoptyping + +In the previous chapter we mentioned bold math and as Xits also comes with +a bold variant which means that this command loads the whole lot (which is +fast enough anyway). + +Easiest is to just show a few examples. When in left to right mode we get what we +are accustomed to: + +\startbuffer +\setupmathematics[align=l2r] + +\startformula +\sqrt{x^2\over 4x} \eqno(1) +\stopformula + +\startformula +5 < 6 > 4 +\stopformula + +\startformula +5 \leq 6 \geq 7 +\stopformula +\stopbuffer + +\typebuffer \start \switchtobodyfont[xitsbidi] \getbuffer \stop + +However, when we go the other way, we automatically get digits converted to +arabic. + +\startbuffer +\setupmathematics[align=r2l,bidi=yes] + +\startformula +\sqrt{ف^2\over 4ب} \eqno(1) +\stopformula + +\startformula +5 < 6 > 4 +\stopformula + +\startformula +5 \leq 6 \geq 7 +\stopformula +\stopbuffer + +\typebuffer \start \switchtobodyfont[xitsbidi] \getbuffer \stop + +You don't have to worry about how the font is set up, but not that much is needed +because \CONTEXT\ does it for you and the Xits typescripts carries the right +definitions. Just to give you an idea, we show a feature definition: The magic is +in the \type {rtlm} feature combined with \type {locl}. + +\starttyping +\definefontfeature + [mathematics-r2l] + [mathematics] + [language=ara, + rtlm=yes, + locl=yes] +\stoptyping + +Some symbols are mirrored too: + +\startbuffer +\setupmathematics[align=r2l,bidi=yes] + +\startformula +\sum^\infty_{س=0} س^2 \eqno(2) +\stopformula +\stopbuffer + +\typebuffer \start \switchtobodyfont[xitsbidi] \getbuffer \stop + +And of course the extensible fences are done properly too: + +\startbuffer +\setupmathematics[align=r2l,bidi=yes] + +\startformula +\left(\root{2} \of{155}\right) +\stopformula + +\startformula +\left[\int^{55}_{123} 666^3\right] +\qquad\textstyle\left[\int^{55}_{123} 666^3\right] +\stopformula + +\startformula +\left\{\sum^{55}_{123} 666^3\right\} +\stopformula +\stopbuffer + +\typebuffer \start \switchtobodyfont[xitsbidi] \getbuffer \stop + +The real torture test is the radical sign. A mirrored shape is used +and it grows upwards as well as leftwards. + +\startbuffer +\setupmathematics[align=r2l,bidi=yes] + +\startformula +\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{55}}}}}}}}}} +\stopformula +\stopbuffer + +\typebuffer \start \switchtobodyfont[xitsbidi] \getbuffer \stop + +\stopsection + +\startsection[title=Styles] + +In text mode you use font switches like \type {\sl} that switches the current font +to a slanted one. In math mode it is an alphabet switch in the same font. In +fact, there isn't much to choose from fonts there, apart from a massive switch +to bold, in which case \type {\bf} is just a bolder alphabet in that bolder font. + +A lot of things in math mode happen automatically. There are for instance always +three instances of (the same) font active, each different in size: text, script +and the smallest, scriptscript and when you ask for instance for a superscript +the next smaller size is used. + +\starttabulate[|l|l|l|] +\NC normal \NC \type {\textstyle} \NC $\textstyle text^{script^{scriptscript}}$ \NC \NR +\NC smaller \NC \type {\scriptstyle} \NC $\scriptstyle text^{script^{scriptscript}}$ \NC \NR +\NC smallest \NC \type {\scriptscriptstyle} \NC $\scriptscriptstyle text^{script^{scriptscript}}$ \NC \NR +\stoptabulate + +In text style, superscripts can go twice smaller, but in script style only one +smaller size is left, and in scriptscript style you're stuck with one size. The +commands in the second column can be used to force a style. + +The math formula builder has an important property: the formula is typeset after +it has been scanned completely. In a traditional setup that has some +consequences. Take this: + +\starttyping +one \sl two \bf three \bi four +\stoptyping + +In a traditional setup four so called families are used and each character gets +tagged with a family number. So we have (for instance): + +\blank \start \tttf +o\low7n\low7e\low7 t\low6w\low6o\low6 t\low5h\low5r\low5e\low5e\low5 f\low9o\low9u\low9r\low9 +\stop \blank + +As the number of families was limited there could be at most 16 families. In +fact, the first four were traditionally reserved for math roman, math italic, +symbol and extensibles. Then, due to the limit of 256 characters per font, +another few were used for additional symbol fonts. So, adding a few more variants +could exhaust the family pool quite fast. You could argue that we could halfway +redefine a family but this will not work as there is a one to one relationship +between family numbers and fonts assigned to them when the formula has been +read in (the last value counts). And grouping won't help you either. + +The actual (plain) situation is even more complex. As we have a limited number of +characters per font, most symbols are accessed by name, and the name relates to a +mathematical character definition using for instance \type {\mathchardef}. Such a +definition refers to a slot in a specific family number and therefore font. It +also puts a character in a so called math class. One of these, the alphanumeric +class, with number~7, is special. Characters that are input directly on the +keyboard (like \type {a}||\type {z} can also be tagged this way using \type +{\mathcode}. + +When we switch a family, this will normally not affect a symbol defined as math +character, simply because we refer to a specific family|/|slot combination, but +when a character has class~7, then it will be taken from the current family. This +permits latin letters, digits and greek letters to be typeset in different +styles. So, in that traditional approach we have fonts that provide a bunch of +symbols as well as some alphabets. Think for instance of a font with additional +symbols where the regular alphabet slots contain blackboard shapes. The symbols +are accessed directly and the characters are accessed via the regular \type +{a}||\type {z} characters as these will adapt to the family and therefore font. +In practice users will not notice this complication as macro packages hide the +implementation details. + +In \MKIV\ the situation is different as there we have one family (or a few more +if we use a full bold switch and|/|or bidirectional math). Although we no longer +have the limit of 16 fonts we actually don't need that many families, at least +not in the way we've set up \MKIV \footnote{A technical note: in principle the +\MKIV\ approach can have a speed penalty compared to a multi||family approach but +we don't care too much about it. Also, as we load less fonts the extra overhead gets +compensated nicely.} + +\blank \start \tttf +o\low1n\low1e\low1 t\low1w\low1o\low1 t\low1h\low1r\low1e\low1e\low1 f\low1o\low1u\low1r\low1 +\stop \blank + +So how does this relate to styles? Each family has three fonts and we can use the +switch commands to choose any of these. In text mode we use the term style for a +font switch, while in math mode it's more than that: indeed we switch a font, but +only in size, but the spacing is also adapted. If a proper math font is used, the +smaller sizes are actually alternates in the font, visually adapted to suit their +use. + +In text mode we do this in order to limit the scope of a switch: + +\starttyping +normal {\bf bold {\it italic} bold} normalbracket +\stoptyping + +This is the same as: + +\starttyping +normal \bgroup \bf bold \bgroup \it italic\egroup + \ bold\egroup \ normalbracket +\stoptyping + +and: + +\starttyping +normal \begingroup \bf bold \begingroup \it italic\endgroup + \ bold\endgroup \ normalbracket +\stoptyping + +The \CONTEXT\ distribution ships with a plain math definition file that also uses +one family but reassigns some math codes when we switch to another style. As the +number of characters that this applies to this is efficient enough for a modern +computer. A peek into \type {luatex-math.tex} gives an impression of what we deal +with. However, keep in mind that the implementation in \MKIV\ goes it differently +and is therefore more powerful. We also have hardly any definitions at the \TEX\ +end and use information from \type {char-def.lua} instead. + +In math mode there is a subtle difference in the way grouping works with styles: + +\starttyping +text {\scriptstyle script} normal +\stoptyping + +This is the same as: + +\starttyping +text \bgroup\scriptstyle script\egroup\ normal +\stoptyping + +but different from: + +\starttyping +text \begingroup\scriptstyle script\endgroup\ script +\stoptyping + +This has to do with the fact that a style switch is explicitly registered in the +math list and grouping like this is not limiting the scope. In math mode the +braced grouping mode actually does create a math group and there the scope of the +switch is limited to that group. In practice users will not run into this but +they can use macros that use \type {\begingroup}. Among other reasons, this is +why we have a special mathstyle mechanism. + +\startbuffer +\ruledhbox{$x\begingroup\scriptstyle x\endgroup x$} \quad +\ruledhbox{$x\begingroup\setupmathstyle[script]x\endgroup x$} \quad +\ruledhbox{$x{\setupmathstyle[script]x}x$} \quad +\ruledhbox{$x\startmathstyle[script]x\stopmathstyle x$} +\stopbuffer + +\typebuffer + +This gives: + +\startlinecorrection[blank] \dontleavehmode \getbuffer \stoplinecorrection + +Mechanisms that support the \type {mathstyle} parameter know how to apply the +proper grouping so you don't have to worry there. You can best avoid using the +verbose grouping command and stick to braces or the \type {start}||\type {stop} +command. An example is the fence mechanism: + +\startbuffer +\definemathfence + [fancybracket] [bracket] + [color=darkblue] +\definemathfence + [smallbracket] [bracket] + [command=yes,color=darkgreen,mathstyle=small] +\definemathfence + [normalbracket] [bracket] + [command=yes,color=darkred] +\stopbuffer + +\typebuffer \getbuffer + +We apply this to an example: + +\startbuffer +$x \fenced[bar]{\frac{1}{x}} x$ \quad +$x \fenced[doublebar]{\frac{1}{x}} x$ \quad +$x \fenced[bracket]{\frac{1}{x}} x$ \quad +$x \fenced[fancybracket]{\frac{1}{x}} x$ \quad +$x \frac{1}{n} \normalbracket{\frac{1}{n}} \smallbracket{\frac{1}{s}} x$ +\stopbuffer + +\typebuffer + +Of course these somewhat weird examples are not real but at least they +demonstrate the principles. + +\startlinecorrection[blank] \dontleavehmode \getbuffer \stoplinecorrection + +A math style is a combination of the following keys. Their effect can depend on +the current state, for instance you can switch cramp or size indepently. + +\starttabulate[|T||] +\NC display \NC display style, like text style but somewhat more spacy \NC \NR +\NC text \NC text style, normally used inline \NC \NR +\NC script \NC smaller than text cq. display style \NC \NR +\NC scriptscript \NC smaller than script style \NC \NR +\NC cramped packed \NC more tightly positioned superscripts \NC \NR +\NC uncramped normal \NC normal positioned superscripts \NC \NR +\NC small \NC switch to the next smaller style but keep cramp state \NC \NR +\NC big \NC switch to the next larger style but keep cramp state \NC \NR +\stoptabulate + +Future versions of \MKIV\ will provide more features (like parameter sets driven +by keywords). As you might prefer a more symbolic approach we provide: + +\starttyping +\definemathstyle[default][text,cramped] +\stoptyping + +After this you can use the keyword \type {default} which has the advantage that +you only need to change one definition in order to get different rendering. + +\stopsection + +\startsection[title=Supported fonts] + +As in \CONTEXT\ MKIV\ I wanted to go ahead with \UNICODE\ math as soon as the +first version of \LUATEX\ showed up. Because at that time only Cambria was +available I decided to provide virtual \UNICODE\ math fonts as a prelude to +proper replacements for the popular \TYPEONE\ math fonts. In the meantime Xits +came around and in 2012 we had quite useable math companions for the public Latin +Modern, Pagella and Termes fonts and the \TEX\ user groups started shipping +\OPENTYPE\ variants of Lucida. The virtual variants will still around so that we +can compare them with the new implementations. As the official specification of +\OPENTYPE\ math is not always clear from the beginning the \OPENTYPE\ fonts get +improved over time. In fact, this is true not only for math fonts. Just think of +this: + +\startitemize + +\startitem As \UNICODE\ gets extended, fonts might get more glyphs and possibly +alternate shapes. \stopitem + +\startitem The more languages are supported, the more glyphs are to be available +and features have to get language dependent instances. \stopitem + +\startitem The larger the font, the bigger the chance that mistakes get unnoticed +especially when contextual subtitutions and positioning are used. \stopitem + +\startitem Math fonts can get more script and scriptscript alternates, more size +variants, more advanced extensibles, bidirectional support, etc. \stopitem + +\stopitemize + +So, like regular programs, \LUATEX\ and macro packages, we now have fonts as +component that needs occasional updating. Of course resources like hyphenation +patterns are also subjected to this, so it's not a new aspect. But still, best +keep en eye on font updates. + +While there are lots of text fonts, there are not that many math fonts, so you +can safely assume that \CONTEXT\ ships with the proper setup for those fonts. Of +course you have to choose a specific instance when you set up your own +combination of fonts, but a peek into the typescripts shows the way. + +In the font manual and on the wiki you can find more about typescript and what is +possible, so here we just take a look at one definition: + +\startnarrowtyping +\starttypescript [serif] [dejavu] [name] + \definefontsynonym [Serif] [name:dejavuserif] [features=default] + \definefontsynonym [SerifBold] [name:dejavuserifbold] [features=default] + \definefontsynonym [SerifItalic] [name:dejavuserifitalic] [features=default] + \definefontsynonym [SerifBoldItalic] [name:dejavuserifbolditalic] [features=default] +\stoptypescript + +\starttypescript [sans] [dejavu] [name] + \definefontsynonym [Sans] [name:dejavusans] [features=default] + \definefontsynonym [SansBold] [name:dejavusansbold] [features=default] + \definefontsynonym [SansItalic] [name:dejavusansoblique] [features=default] + \definefontsynonym [SansBoldItalic] [name:dejavusansboldoblique] [features=default] +\stoptypescript + +\starttypescript [mono] [dejavu] [name] + \definefontsynonym [Mono] [name:dejavusansmono] [features=none] + \definefontsynonym [MonoBold] [name:dejavusansmonobold] [features=none] + \definefontsynonym [MonoItalic] [name:dejavusansmonooblique] [features=none] + \definefontsynonym [MonoBoldItalic] [name:dejavusansmonoboldoblique] [features=none] +\stoptypescript + +\starttypescript[dejavu] + \definetypeface [dejavu] [rm] [serif] [dejavu] [default] + \definetypeface [dejavu] [ss] [sans] [dejavu] [default] + \definetypeface [dejavu] [tt] [mono] [dejavu] [default] + \definetypeface [dejavu] [mm] [math] [xits] [default] [scale=1.2] +\stoptypescript +\stopnarrowtyping + +So, in many cases you can just copy this blob and replace the font names by your +own. + +Loading a font, and Dejavu is a predefined one, is done as follows: + +\starttyping +\setupbodyfont[dejavu] +\stoptyping + +In a similar fashion you can enable \type {cambria}, \type {pagella}, \type +{termes}, \type {lucidaot}, etc.\ and if you don't use this command at all, you +get Latin Modern. These fonts are part of \TEX\ distributions, including +\CONTEXT\ stand||alone that can be downloaded from \CONTEXT\ garden. + +If you want to use Lucida, all you have to do when you have bought the fonts, is +to put the \OPENTYPE\ files in a place where they can be found, for instance: + +\starttyping +tex/texmf-fonts/fonts/data/lucida +\stoptyping + +Of course you need to run \type {mtxrun --generate} afterwards so that the files +can be found. + +\startnotabene + Tracing and characters coverage will be discussed here as soon as the styles + that are used for them are normalized. +\stopnotabene + +\stopsection + +\startsection[title={Stylistic alternates}] + +Some fonts provide stylistic alternates. These can be described in goodies files +and the Lucida setup is a good example. Here we demonstrate the effects. We +disable the default math rendering (which takes the italic variants). + +\startbuffer[sa:1] +\switchtobodyfont[lucidaot,14.4pt] +\setupmathrendering[lucidaot][it=] +$x + ^{i \leftarrow 0 = ∅} + _{i \leftarrow 0 = ∅} +$ +\stopbuffer + +\typebuffer[sa:1] + +The next code enabled three alternatives: + +\startbuffer[sa:2] +\switchtobodyfont[lucidaot,14.4pt] +\setupmathrendering[lucidaot][it=] +$x + ^{i \leftarrow 0 = ∅} + _{\setmathfontalternate{arrow} + \setmathfontalternate{dotless} + \setmathfontalternate{zero} + i \leftarrow 0 = ∅} +$ +\stopbuffer + +\typebuffer[sa:2] + +Here we set them in one go: + +\startbuffer[sa:3] +\switchtobodyfont[lucidaot,14.4pt] +\setupmathrendering[lucidaot][it=] +$x + ^{i \leftarrow 0 = ∅} + _{\setmathfontalternate{arrow,dotless,zero} + i \leftarrow 0 = ∅} +$ +\stopbuffer +\ +\typebuffer[sa:3] + +The last example shows how to enable these features globally: + +\startbuffer[sa:4] +\switchtobodyfont[lucidaot,14.4pt] +\setupmathrendering[lucidaot][it=] +\setupmathematics[stylealternative={arrow,dotless,zero}] +$x + ^{i \leftarrow 0 = ∅} + _{i \leftarrow 0 = ∅} +$ +\stopbuffer + +\typebuffer[sa:4] + +The results are collected here: + +\startlinecorrection[blank] +\startcombination[4*1] + {\vbox{\hsize.2\hsize\midaligned{\nospacing\getbuffer[sa:1]}}} {\bf nothing} + {\vbox{\hsize.2\hsize\midaligned{\nospacing\getbuffer[sa:2]}}} {\bf stepwise} + {\vbox{\hsize.2\hsize\midaligned{\nospacing\getbuffer[sa:3]}}} {\bf combined} + {\vbox{\hsize.2\hsize\midaligned{\nospacing\getbuffer[sa:4]}}} {\bf global} +\stopcombination +\stoplinecorrection + +\stopsection + +\stopchapter + +\stopcomponent diff --git a/doc/context/sources/general/fonts/fonts/fonts-methods.tex b/doc/context/sources/general/fonts/fonts/fonts-methods.tex new file mode 100644 index 000000000..eac86d694 --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-methods.tex @@ -0,0 +1,376 @@ +% language=uk + +\startcomponent fonts-methods + +\environment fonts-environment + +\startchapter[title=Methods][color=darkyellow] + +\startsection[title=Introduction] + +A font definition looks as follows: + +\starttyping +\definefont + [MyFont] + [namepart method specification size] +\stoptyping + +For example: + +\starttyping +\definefont + [MyFont] + [Bold*default at 12.3pt] +\stoptyping + +We have already discussed the namepart and size in a previous chapter and here +we will focus on the method. The method is represented by a character and although +we currently only have a few methods there can be many more. + +\stopsection + +\startsection[title=: (direct features)] + +This one is seldom used, but those coming from another macro package to \CONTEXT\ +might use it as first attempt to defining a font. + +\starttyping +\definefont + [MyFont] + [Bold:+kern;+liga; at 12.3pt] +\stoptyping + +This is the \XETEX\ way of defining fonts. A \type {+} means as much as +\quotation {turn on this feature} so you can guess what the minus sign does. +Alternatively you can use a key/value approach with semicolons as separator. If +no value is given the value \type {yes} is assumed. + +\starttyping +\definefont + [MyFont] + [Bold:kern=yes;liga=yes; at 12.3pt] +\stoptyping + +When we started supporting \XETEX\ we ran into issues with already present +features of \CONTEXT\ as the \XETEX\ syntax also has some more obscure properties +using slashes and brackets for signalling a file or name lookup. As in \CONTEXT\ +we prefer a more symbolic approach anyway, it never was a real issue. + +\stopsection + +\startsection[title=* (symbolic features)] + +The most natural way to associate a set of features with a font instance +is the following: + +\starttyping +\definefont + [MyFont] + [Bold*default at 12.3pt] +\stoptyping + +This will use the featureset named \type {default} and this one is defined in +\type {font-pre.mkiv} which might be worth looking at. + +\starttyping +\definefontfeature + [always] + [mode=auto, + script=auto, + kern=yes, + mark=yes, + mkmk=yes, + curs=yes] + +\definefontfeature + [default] + [always] + [liga=yes, + tlig=yes, + trep=yes] % texligatures=yes,texquotes=yes + +\definefontfeature + [smallcaps] + [always] + [smcp=yes, + tlig=yes, + trep=yes] % texligatures=yes,texquotes=yes + +\definefontfeature + [oldstyle] + [always] + [onum=yes, + liga=yes, + tlig=yes, + trep=yes] % texligatures=yes,texquotes=yes + +\definefontfeature % == default unless redefined + [ligatures] + [always] + [liga=yes, + tlig=yes, + trep=yes] + +\definefontfeature % can be used for type1 fonts + [complete] + [always] + [compose=yes, + liga=yes, + tlig=yes, + trep=yes] + +\definefontfeature + [none] + [mode=none, + features=no] +\stoptyping + +These definitions show that you can construct feature sets on top of existing +ones, but keep in mind that they are defined instantly, so any change in the +parent is not reflected in its kids. + +In a font definition you can specify more than one set: + +\starttyping +\definefont + [MyFont] + [Bold*always,oldstyle at 12.3pt] +\stoptyping + +\stopsection + +\startsection[title=@ (virtual features)] + +This method is somewhat special as it demands knowledge of the internals +of the \CONTEXT\ font code. Much of it is still experimental but it is a +nice playground. A good example of its usage can be found in the file +\type {m-punk.mkiv} where we create a font out of \METAPOST\ graphics. + +Another example is virtual math. As in the beginning of \LUATEX\ and \MKIV\ +there were only a few \OPENTYPE\ math fonts, and as I wanted to get rid +of the old mechanisms, it was decided to virtualize the math fonts. For +instance a Latin Modern Roman 10 point math font can be defined as follows: + +\starttyping +\definefontsynonym + [LMMathRoman10-Regular] + [LMMath10-Regular@lmroman10-math] +\stoptyping + +The \type {lmroman10-math} refers to a virtual definition and in this case +it is one using a built|-|in constructor and therefore we use a goodies +file to specify the font. That file looks as follows: + +\starttyping +return { + name = "lm-math", + version = "1.00", + comment = "Goodies that complement latin modern math.", + author = "Hans Hagen", + copyright = "ConTeXt development team", + mathematics = { + ... + virtuals = { + ... + ["lmroman10-math"] = ten, + ... + }, + ... + } +} +\stoptyping + +Here \type {ten} is a previously defined table: + +\startnarrowtyping +local ten = { + { name = "lmroman10-regular.otf", features = "virtualmath", main = true }, + { name = "rm-lmr10.tfm", vector = "tex-mr-missing" } , + { name = "lmmi10.tfm", vector = "tex-mi", skewchar = 0x7F }, + { name = "lmmi10.tfm", vector = "tex-it", skewchar = 0x7F }, + { name = "lmsy10.tfm", vector = "tex-sy", skewchar = 0x30, parameters = true } , + { name = "lmex10.tfm", vector = "tex-ex", extension = true } , + { name = "msam10.tfm", vector = "tex-ma" }, + { name = "msbm10.tfm", vector = "tex-mb" }, + { name = "stmary10.afm", vector = "tex-mc" }, + { name = "lmroman10-bold.otf", vector = "tex-bf" } , + { name = "lmmib10.tfm", vector = "tex-bi", skewchar = 0x7F } , + { name = "lmsans10-regular.otf", vector = "tex-ss", optional = true }, + { name = "lmmono10-regular.otf", vector = "tex-tt", optional = true }, + { name = "eufm10.tfm", vector = "tex-fraktur", optional = true }, + { name = "eufb10.tfm", vector = "tex-fraktur-bold", optional = true }, +} +\stopnarrowtyping + +This says as much as: take \type {lmroman10-regular.otf} as starting point +and overload slots with ones found in the following fonts. The vectors are +predefined as they are shared with other font sets like \type {px} and +\type {tx}. + +In due time more virtual methods might end up in \CONTEXT\ because they are +a convenient way to extend or manipulate fonts. + +\stopsection + +\startsection[title=Lua fonts] + +You can define a font in \LUA. In the process you can use all kind of helper +functions that \CONTEXT\ provides. Here is an example: + +\typefile{fonts-demo-rule.lua} + +This code is stored in \type {fonts-demo-rule.lua} and we can load that font +in the usual way, by specifying a filename: + +\startbuffer +\definefont + [MyRuleFont] + [file:fonts-demo-rule.lua*default sa 1] +\stopbuffer + +\typebuffer + +\getbuffer + +{\MyRuleFont So when we use it we get text typeset where all vowels are replaced +by rules. The actualtext injection (in theory) makes it possible to cut and paste +the text from the \PDF\ document but while writing this (mid 2016) a {\maincolor +\type {mupdf}} based viewer couldn't handle it and {\maincolor \type {acrobat}} +had problems with spaces.} + +\startbuffer +\definefontfeature + [myrulefont] + [default] + [original=file:texgyrepagella-regular.otf] +\definefont + [MyRuleFont] + [file:fonts-demo-rule.lua*myrulefont] +\stopbuffer + +\typebuffer + +\getbuffer + +{\showfontkerns \MyRuleFont The previous code demonstrates how we can pass a +fontname to be used as base to the generator. In case you wonder how features +behave with such fonts: as you can see here, font kerns are indeed injected. +Compared to {\maincolor \type {Dejavu}}, the {\maincolor \type {Pagella}} font +has quite some more kerns.} + +\startbuffer +\definefontfeature + [myrulefont] + [default] + [original=file:texgyrepagella-regular.otf, + option=line] +\definefont + [MyRuleFont] + [file:fonts-demo-rule.lua*myrulefont] +\stopbuffer + +\typebuffer + +\getbuffer + +{\MyRuleFont Here we show how the passed {\maincolor \type {option}} is handled. +Because we no longer have a relationship with the height and depth, the real text +is a bit harder to guess.} + +\stopsection + +\startsection[title=Old fuzzy fonts] + +Most natural is to use \OPENTYPE\ or \TYPEONE\ fonts. In the case of \TYPEONE\ a +matching pair of \type {afm} and \type {pfb} files is needed. However, there can +be situations where there is only a \type{tfm} and \type {pfb} file (or not even +that: just a bitmap file). + +I will not show specimen here, simply because I don't have (nor want to have) the +fonts needed in my development and production environments. The implementation +was tested with a specific czech computer modern font. + +In a traditional (8 bit) setup we have an \type {tfm} file, a \type {pfb} file +and a \type {enc file}. The order of the characters in the \type {tfm} file +directly relates to the input encoding. The \type {enc} file relates that order +to the order in the \type {pfb} file. The mapping from input encoding to font +shape encoding happens via glyph names. In the \type {map} file we tell what +\type {pfb} file to use with what \type {enc} file. + +However, in the case of the \type {csr.tfm} and \type {csr.pfb} file it looks +like in practice the \type {enc} file is not used, probably because in the \type +{pfb} file the standard encoding matches the order in the \type {tfm} file. This +is of course a rather dangerous assumption, especially if information lacks to +check it. + +The next example definitions demonstrate several paths to go from \UNICODE\ input +(source file) to rendered shapes. As this is mostly meant for generic usage we +use the low level definition code (\CONTEXT\ users are not supposed to use that +method). + +\starttyping +\font\foo=file:csr10.tfm:reencode=auto;mode=node;liga=yes;kern=yes +\stoptyping + +This is the easiest way. We use the \type {tfm} file for dimensions, ligatures +and kerns. The \type {auto} option will use the \type {pfb} file to identify the +right mapping. We enable ligatures and kerns and we use node mode. This indicates +that we're dealing with a pseudo \OPENTYPE\ setup here. You can provide a \type +{pfb} file with the \type {pfbfile} feature in case the name differes from the +\type {tfm} file. + +\starttyping +\font\foo=file:csr10.tfm:reencode=csr.enc;mode=node;liga=yes;kern=yes +\stoptyping + +Now we use the \type {enc} file for the encoding vector but we still need the +\type {pfb} file for mapping that onto the right shape. You probably can best use +\type {auto} instead. + +\starttyping +\font\foo=file:csr10.tfm:reencode=csr.enc;bitmap=yes;mode=node;liga=yes;kern=yes +\stoptyping + +Here we force bitmap shapes. This is a bit tricky as a different code path is +followed in the backend. Unless the situation is too confusing, a proper \type +{ToUnicode} is included in the output, so that cut and paste works all right, +given that the viewer is able to deal with it (always use \ACROBAT\ as +reference). + +Why do we need modes and|/|or to simulate \OPENTYPE\ behaviour? Indeed it seldom +makes sense with \type {tfm} files but in this particular case teh font has a +quote cheat. + +\starttyping +\startluacode + fonts.handlers.otf.addfeature { + name = "czechdqcheat", + type = "substitution", + data = { + quotedblright = "csquotedblright", + }, + } +\stopluacode +\stoptyping + +We could make this a language specific feature but as this font is not meant for +other languages it makes no sense to do so. This feature is enabled with: + +\starttyping +czechdqcheat=yes +\stoptyping + +This will replace one quote by another with different side bearings. Of course a +properly bounded quote with proper kerning makes much more sense. A test case is: + +\starttyping +\quotedblleft X\quotedblright +\quotedblright X\quotedblleft +\stoptyping + +\stopsection + +\stopchapter + +\stopcomponent diff --git a/doc/context/sources/general/fonts/fonts/fonts-mkiv.tex b/doc/context/sources/general/fonts/fonts/fonts-mkiv.tex new file mode 100644 index 000000000..43da5870f --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-mkiv.tex @@ -0,0 +1,71 @@ +% language=uk + +% author : Hans Hagen +% copyright : PRAGMA ADE & ConTeXt Development Team +% license : Creative Commons Attribution ShareAlike 4.0 International +% reference : pragma-ade.nl | contextgarden.net | texlive (related) distributions +% origin : the ConTeXt distribution +% +% comment : Because this manual is distributed with TeX distributions it comes with a rather +% liberal license. We try to adapt these documents to upgrades in the (sub)systems +% that they describe. Using parts of the content otherwise can therefore conflict +% with existing functionality and we cannot be held responsible for that. Many of +% the manuals contain characteristic graphics and personal notes or examples that +% make no sense when used out-of-context. + +% \definefontfeature[default][default][globalkern=true] +% +% \usemodule[speedtest] + +\enabletrackers[fonts.files] + +\enablemode[simple] % ,oversized + +\startbuffer[abstract] + + This book is about fonts and how they are dealt with in \CONTEXT\ \MKIV\ and + \LUATEX. Although we use \CONTEXT\ as starting point, much applies to the + generic font handler that ships as part of this macro package. We discuss the + way fonts are dealt with in the engine, font formats, standard features and + additional goodies. Tracing and the extensibility of code are also discussed. + This book is the more technical companion of the regular \CONTEXT\ font + manual. + +\stopbuffer + +\environment fonts-environment + +\startdocument + [author=Hans Hagen, + title=Fonts out of \ConTeXt, + subtitle=explaining luatex and mkiv, + affiliation=PRAGMA ADE, + comment=work in progress, + cover:color:1=darkred, + cover:color:2=darkgreen, + cover:color:3=darkblue, + cover:color:4=darkyellow, + cover:color:5=darkgray] + + \startfrontmatter + \component manuals-explaining-contents + \component fonts-introduction + \stopfrontmatter + + \startbodymatter + \component fonts-formats + \component fonts-modes + \component fonts-lookups + \component fonts-methods + \component fonts-features + \component fonts-scripts + \component fonts-math + \component fonts-extensions + \component fonts-hooks + \stopbodymatter + + \startappendices + \component fonts-appendix + \stopappendices + +\stopdocument diff --git a/doc/context/sources/general/fonts/fonts/fonts-modes.tex b/doc/context/sources/general/fonts/fonts/fonts-modes.tex new file mode 100644 index 000000000..95cb95732 --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-modes.tex @@ -0,0 +1,817 @@ +% language=uk + +\definefontfeature + [otftracker-husayni] + [analyze=yes,mode=node,language=dflt,script=arab, + ccmp=yes,init=yes,medi=yes,fina=yes, + rlig=yes,tlig=yes,anum=yes,calt=yes,salt=yes, + ss01=yes,ss03=yes,ss10=yes,ss12=yes,ss15=yes, + ss16=yes,ss19=yes,ss24=yes,ss25=yes,ss26=yes, + ss27=yes,ss31=yes,ss34=yes,ss35=yes,ss36=yes, + ss37=yes,ss38=yes,ss41=yes,ss42=yes,ss43=yes, + ss60=yes,js16=yes, + kern=yes,curs=yes,mark=yes,mkmk=yes] + +\startbuffer[nodechart:1a] + + \switchtobodyfont[6pt] + + \definecolor[nodechart:glyph][maincolor] + + \hboxtoFLOWchart[dummy]{\definedfont[Normal*none]\language0 test BLAtest} + + \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes] + +\stopbuffer + +\startbuffer[nodechart:1b] + + \switchtobodyfont[6pt] + + \definecolor[nodechart:glyph][maincolor] + + \hboxtoFLOWchart[dummy]{test BLAtest} + + \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes] + +\stopbuffer + +\startbuffer[nodechart:2a] + + \switchtobodyfont[6pt] + + \definecolor[nodechart:glyph][maincolor] + + \hboxtoFLOWchart[dummy]{affiliation} + + \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes] + +\stopbuffer + +\startbuffer[nodechart:2b] + + \switchtobodyfont[6pt] + + \definecolor[nodechart:glyph][maincolor] + + \hboxtoFLOWchart[dummy]{abc\discretionary{d}{e}{f}ghi} + + \FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes] + +\stopbuffer + +\startbuffer[nodechart:2c] + + \switchtobodyfont[6pt] + + \definecolor[nodechart:glyph][maincolor] + + \hboxtoFLOWchart[dummy]{\nl effe fijn fietsen} + + \FLOWchart[dummy][width=12em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes] + +\stopbuffer + +\startbuffer[nodechart:3a] + + \switchtobodyfont[6pt] + + \definecolor[nodechart:glyph][maincolor] + + \hboxtoFLOWchart[dummy]{\tttf\righttoleft فَخَا} + + \FLOWchart[dummy][width=12em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes] + +\stopbuffer + +\startbuffer[nodechart:3b] + + \switchtobodyfont[6pt] + + \definecolor[nodechart:glyph][maincolor] + + \hboxtoFLOWchart[dummy]{{\definedfont[name:husayni*otftracker-husayni at 6pt]\righttoleft فَخَا}} + + \FLOWchart[dummy][width=12em,height=3em,dx=.5em,dy=.75em,offset=1em,hcompact=yes] + +\stopbuffer + +\startcomponent fonts-modes + +\environment fonts-environment + +\startchapter[title=Modes][color=darkgreen] + +\startsection[title=Introduction] + +We use the term modes for classifying the several ways characters are turned into +glyphs. When a font is defined, a set of features can be associated and one of +them is the mode. + +\starttabulate[|l|p|] +\NC none \NC Characters are just mapped onto glyphs and no substitution or + positioning takes place. \NC \NR +\NC base \NC The routines built into the engine are used. For many Latin fonts + this is a rather useable and efficient method. \NC \NR +\NC node \NC Here alternative routines written in \LUA\ are used. This mode is + needed for more complex scripts as well as more advanced features + that demand some analysis. \NC \NR +\NC auto \NC This mode will determine the most suitable mode for the given + feature set. \NC \NR +\stoptabulate + +When we talk about features, we refer to more than only features provided by +fonts as \CONTEXT\ adds some of its own. In the following section each of these +modes is discussed. Before we do so a short introduction to font tables that we +use is given. + +\stopsection + +\startsection[title=The font table] + +The internal representation of a font in \CONTEXT\ is such that we can +conveniently access data that is needed in the mentioned modes. When a font is +used for the first time, or when it has changed, it is read in its most raw form. +After some cleanup and normalization the font gets cached when it is a \TYPEONE\ +or \OPENTYPE\ font. This is done in a rather efficient way. A next time the +cached copy is used. + +The normalized table is shared among instances of a font. This means that when a +font is used at a different scale, or when a different feature set is used, the +font gets loaded only once and its data is shared when possible. In \in {figure} +[fig:tfm-loading] we have visualized the process. Say that you ask for font \type +{whatever} at \type {12pt} using featureset \type {smallcaps}. In low level code +this boils down to: + +\starttyping +\font\MySmallCaps=whatever*smallcaps at 12pt +\stoptyping + +In \CONTEXT\ we have overloaded the font loader so \LUA\ code takes care of the +loading. Basically there is a function hooked into \LUATEX's font definer (the +\type {\font} primitive) that returns a table and from that on \LUATEX\ will +create its internal representation that is identified by a number, the so called +font id. So, in fact the \type {\Whatever} command is a reference to a font id, a +positive number. When this font is already loaded, \CONTEXT\ will reuse the id +and pas that one. + +\startFLOWchart[loading] + \startFLOWcell \name {tfm 1} \location {2,1} \text {raw tfm} \connection [bt]{tfm 2} \stopFLOWcell + \startFLOWcell \name {tfm 2} \location {2,2} \text {normalized tfm} \connection [rl]{tfm 3} \stopFLOWcell + \startFLOWcell \name {tfm 3} \location {4,2} \text {featured tfm} \connection[+rl]{tfm 5a} + \connection [rl]{tfm 5b} + \connection[-rl]{tfm 5c} \stopFLOWcell + + \startFLOWcell \name {tfm 5a} \location {5,1} \text {scaled tfm} \connection[r+t]{tfm} \stopFLOWcell + \startFLOWcell \name {tfm 5b} \location {5,2} \text {scaled tfm} \connection [rt]{tfm} \stopFLOWcell + \startFLOWcell \name {tfm 5c} \location {5,3} \text {scaled tfm} \connection[r-t]{tfm} \stopFLOWcell + + \startFLOWcell \name {afm 1} \location {2,4} \text {raw afm} \connection [bt]{afm 2} \stopFLOWcell + \startFLOWcell \name {afm 2} \location {2,5} \text {normalized afm} \connection [rl]{afm 3} \stopFLOWcell + \startFLOWcell \name {afm 3} \location {3,5} \text {cached afm} \connection[+rl]{afm 4a} + \connection [rl]{afm 4b} \stopFLOWcell + \startFLOWcell \name {afm 4a} \location {4,4} \text {featured afm} \connection [rl]{afm 5a} \stopFLOWcell + \startFLOWcell \name {afm 4b} \location {4,5} \text {featured afm} \connection [rl]{afm 5b} + \connection[-rl]{afm 5c} \stopFLOWcell + \startFLOWcell \name {afm 5a} \location {5,4} \text {scaled afm} \connection[r+l]{tfm} \stopFLOWcell + \startFLOWcell \name {afm 5b} \location {5,5} \text {scaled afm} \connection [rl]{tfm} \stopFLOWcell + \startFLOWcell \name {afm 5c} \location {5,6} \text {scaled afm} \connection[r-l]{tfm} \stopFLOWcell + + \startFLOWcell \name {otf 1} \location {2,7} \text {raw otf} \connection [bt]{otf 2} \stopFLOWcell + \startFLOWcell \name {otf 2} \location {2,8} \text {normalized otf} \connection [rl]{otf 3} \stopFLOWcell + \startFLOWcell \name {otf 3} \location {3,8} \text {cached otf} \connection[+rl]{otf 4a} + \connection [rl]{otf 4b} \stopFLOWcell + \startFLOWcell \name {otf 4a} \location {4,7} \text {featured otf} \connection [rl]{otf 5a} \stopFLOWcell + \startFLOWcell \name {otf 4b} \location {4,8} \text {featured otf} \connection [rl]{otf 5b} + \connection[-rl]{otf 5c} \stopFLOWcell + \startFLOWcell \name {otf 5a} \location {5,7} \text {scaled otf} \connection[r-b]{tfm} \stopFLOWcell + \startFLOWcell \name {otf 5b} \location {5,8} \text {scaled otf} \connection [rb]{tfm} \stopFLOWcell + \startFLOWcell \name {otf 5c} \location {5,9} \text {scaled otf} \connection[r+b]{tfm} \stopFLOWcell + + \startFLOWcell \name {tfm} \location {6,5} \text {engine tfm} \stopFLOWcell +\stopFLOWchart + +\startplacefigure [location=here,reference=fig:tfm-loading,title={Defining a font.}] + \FLOWchart[loading][dx=.75\bodyfontsize,dy=.5\bodyfontsize,width=6\bodyfontsize,offset=0pt,x=2] +\stopplacefigure + +The first step is loading the font (or using the cached copy). From that a copy +is made that has some additional data concerning the features set and from that a +scaled copy is constructed. These copies share as much data as possible to keep +the memory footprint as small as possible. The table that is passed to \LUATEX\ +gets cleaned up afterwards. In practice the \TFM\ loader only kicks in for +creating virtual math fonts. The \AFM\ reader is used for \TYPEONE\ fonts and as +there is no free upgrade path from \TYPEONE\ to \OPENTYPE\ for commercial fonts, +that one will get used for older fonts. Of course most loading is done by the +\OTF\ reader(s). + +\appendixdata{\in[fonts:trackers:tables]} + +The data in the final \TFM\ table is organized in subtables. The biggest ones are +the \type {characters} and \type {descriptions} tables that have information +about each glyph. Later we will see more of that. There are a few additional +tables of which we show two: \type {properties} and \type {parameters}. For the +current font the first one has the following entries: + +\showfontproperties + +The \type {parameters} table has variables that have been (re)assigned in the +process. A period in the key indicates that we are dealing with a subtable, for +instance \type {expansion}. + +\showfontparameters + +To give you an impression of what we are dealing with, the positional features +are shown next: + +\showfontpositionings + +The substitution features of the current font are as follows: + +\showfontsubstitutions + +This is clearly an \OPENTYPE\ font. Normally there are a default +script and default language supported. If this is not the case you +need to provide them as part of the featureset, otherwise there +will be no features applied. + +\stopsection + +\startsection[title=Base mode] + +We talk of base mode processing when the font machinery is used that is built in +\LUATEX. So what does this traditional mechanism provide? + +Before we discuss this, a somewhat simplified model of how \TEX\ works has to be +given. Say that we have the following input: + +\starttyping +\def\bla{BLA} +test \bla test +\stoptyping + +This input gets translated into tokens and those tokens are either processed +later or they become something else directly. Take the first line. Characters in +the input have a so called catcode property that determines how the parser +tokenized them. Effectively we therefore get something like this: + +\starttyping +<command def> +<command bla> +<begingroup> +<character B> +<character L> +<character A> +<endgroup> +\stoptyping + +and finally in the hash table there will be an entry for \type {bla} that has the +meaning \type {BLA} expressed in three characters. + +The second line refers to \type {\bla} and in the process this macro gets +expanded, so we get: + +\starttyping +<character t> +<character e> +<character s> +<character t> +<space> +<character B> +<character L> +<character A> +<character t> +<character e> +<character s> +<character t> +\stoptyping + +Because the parser gobbles spaces after a macro name, there is no space before +the second \type {test}. In practice there will be no intermediate list like +this, because as soon as possible \TEX\ will add something to a so called node +list. When the moment is there, this list will be passed to the typesetting +routine that constructs a horizontal list. Later this list can be converted into +a horizontal box or broken into lines when it concerns a paragraph. + +In traditional \TEX\ characters are stored into char nodes and the builder turns +them into glyph nodes. In \LUATEX\ they start out as glyph nodes and the subtype +number will flag them as glyphs. Any value larger than 255 is a signal that the +list has been processed. The previous example leads to the list shown in \in +{figure} [nodechart:1a]. + +\startplacefigure[title={The text \quote {\typ {test BLAtest}} converted to nodes.},reference=nodechart:1a] + \getbuffer[nodechart:1a] +\stopplacefigure + +Here we have turned off inter|-|character kerning and hyphenation. When we turn +that on, we get a slightly more complex list, as shown in \in {figure} +[nodechart:1b]. Hyphenation points are represented by discretionary nodes and +these have pointers to a pre break, post break and replacement text. + +\startplacefigure[title={The text \quote {\typ {test BLAtest}} converted to nodes, hyphenated and kerned.},reference=nodechart:1b] + \getbuffer[nodechart:1b] +\stopplacefigure + +In addition to hyphenation and kerning we can have ligatures. The list in \in +{figure} [nodechart:2a] shows that we get a reference to a ligature in the glyph +node but that the components are still known. This figure also demonstrates that +the ligature is build in steps. + +\startplacefigure[title={The rendering of the word \quote {\typ {affiliation}}.},reference=nodechart:2a] + \getbuffer[nodechart:2a] +\stopplacefigure + +% \appendixdata{\in[nodes:discretionaries]} + +If we insert an explicit \type {\discretionary} command, we see in +\in {figure} [nodechart:2b] that we get three variants. In \in +{figure} [nodechart:2c] we render some Dutch words and these have +quite some ligatures. + +\startplacefigure[title={The rendering of the bogus word \quote {\typ {abcghi}} with an + explicit discretionary added.},reference=nodechart:2b] + \getbuffer[nodechart:2b] +\stopplacefigure + +\startplacefigure[title={The rendering of the Dutch words \quote { \typ{effe fijn fietsen}}.},reference=nodechart:2c] + \getbuffer[nodechart:2c] +\stopplacefigure + +So, we have hyphenation, ligature building and kerning and to some extent these +mechanisms hook into each other. This process is driven by information stored in +the font and rules related to the language. The hyphenation happens first, so the +builder just sees discretionary nodes and needs to act properly on them. Although +languages play an important role in formatting the text, for the moment we can +forget about that. This leaves the font. + +As we already mentioned in a previous chapter, in \CONTEXT\ we use \UNICODE\ +internally. This also means that fonts are organized this way. By default the +glyph representation of a \UNICODE\ character sits in the same slot in the glyph +table. All additional glyphs, like ligatures or alternates are pushed in the +private unicode space. This is why in the lists shown in the figures the +ligatures have a private \UNICODE\ number. + +The basic mode of operation in the builder in \LUATEX\ is as follows: + +\startitemize[packed] +\startitem hyphenate the node list \stopitem +\startitem build ligatures \stopitem +\startitem inject kerns \stopitem +\startitem optionally break into lines \stopitem +\stopitemize + +In traditional \TEX\ the first step is not that independent. There hyphenation +takes place when the text is broken into lines, and only in places that are +candidate for such a break. In \LUATEX\ the whole text is hyphenated. This has +the advantage that the steps are clearly separated and that no complex +reconstruction and re|-|hyphenation has to take place. The speed penalty can be +neglected and the extra memory overhead is small compared to what is needed +anyway. + +In base mode the raw font data is read in and from that only basic information is +used to construct the \TFM\ table: dimensions, ligatures and kerns. In a node +list, all glyph ranges that refer to such a font get the standard ligature and +kern routines applied, but only if the subtype is still less than 256. This check +on subtype prevents duplicate processing that might happen as a side effect of +for instance unboxing some material in a yet to be typeset text. + +Given that the majority of what \TEX\ has to deal with is relatively simple latin +script, base mode processing is rather convenient and efficient. It is also the +reference point of other kinds of processing. The most simple way to force base +mode is the following: + +\starttyping +\definefontfeature[basemode][mode=base,kern=yes,liga=yes] + +\definefont[MyTitleFont][SerifBold*basemode at 12pt] +\stoptyping + +Here \type {\MyTitleFont} will be a bold serif with ligatures and kerns applied. +However, as an \OPENTYPE\ font can have many features, the following definitions +are also valid: + +\starttyping +\definefontfeature[basemode-o][mode=base,kern=yes,onum=yes,liga=yes] +\definefontfeature[basemode-s][mode=base,kern=yes,smcp=yes] +\stoptyping + +The \TFM\ constructor will filter the right information from the font data and +construct a proper table based on these specifications. But you need to keep in +mind that when for instance old style numerals or small caps are activated, that +their rendering (the glyph) will always be used. So, for instance \type {3} and +\type {A} keep their \UNICODE\ points but as part of their specification they +will get an index pointing to the oldstyle or small caps variant and the +dimensions of that shape will be used. + +\stopsection + +\startsection[title=Node mode] + +Node mode is by far the most interesting of the modes. When enabled we only pass +a few properties of glyphs to the engine: the width, height and depth and +optionally protrusion, expansion factors as well as some extra \CONTEXT\ specific +quantities. So there is no kerning and no ligature building done by the engine. +Instead we do this in \LUA\ by walking over the node list and checking if some +action is needed. + +\appendixdata{\in[fonts:trackers:features]} + +The default feature set enables kerning and ligature building for default and/or +Latin scripts and the default language. Being a relative simple feature, +ligatures don't take much action. Next we show a trace of a ligature replacement. + +\blank +\showotfcomposition{name:dejavuserif*default at 24pt}{1}{affiliation} +\blank + +Be warned that this \type {f f i} sequence not always becomes a ligature. +Actually this is one area where tradition is quite visible: for some reason most +fonts do have these f|-|related ligatures but lack others. These ligatures even +have code points in \UNICODE\ which is quite debatable. Just as there are fonts +with hardly any kerns (like Lucida) there are fonts that follow a different route +to improve the look and feel of neighbouring glyphs, like Cambria: + +\blank +\showotfcomposition{name:cambria*default at 24pt}{1}{affiliation} +\blank + +Instead of representing multiple characters by one glyph the designer has decided +to replace the \type {f} by a slightly narrower one so that the dot of the \type +{i} stays loose. + +An example where much more is involved is the following. The Husayni font that is +used for typesetting Arabic is built upon a solid but complex \OPENTYPE\ +foundation and can only be dealt with in node mode. When the \LUATEX\ project +started we assumed that more power in the engine was needed to accomplish this, +but so far the results with standard \OPENTYPE\ functionality are quite good. +\CONTEXT\ has an additional paragraph optimizer that can apply additional +features to get even better results but discussing this falls beyond this +chapter. A trace of just one Arabic word is much longer than the previously shown +traces. + +\blank +\showotfcomposition{name:husayni*otftracker-husayni at 48pt}{-1}{فَخَا} +\blank + +What we see here is a stepwise substitution process, sometimes based on a +contextual analysis, followed by positioning. The coloring concerns the outcome +of the analysis which in this case flags initial, final, medial and isolated +characters. + +The starting point of this Arabic word is visualized in \in {figure} +[nodechart:3a] and as expected we see no discretionary nodes here. The result as +seen in \in {figure} [nodechart:3b] has (interestingly) no kerns as all +replacements happen via offsets in the glyph node. + +\startplacefigure[title={The Arabic input \quote {\tttf\righttoleft فَخَا} before rendering.},reference=nodechart:3a] + \getbuffer[nodechart:3a] +\stopplacefigure + +\startplacefigure[title={The Arabic input \quote {\tttf\righttoleft فَخَا} after rendering.},reference=nodechart:3b] + \getbuffer[nodechart:3b] +\stopplacefigure + +\stopsection + +\startsection[title=Auto mode] + +Base mode is lean and mean and relatively fast while node mode is more powerful +and slower. So how do you know what to choose? The safest bet is to use node mode +for everything. In \CONTEXT\ however, we also have the so called auto mode. In that +case there is some analysis going on that chooses between base mode and node mode +depending on the boundary conditions of script and language and there are specific +demands in terms of feature processing. So, auto mode will resolve to base or +node mode. + +\stopsection + +\startsection[title=None mode] + +Sometimes no features have to be applied at all. A good example is verbatim. +There you don't want ligatures, kerning or fancy substitutions. Contrary to what +you might expect, monospaced fonts can have such features. Some might actually +make sense, like rendering zeros. However, you cannot assume such a feature to be +present so this is an example of where some more knowledge about a particular +font is needed. This is what Latin Modern provides. + +\starttabulate[|l|l|l|] +\NC \type{none} \NC typewriter \NC \ruledhbox{\maincolor\DemoNoneLT1234567890} \NC \NR +\NC \type{zero} \NC typewriter \NC \ruledhbox{\maincolor\DemoZeroLT1234567890} \NC \NR +\NC \type{none} \NC regular \NC \ruledhbox{\maincolor\DemoNoneLM1234567890} \NC \NR +\NC \type{zero} \NC regular \NC \ruledhbox{\maincolor\DemoZeroLM1234567890} \NC \NR +\stoptabulate + +Normally using mode none for situations that need to be predictable is quite +okay. + +\stopsection + +\startsection[title=Dynamics] + +Sometimes you want to enable or disable a specific feature only for a specific +span of text. Defining a font for only this occasion is overkill, especially when +for instance features are used to fine|-|tune the typography as happens in the +Oriental \TEX\ project, which is related to \LUATEX. Instead of defining yet +another font instance we can therefore enable and disable specific features. For +this it is not needed to know the current font and its size. \footnote {Dynamics +are a \CONTEXT\ specific feature and is not available in the generic version of +the font code. There are several reasons for this: it complicates the code, it +assumes the \CONTEXT\ feature definition mechanism to be used, and it is somewhat +slower as some extra analysis has to be done.} + +Dynamics are a special case of node mode and you don't need to set it up when +defining a font. In fact, a font defined in base mode can also be dynamic. We +show some simple examples of applying dynamic features. + +% First we define two feature sets, one for ligatures and one for oldstyle. As in +% our example we want to start fresh we also define a simple set with only kerning +% enabled. In a next chapter we will see more of how featuresets are defined. +% +% \startbuffer +% \definefontfeature[l][script=latn,liga=yes] +% \definefontfeature[o][script=latn,onum=yes] +% \definefontfeature[k][script=latn,kern=yes] +% +% \definefont[LOKfont][file:lmroman10-regular*k] +% \stopbuffer +% +% \typebuffer \getbuffer + +% \startbuffer[demo] +% {\LOKfont fiets 123 fiets 123 fiets 123}\par +% {\LOKfont fiets 123 \addff{l}fiets 123 \addff{o}fiets 123}\par +% {\LOKfont fiets 123 \addff{o}fiets 123 \addff{l}fiets 123}\par +% {\LOKfont fiets 123 \addfs{l}fiets 123 \addfs{o}fiets 123}\par +% {\LOKfont fiets 123 \addfs{o}fiets 123 \addfs{l}fiets 123}\par +% {\LOKfont fiets 123 \addfs{l}fiets 123 \subfs{l}fiets 123}\par +% {\LOKfont fiets 123 \addfs{o}fiets 123 \subfs{o}fiets 123}\par +% \stopbuffer +% +% We use the following test line: +% +% \typebuffer +% +% In the first line we do nothing but in the following lines we add features to the +% font (replacing existing ones), we add features to the current set (nothing gets +% replaced) and finally we remove some from the set. The typeset result is shown in +% \in {figure} [fig:modes:dynamics]. +% +% \placefigure +% [here] +% [fig:modes:dynamics] +% {Selectively applying ligatures and oldstyle numerals using dynamic features in +% Latin Modern Roman.} +% {\color[maincolor]{\externalfigure[demo.buffer][width=.75\textwidth]}} +% +% Although for reasons of symmetry we have a few more commands, in practice only +% the following make sense, and even the first one is mostly of interest or +% testing. +% +% \starttabulate[|l|l|] +% \NC \type {\addff} \NC set a feature to be the one applied \NC \NR +% \NC \type {\addfs} \NC add a feature to current set \NC \NR +% \NC \type {\subfs} \NC remove a feature from the current set \NC \NR +% \stoptabulate +% +% Keep in mind that the given feature set can set a combination of +% features. Also be aware of the fact that these commands don't +% accumulate: the last one is applied. + +% A more sophisticated dynamic feature mechanism is the following. This +% time we do stack up features. We can add, subtract or even replace +% feature sets. + +Let's first define some feature sets: + +\startbuffer +\definefontfeature[f:smallcaps][smcp=yes] +\definefontfeature[f:nocaps] [smcp=no] +\definefontfeature[f:oldstyle] [onum=yes] +\definefontfeature[f:newstyle] [onum=no] +\stopbuffer + +\typebuffer \getbuffer + +We can add and subtract these features from the current feature set +that is bound to the current font. + +\startbuffer +\switchtobodyfont[pagella] 123 normal +\addfeature {f:oldstyle} 123 oldstyle +\addfeature {f:smallcaps} 123 olstyle smallcaps +\subtractfeature{f:oldstyle} 123 smallcaps +\subtractfeature{f:smallcaps} 123 normal +\stopbuffer + +\typebuffer + +Here we choose a font that has oldstyle numerals as well as small caps: pagella. + +\blank \start \getbuffer \stop \blank + +The following does the same, but only uses addition: + +\startbuffer +\switchtobodyfont[pagella] 123 normal +\addfeature{f:oldstyle} 123 oldstyle +\addfeature{f:smallcaps} 123 olstyle smallcaps +\addfeature{f:newstyle} 123 smallcaps +\addfeature{f:nocaps} 123 normal +\stopbuffer + +\typebuffer + +You can also completely replace a feature set. Of course the set is only +forgotten inside the current group. + +\startbuffer +\switchtobodyfont[pagella] 123 normal +\addfeature {f:oldstyle} 123 oldstyle +\addfeature {f:smallcaps} 123 olstyle smallcaps +\replacefeature{f:oldstyle} 123 oldstyle +\replacefeature{f:smallcaps} 123 smallcaps +\stopbuffer + +\typebuffer + +and now we get: + +\blank \start \getbuffer \stop \blank + +You can exercise some control with \type {\resetfeature}: + +\startbuffer +\switchtobodyfont[pagella] 123 normal +\addfeature [f:oldstyle] 123 oldstyle +\addfeature [f:smallcaps] 123 olstyle smallcaps +\resetfeature 123 reset +\addfeature [f:oldstyle] 123 oldstyle +\addfeature [f:smallcaps] 123 olstyle smallcaps +\stopbuffer + +\typebuffer + +Watch how we use the \type {[]} variant of the commands. The braced and +bracketed variants behave the same. + +\blank \start \getbuffer \stop \blank + +There is also a generic command \type {\feature} that takes two arguments. Below +we show all calls, with long and short variants: + +\starttyping +\addfeature [f:mine] \feature [more][f:mine] \feature[+][f:mine] +\subtractfeature [f:mine] \feature [less][f:mine] \feature[-][f:mine] +\replacefeature [f:mine] \feature [new][f:mine] \feature[=][f:mine] +\resetandaddfeature[f:mine] \feature[local][f:mine] \feature[!][f:mine] +\revivefeature [f:mine] \feature [old][f:mine] \feature[>][f:mine] +\resetfeature \feature[reset] \feature[<] +\stoptyping + +Each variant also accepts \type {{}} instead of \type {[]} so that they can +conveniently be used in square bracket arguments. As a bonus, the following also +works: + +\startbuffer +\switchtobodyfont[pagella] +123 normal +\feature[+][f:smallcaps,f:oldstyle] +123 SmallCaps and OldStyle +\stopbuffer + +\typebuffer + +Here is the proof: + +\blank \start \getbuffer \stop \blank + +\stopsection + +\startsection[title=Discretionaries] + +One of the complications in supporting more complex features is that we can have +discretionary nodes. These are either inserted by the hyphenation engine, or +explicitly by the user (directly or via macros). In most cases we don't need to +bother about this. For instance, more demanding scripts like Arabic don't +hyphenate, languages using the Latin script seldom want ligatures at hyphenation +points (as they can be compound words) and|/|or avoid confusing hyphenation +points, so what is left are specific user inserted discretionaries. Add to that, +that a proper font has not much kerning between lowercase characters and it will +be clear that we can ignore most of this. Anyway, as we explicitly deal with user +discretionaries, the next works out okay. Watch how we normally only have +something special in the replacements text that shows up when no hyphenation is +needed. + +\startbuffer +\language[nl] +\definedfont[file:texgyrepagella-regular.otf*default] +\hsize 1mm vereffenen \par +\hsize 1mm effe \par +\hsize 1mm e\discretionary{f-}{f}{ff}e \par +\hsize 20mm e\discretionary{f-}{f}{ff}e \par +\smallcaps +\hsize 1mm vereffenen \par +\hsize 1mm effe \par +\hsize 1mm e\discretionary{f-}{f}{ff}e \par +\hsize 20mm e\discretionary{f-}{f}{ff}e \par +\stopbuffer + +\typebuffer + +\blank +\startcolumns[n=6] + \indenting[no] + \maincolor + \getbuffer +\stopcolumns +\blank + +In base mode such things are handled by the \TEX\ engine itself and it can deal +with pretty complex cases. In node mode we use a simplification which in practice +suffices. We will come back to this in \in {section} [ligatures:hyphenation]. + +\stopsection + +\startsection[title=Efficiency] + +The efficiency of the mechanisms described here depends on several factors. It +will be clear that the larger the font, the more time it will take to load it. +But what is large? Most \CJK\ fonts are pretty large but also rather simple. A +font like Zapfino on the other hand covers only latin but comes with many +alternative shapes and a large set of rules. The Husayni font focusses on Arabic, +which in itself has not that large an alphabet, but being an advanced script +font, it has a lot of features and definitely a lot of rules. + +In terms of processing it's safe to say that Latin is of average complexity. At +most you will get some substitutions, like regular numerals being replaced by +oldstyles, or ligature building, which involves a bit of analysis, and some +kerning at the end. In base mode the substitutions have no overhead, simply +because the character table already has references to the substituents and the +replacement already takes place when defining the font. There ligature building +and kerning are also fast because of the limited amount of lookups that also are +already kept with the characters. In node mode however, the lists have to be +parsed and tables have to be consulted so even Latin processing has some +overhead: each glyph node is consulted and analyzed (either or not in its +context), often multiple times. However, the code is rather optimized and we use +caching of already analyzed data when possible. + +A \CJK\ script is somewhat more complex on the one hand, but pretty simple on the +other. Instead of font based kerning, we need to prevent or encourage breaks +between certain characters. This information is not in the font and is processed +otherwise but it does cost some time. The font part however is largely idle as +there are no features to be applied. Even better, because the glyphs are large +and the information density is high, the processing time per page is not much +different from Latin. Base mode is good enough for most \CJK. + +The Arabic script is another matter. There we definitely go beyond what base mode +offers so we always end up in node mode. Also, because there is some analysis +involved, quite some substitutions and in the end also positioning, these are the +least efficient fonts in terms of processing time. Of course the fact that we mix +directions also plays a role. If in the Husayni font you enable 30 features with +an average of 5 rules per feature, a 300 character paragraph will take 45.000 +actions. \footnote {For a modern machine this amount is no real issue, but as +each action involves function calls and possibly some garbage collection there +is some price to pay.} When multiple fonts are combined in a paragraph there will +be more sweeps over the list and of course the replacements also have to happen. + +In a time when the average photo camera produces megabyte pictures it makes no +sense to whine about the size of a font file. On the other hand as each font +eventually ends up in memory as a \LUA\ table, it makes sense to optimize that +bit. This is why fonts are converted into a more efficient intermediate table +that is cached on disk. This makes loading a font quite fast and due to shared +tables memory usage rather efficient. Of course a scaled instance has to be +generated too, but that is acceptable. To some extent loading and defining a font +also depends on the way the macro package is set up. + +When comparing \LUATEX\ with for instance \PDFTEX\ or \XETEX\ you need to take +into account that in \CONTEXT\ \MKIV\ we tend to use \OPENTYPE\ fonts only so +there are less fonts loaded than in a more traditional setup. In \CONTEXT\ +startup time of \MKIV\ is less than \MKII\ although overall processing time is +slower, which is due to \UNICODE\ being used and more functionality being +provided. On the other hand, immediate \METAPOST\ processing and more clever +multipass handling wins back time. The impact of fonts on processing time in a +regular document is therefore not that impressive. In practice a \MKIV\ run can +be faster than a \MKII\ run, especially when \METAPOST\ is used. + +In \CONTEXT\ processing of node lists with respect to fonts is only one of the +many manipulations of such lists and by now fonts are not really the bottleneck. +The more not font related features users demand and enable, the less the relative +impact of font processing becomes. + +Also, there are some advanced typographic extras that \LUATEX\ offers, like +protrusion (think of hanging punctuation) and hz optimization (glyph scaling) and +these slow down processing quite a lot, and they are not taking place at the +\LUA\ end at all, but this might change in \MKIV. And, of course, typesetting +involves more than fonts and other aspects can be way more demanding. + +\stopsection + +\stopchapter + +\stopcomponent + +% oldstyle not in math (old school tex) +% funny tex ligatures +% features=yes +% analysis +% mode=none (tt) diff --git a/doc/context/sources/general/fonts/fonts/fonts-scripts.tex b/doc/context/sources/general/fonts/fonts/fonts-scripts.tex new file mode 100644 index 000000000..aed4f0a5c --- /dev/null +++ b/doc/context/sources/general/fonts/fonts/fonts-scripts.tex @@ -0,0 +1,18 @@ +% language=uk + +\startcomponent fonts-scripts + +\environment fonts-environment + +\startchapter[title=Scripts][color=darkmix-6] + +\startsection[title=Introduction] + +As \OPENTYPE\ fonts can provide specific features to deal with scripts and +languages it makes sense to spend some word on this. + +\stopsection + +\stopchapter + +\stopcomponent diff --git a/doc/context/sources/general/fonts/manuals-explaining-contents.tex b/doc/context/sources/general/fonts/manuals-explaining-contents.tex new file mode 100644 index 000000000..3e1fadabc --- /dev/null +++ b/doc/context/sources/general/fonts/manuals-explaining-contents.tex @@ -0,0 +1,11 @@ +% language=uk + +\startcomponent manuals-explaining-contents + + \starttitle[title=Contents][color=darkgray] + + \placelist[chapter][criterium=text] + + \stoptitle + +\stopcomponent diff --git a/doc/context/sources/general/fonts/manuals-explaining-cover.tex b/doc/context/sources/general/fonts/manuals-explaining-cover.tex new file mode 100644 index 000000000..8b4f3e891 --- /dev/null +++ b/doc/context/sources/general/fonts/manuals-explaining-cover.tex @@ -0,0 +1,199 @@ +% language=uk + +% Please try to be original and don't just copy this cover page as I don't want +% confusion and be associated with (or responsibility for the look of) similar +% looking documents. + +\startenvironment manuals-explaining-cover + +\startsetups document:abstract + \framed [ + foregroundstyle=bold, + foregroundcolor=white, + width=7.5cm, + align={normal,tolerant}, + frame=off, + strut=no, + ] { + \getbuffer[abstract] + } +\stopsetups + +\startMPinclusions + + def DrawCoverPage (expr what) = + + numeric variant ; variant := 1 ; + + StartCover ; + + save width, height, size, anchor, offset, colors ; + + numeric width, height, size ; pair anchor, offset ; string colors[] ; + + colors[1] := "\documentvariable{cover:color:1}" ; + colors[2] := "\documentvariable{cover:color:2}" ; + colors[3] := "\documentvariable{cover:color:3}" ; + colors[4] := "\documentvariable{cover:color:4}" ; + colors[5] := "\documentvariable{cover:color:5}" ; + + fill CoverPage enlarged PaperBleed withcolor colors[5] ; + + fill Spine bottomenlarged -.5PaperHeight withcolor colors[3] ; + fill Spine topenlarged -.5PaperHeight withcolor colors[2] ; + + width := FrontPageWidth ; + height := FrontPageHeight ; + size := 4 * width / 3 ; + offset := (-1cm,1cm) ; + anchor := .5[lrcorner CoverPage,urcorner CoverPage] ; + + fill anchored.llft(lltriangle scaled size, urcorner FrontPage) withcolor colors[1] ; + fill anchored.urt (urtriangle scaled size, llcorner FrontPage) withcolor colors[2] ; + fill anchored.lrt (lrtriangle scaled size, ulcorner FrontPage) withcolor colors[3] ; + fill anchored.ulft(ultriangle scaled size, lrcorner FrontPage) withcolor colors[4] ; + + fill anchored.lrt (lrtriangle scaled size, ulcorner BackPage) withcolor colors[1] ; + fill anchored.llft(lltriangle scaled size, urcorner BackPage) withcolor colors[3] ; + fill anchored.ulft(ultriangle scaled size, lrcorner BackPage) withcolor colors[2] ; + fill anchored.urt (urtriangle scaled size, llcorner BackPage) withcolor colors[4] ; + + draw thetextext.llft( + textext("\bf \documentvariable{title}\hskip-.1em") + rotated 45 ysized .350height, + anchor shifted (6*offset+offset) + ) withcolor white ; + draw thetextext.llft( + textext("\bf \documentvariable{subtitle}") + rotated 45 ysized .275height, + anchor shifted (5*offset+offset) + ) withcolor white ; + draw thetextext.llft( + textext("\bf \documentvariable{author}") + rotated 45 ysized .200height, + anchor shifted (2*offset+offset) + ) withcolor white ; + draw thetextext.llft( + textext("\bf \documentvariable{affiliation}") + rotated 45 ysized .200height, + anchor shifted (1*offset+offset) + ) withcolor white ; + + % for the moment + + if (what = "back") or (what = "cover") : + + draw + thetextext.top( + textext("\bf \documentvariable{comment}") + xsized 4cm, + lrcorner Page shifted (-3cm,1cm) + ) withcolor white ; + + fi ; + + % till here + + width := BackPageWidth ; + + if (what = "back") or (what = "cover") : + + draw thetextext( + textext("\bf\setups[document:abstract]") + xsized .65width rotated 45, + center BackPage + ) withcolor white ; + + fi ; + + if what = "cover" : + + draw thetextext.bot( + textext("\bf \documentvariable{title}\hskip-.1em") + rotated 90 xsized .8SpineWidth, + .5[ulcorner Spine,urcorner Spine] shifted (0,-1cm) + ) withcolor white ; + + draw thetextext.top( + textext("\bf \documentvariable{author}") + rotated 90 xsized .8SpineWidth, + .5[llcorner Spine,lrcorner Spine] shifted (0,1cm) + ) withcolor white ; + + fi ; + + StopCover ; + + if what = "front" : + clip currentpicture to FrontPage ; + elseif what = "back" : + clip currentpicture to BackPage ; + else : + drawboundary CoverPage ; + fi ; + + enddef ; + +\stopMPinclusions + +\startsetups document:start + + % \startcovermatter[front] + + \setupbackgrounds[page][background=] + + \doifmodeelse {simple} { + + \startMPpage + DrawCoverPage("front") ; + \stopMPpage + + } { + + \startMPpage + DrawCoverPage("cover") ; + \stopMPpage + + } + + \page[dummy] + + \setupbackgrounds[page][background=page] + + \resetuserpagenumber + + % \stopcovermatter + +\stopsetups + +\startsetups document:stop + + \doifmodeelse {simple} { + + % \startcovermatter[back] + + \page + + \setuppagenumbering[page=] + + \setupbackgrounds[page][background=] + + \page[empty,left] + + \setupmakeup[doublesided=no,page=no] + + \startMPpage + DrawCoverPage("back") ; + \stopMPpage + + % \stopcovermatter + + } { + + % not needed as it's part of the cover page + + } + +\stopsetups + +\stopenvironment diff --git a/doc/context/sources/general/fonts/manuals-explaining-environment.tex b/doc/context/sources/general/fonts/manuals-explaining-environment.tex new file mode 100644 index 000000000..f896c219b --- /dev/null +++ b/doc/context/sources/general/fonts/manuals-explaining-environment.tex @@ -0,0 +1,325 @@ +\startenvironment manuals-explaining-environment + +\usemodule[abr-01] +\usemodule[visual] +\usemodule[simulate] +\usemodule[chart] +\usemodule[nodechart] + +% done + +\dontcomplain + +\definepapersize + [book] + [width=18cm, + height=24cm] + +\setuppapersize + [book] + +\startmode[oversized] + + \setuppapersize + [book] + [oversized] + + \setuplayout + [marking=on] + +\stopmode + +\setuplayout + [location=middle, + topspace=1.5cm, + bottomspace=2cm, + backspace=2cm, + cutspace=2cm, + header=0cm, + footer=0cm, + margindistance=.25cm, + margin=1.25cm, + width=middle, + height=middle] + +\setuplayout + [style=\ss] + +\usetypescript + [dejavu-condensed] + +\setupbodyfont + [ipaex,9pt] + +\setupbodyfont + [dejavu,9pt] + +\definetyping + [narrowtyping] + [typing] + [bodyfont=dejavu-condensed] + +% This is way too ugly for a manual: +% +% \setuptyping +% [indentnext=no] +% +% \setupindenting +% [medium,yes] + +\setupwhitespace + [big] + +\defineoverlay + [page] + [\useMPgraphic{page}] + +\setupbackgrounds + [page] + [background=page] + +\setuphead + [chapter,section,subsection] + [color=\namedstructureuservariable{chapter}{color}] + +\setuphead + [chapter] + [style=\bfc] + +\setuphead + [section] + [style=\bfb] + +\setuphead + [subsection] + [style=\bf, + before=\blank, + after=\blank] + +\startsetups document:chapter:inside + \definecolor[maincolor][1.0(\namedheadparameter{chapter}{color})] % this expands the color + \definecolor[halfcolor][0.5(maincolor,white)] +\stopsetups + +\setuphead + [chapter] + [insidesection=\directsetup{document:chapter:inside}] + +\setuppagenumbering + [alternative=doublesided, + location=] + +\setuplist + [aligntitle=yes] + +\setuplist + [chapter] + [pagenumber=no, + style=bold, + before={\blank\startcolor[\structurelistuservariable{color}]}, + after={\placelist[section]\stopcolor}] + +\setuplist + [chapter,section] + [width=3em] + +\startuseMPgraphic{page} + + StartPage ; + + linecap := butt ; + + if OnRightPage : + + path p ; p := ( + urcorner Page shifted (-2cm,0) -- + urcorner Page -- + urcorner Page shifted (0,-2cm) -- cycle + ) shifted (-2.5mm,-2.5mm) ; + + else : + + path p ; p := ( + ulcorner Page shifted (2cm,0) -- + ulcorner Page -- + ulcorner Page shifted (0,-2cm) -- cycle + ) shifted (2.5mm,-2.5mm) ; + + fi ; + + fill p + withpen pencircle scaled 1mm + withcolor "maincolor" ; + + draw thetextext("\bf\userpagenumber", + if OnRightPage : urcorner p shifted (-5mm,-5mm) else : ulcorner p shifted (5mm,-5mm) fi) + withcolor white ; + + if OnRightPage : + + path p ; p := ( + lrcorner Page shifted (-5cm,0) -- + lrcorner Page + ) shifted (-5mm,10mm) + + else : + + path p ; p := ( + llcorner Page shifted (5cm,0) -- + llcorner Page + ) shifted (5mm,10mm) ; + + fi ; + + draw p + withpen pencircle scaled 1mm + withcolor "maincolor" ; + + draw if OnRightPage : + thetextext.lft("\bf\getspecificstructuretitle{chapter}",lrcorner Page shifted (-5mm,5mm)) + else : + thetextext.rt ("\bf\getspecificstructuretitle{chapter}",llcorner Page shifted ( 5mm,5mm)) + fi withcolor "\namedstructureuservariable{chapter}{color}" ; + + StopPage ; +\stopuseMPgraphic + +\definecolor[orange] [r=1,g=.6,b=.1] + +\definecolor[middlegray] [s=.75] +\definecolor[darkgray] [s=.25] +\definecolor[darkred] [r=.5] +\definecolor[darkgreen] [g=.5] +\definecolor[darkblue] [b=.5] + +\definecolor[darkyellow] [.5(red,green)] +\definecolor[darkmagenta][.5(red,blue)] +\definecolor[darkcyan] [.5(green,blue)] + +\definecolor[darkorange] [.5(orange)] + +\definecolor[maincolor] [darkgray] + +\definecolor [mix-1] [r=1,g=.75,b=.25] \definecolor [darkmix-1][.5(mix-1)] +\definecolor [mix-2] [r=1,g=.25,b=.75] \definecolor [darkmix-2][.5(mix-2)] +\definecolor [mix-3] [r=.75,g=1,b=.25] \definecolor [darkmix-3][.5(mix-3)] +\definecolor [mix-4] [r=.75,g=.25,b=1] \definecolor [darkmix-4][.5(mix-4)] +\definecolor [mix-5] [r=.25,g=1,b=.75] \definecolor [darkmix-5][.5(mix-5)] +\definecolor [mix-6] [r=.25,g=.75,b=1] \definecolor [darkmix-6][.5(mix-6)] + +% \blackrule[height=1cm,width=10cm,color=mix-1] \blackrule[height=1cm,width=10cm,color=darkmix-1] +% \blackrule[height=1cm,width=10cm,color=mix-2] \blackrule[height=1cm,width=10cm,color=darkmix-2] +% \blackrule[height=1cm,width=10cm,color=mix-3] \blackrule[height=1cm,width=10cm,color=darkmix-3] +% \blackrule[height=1cm,width=10cm,color=mix-4] \blackrule[height=1cm,width=10cm,color=darkmix-4] +% \blackrule[height=1cm,width=10cm,color=mix-5] \blackrule[height=1cm,width=10cm,color=darkmix-5] +% \blackrule[height=1cm,width=10cm,color=mix-6] \blackrule[height=1cm,width=10cm,color=darkmix-6] + +% modules + +\setupsorting + [logo] + [style=] + +\setupFLOWchart + [width=6em, + height=3em, + offset=-2em, % maybe default : todo: hoffset and voffset + dx=2em, + dy=2em] + +\setupFLOWlines + [color=maincolor] + +\setupFLOWshapes + [rulecolor=maincolor] + +% tables + +\setuptabulate + [rulethickness=.5mm, + rulecolor=maincolor] + +% special commands + +\startuniqueMPgraphic{reference}{color} + fill + .5[llcorner OverlayBox,ulcorner OverlayBox] -- + .5[ulcorner OverlayBox,urcorner OverlayBox] -- + .5[urcorner OverlayBox,lrcorner OverlayBox] -- + .5[lrcorner OverlayBox,llcorner OverlayBox] -- cycle + withcolor \MPvar{color} ; +\stopuniqueMPgraphic + +\startuniqueMPgraphic{reference}{color} + path p ; p := OverlayBox enlarged -1mm ; + filldraw + ulcorner p -- + urcorner p -- + lrcorner p -- + .5[lrcorner p,llcorner p] shifted (0,-1ExHeight) -- + llcorner p -- cycle + withpen pencircle scaled 1mm + withcolor \MPvar{color} ; + setbounds currentpicture to OverlayBox enlarged 1ExHeight ; +\stopuniqueMPgraphic + +\defineoverlay + [reference] + [\uniqueMPgraphic{reference}{color=maincolor,}] + +\definecolor + [maincolor] + [red] + +\definemargindata + [appendixdata] + %[inner] + [outer] + [stack=yes] + +\definemarginframed + [appendixdata] + [width=3.5em, + height=\lineheight, % we know what goes in there + align=middle, + offset=overlay, + foregroundcolor=white, + background=reference] + +% todo: +% +% \appendixdata[reference=bla]{} +% +% whole data + +% interaction + +\setupinteraction + [state=start, + click=no, + color=, + contrastcolor=, + style=] + +% whatever + +\definestartstop + [notabene] + [before=\blank, + after=\blank, + style=\em] + +\setuphyphenation + [method=default] + + +\startbuffer[underconstruction] +\startnotabene + This document is still under construction. The functionality discussed here + will stay and more might show up. Of course there are errors, and they're all + mine. The text is not checked for spelling errors. Feel free to let me know + what should get added. +\stopnotabene +\stopbuffer + +\stopenvironment |