From 9d7c4ba8449bec1da920c01e24a17c41bbf2211d Mon Sep 17 00:00:00 2001 From: Context Git Mirror Bot Date: Mon, 25 Jul 2016 22:53:51 +0200 Subject: 2016-07-25 21:54:00 --- doc/context/documents/general/fonts/fonts-mkiv.pdf | Bin 0 -> 1256587 bytes doc/context/documents/general/mathml/mmlexamp.pdf | Bin 0 -> 136092 bytes doc/context/documents/general/mathml/mmlprime.pdf | Bin 0 -> 772848 bytes .../sources/general/fonts/fonts/fonts-appendix.tex | 484 ++ .../general/fonts/fonts/fonts-environment.tex | 30 + .../general/fonts/fonts/fonts-extensions.tex | 2312 ++++++++ .../sources/general/fonts/fonts/fonts-features.tex | 2585 +++++++++ .../sources/general/fonts/fonts/fonts-formats.tex | 873 +++ .../sources/general/fonts/fonts/fonts-hooks.tex | 585 ++ .../general/fonts/fonts/fonts-introduction.tex | 95 + .../sources/general/fonts/fonts/fonts-lookups.tex | 347 ++ .../sources/general/fonts/fonts/fonts-math.tex | 998 ++++ .../sources/general/fonts/fonts/fonts-methods.tex | 376 ++ .../sources/general/fonts/fonts/fonts-mkiv.tex | 71 + .../sources/general/fonts/fonts/fonts-modes.tex | 817 +++ .../sources/general/fonts/fonts/fonts-scripts.tex | 18 + .../general/fonts/manuals-explaining-contents.tex | 11 + .../general/fonts/manuals-explaining-cover.tex | 199 + .../fonts/manuals-explaining-environment.tex | 325 ++ .../sources/general/mathml/mathml/envexamp.tex | 291 + .../sources/general/mathml/mathml/mmlexamp.tex | 107 + .../sources/general/mathml/mathml/mmlprime.tex | 6036 ++++++++++++++++++++ .../sources/general/mathml/mathml/pc-d-001.xml | 9 + .../sources/general/mathml/mathml/pc-d-002.xml | 9 + .../sources/general/mathml/mathml/pc-d-003.xml | 18 + .../sources/general/mathml/mathml/pc-d-004.xml | 26 + .../sources/general/mathml/mathml/pc-d-005.xml | 27 + .../sources/general/mathml/mathml/pc-d-006.xml | 38 + .../sources/general/mathml/mathml/pc-d-007.xml | 58 + .../sources/general/mathml/mathml/pc-d-008.xml | 25 + .../sources/general/mathml/mathml/pc-d-009.xml | 25 + .../sources/general/mathml/mathml/pc-d-010.xml | 26 + .../sources/general/mathml/mathml/pc-d-011.xml | 32 + .../sources/general/mathml/mathml/pc-d-043.xml | 47 + .../sources/general/mathml/mathml/pc-d-051.xml | 17 + .../sources/general/mathml/mathml/pc-i-022.xml | 52 + .../sources/general/mathml/mathml/pc-i-380.xml | 73 + .../sources/general/mathml/mathml/pc-s-001.xml | 28 + .../sources/general/mathml/mathml/pc-s-002.xml | 36 + .../sources/general/mathml/mathml/pc-s-003.xml | 40 + .../sources/general/mathml/mathml/wh-g-001.xml | 28 + .../sources/general/mathml/mathml/wh-g-002.xml | 28 + .../sources/general/mathml/mathml/wh-g-003.xml | 28 + .../sources/general/mathml/mathml/wh-g-004.xml | 28 + .../sources/general/mathml/mathml/wh-g-005.xml | 31 + .../sources/general/mathml/mathml/wh-g-006.xml | 31 + .../sources/general/mathml/mathml/wh-g-007.xml | 33 + .../sources/general/mathml/mathml/wh-g-008.xml | 33 + .../sources/general/mathml/mathml/wh-g-009.xml | 33 + .../sources/general/mathml/mathml/wh-g-010.xml | 35 + .../sources/general/mathml/mathml/wh-g-011.xml | 27 + .../sources/general/mathml/mathml/wh-g-012.xml | 27 + .../sources/general/mathml/mathml/wh-g-013.xml | 27 + .../sources/general/mathml/mathml/wh-g-014.xml | 29 + .../sources/general/mathml/mathml/wh-g-015.xml | 32 + .../sources/general/mathml/mathml/wh-g-016.xml | 90 + .../sources/general/mathml/mathml/wh-l-001.xml | 35 + .../sources/general/mathml/mathml/wh-l-002.xml | 35 + .../sources/general/mathml/mathml/wh-l-003.xml | 32 + .../sources/general/mathml/mathml/wh-l-004.xml | 28 + .../sources/general/mathml/mathml/wh-s-001.xml | 49 + .../sources/general/mathml/mathml/wh-s-002.xml | 63 + 62 files changed, 17928 insertions(+) create mode 100644 doc/context/documents/general/fonts/fonts-mkiv.pdf create mode 100644 doc/context/documents/general/mathml/mmlexamp.pdf create mode 100644 doc/context/documents/general/mathml/mmlprime.pdf create mode 100644 doc/context/sources/general/fonts/fonts/fonts-appendix.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-environment.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-extensions.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-features.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-formats.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-hooks.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-introduction.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-lookups.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-math.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-methods.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-mkiv.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-modes.tex create mode 100644 doc/context/sources/general/fonts/fonts/fonts-scripts.tex create mode 100644 doc/context/sources/general/fonts/manuals-explaining-contents.tex create mode 100644 doc/context/sources/general/fonts/manuals-explaining-cover.tex create mode 100644 doc/context/sources/general/fonts/manuals-explaining-environment.tex create mode 100644 doc/context/sources/general/mathml/mathml/envexamp.tex create mode 100644 doc/context/sources/general/mathml/mathml/mmlexamp.tex create mode 100644 doc/context/sources/general/mathml/mathml/mmlprime.tex create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-001.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-002.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-003.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-004.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-005.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-006.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-007.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-008.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-009.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-010.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-011.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-043.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-d-051.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-i-022.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-i-380.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-s-001.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-s-002.xml create mode 100644 doc/context/sources/general/mathml/mathml/pc-s-003.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-001.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-002.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-003.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-004.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-005.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-006.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-007.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-008.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-009.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-010.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-011.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-012.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-013.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-014.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-015.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-g-016.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-l-001.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-l-002.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-l-003.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-l-004.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-s-001.xml create mode 100644 doc/context/sources/general/mathml/mathml/wh-s-002.xml (limited to 'doc') diff --git a/doc/context/documents/general/fonts/fonts-mkiv.pdf b/doc/context/documents/general/fonts/fonts-mkiv.pdf new file mode 100644 index 000000000..4cc8b07e6 Binary files /dev/null and b/doc/context/documents/general/fonts/fonts-mkiv.pdf differ diff --git a/doc/context/documents/general/mathml/mmlexamp.pdf b/doc/context/documents/general/mathml/mmlexamp.pdf new file mode 100644 index 000000000..d86238a5a Binary files /dev/null and b/doc/context/documents/general/mathml/mmlexamp.pdf differ diff --git a/doc/context/documents/general/mathml/mmlprime.pdf b/doc/context/documents/general/mathml/mmlprime.pdf new file mode 100644 index 000000000..0d48394c0 Binary files /dev/null and b/doc/context/documents/general/mathml/mmlprime.pdf differ 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" 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 = { + [