Palatino Linotype under MKIV

From ConTeXt wiki
Revision as of 16:04, 30 June 2010 by Schickele (talk | contribs) (New page: This page shows you how to use most of the typographical features of the Palatino Linotype font shipped with Windows XP under ConTeXt / LuaTeX a.k.a. MKIV, and particularly how to get the ...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This page shows you how to use most of the typographical features of the Palatino Linotype font shipped with Windows XP under ConTeXt / LuaTeX a.k.a. MKIV, and particularly how to get the small cap "i" issue patched. All credits for the lua patch and the detailed explanations go to Taco Hoekwater.

Note that the Palatino version (5.00) provided by Windows Vista and Windows 7 differs from the Windows XP one (version 1.40).

The following code has been tested with ConTeXt 2010.06.23 / LuaTeX 0.60.1 on Win XP. (Schickele 16:02, 30 June 2010 (UTC))

Example file

The following example file should give you a ready-to-use solution to take advantage of the typographical possibilities of Palatino Linotype under ConTeXt / MKIV. Of course, the four Palatino font shapes, called pala.ttf, palai.ttf, palab.ttf and palabi.ttf, must be installed on your computer. On a normal XP machine, they are stored in the system font folder (C:\Windows\Fonts).

\startluacode
function palapatch (data,filename)
     if data.version == "1.40" then
        logs.report("load otf", "patching smallcaps i")
        data.glyphs[0x92].lookups["ss_latn_l_14_s"][1].specification.variant="a.scturkish"
        data.glyphs[0x492].name = "a.scturkish"
     end
end

fonts.otf.enhancers.patches["^pala"] = palapatch
\stopluacode

\definefontfeature[palatinolt-default][script=latn,kern=yes,liga=yes,trep=yes,tlig=yes,protrusion=quality]
\definefontfeature[palatinolt-smcp][script=latn,kern=yes,liga=yes,trep=yes,tlig=yes,protrusion=quality,smcp=yes,onum=yes]
\definefontfeature[palatinolt-sups][mode=node,script=latn,kern=yes,liga=yes,trep=yes,tlig=yes,protrusion=quality,sups=yes]

\starttypescript[serif][palatinolt][name]
\usetypescript[serif][fallback]
\definefontsynonym[Serif][file:pala.ttf][features=palatinolt-default]
\definefontsynonym[SerifBold][file:palab.ttf][features=palatinolt-default]
\definefontsynonym[SerifItalic][file:palai.ttf][features=palatinolt-default]
\definefontsynonym[SerifBoldItalic][file:palabi.ttf][features=palatinolt-default]
\definefontsynonym[SerifCaps][file:pala.ttf][features=palatinolt-smcp]
\definefontsynonym[SerifSlanted][file:pala.ttf][features=palatinolt-sups]
\stoptypescript

\definetypeface[PalatinoLinotype][rm][serif][palatinolt][default]

\setupbodyfont[PalatinoLinotype]
\setupbodyfontenvironment[default][em=italic]
\setuppagenumbering[location=]
\enableprotruding

\defineparagraphs[TwoColumns][n=2,align=hanging]
\setupparagraphs[TwoColumns][1][width=52pt,style=\em,align=left]

\starttext

\startbuffer[Plato]
How you, O Athenians, have been affected by my accusers, I cannot tell;
but I know that they almost made me forget who I was--so persuasively
did they speak; and yet they have hardly uttered a word of truth.
\stopbuffer

\startTwoColumns
Roman\TwoColumns
\getbuffer[Plato]
\stopTwoColumns

\startTwoColumns
Italic\TwoColumns
{\em\getbuffer[Plato]}
\stopTwoColumns

\startTwoColumns
Bold\TwoColumns
{\bf\getbuffer[Plato]}
\stopTwoColumns

\startTwoColumns
Bold italic\TwoColumns
{\bi\getbuffer[Plato]}
\stopTwoColumns

\startTwoColumns
Small caps\TwoColumns
{\sc\getbuffer[Plato]}
\stopTwoColumns

\startTwoColumns
Old greek\TwoColumns
Ὅτι μὲν ὑμεῖς, ὦ ἄνδρες Ἀθηναῖοι, 
πεπόνθατε ὑπὸ τῶν ἐμῶν κατηγόρων, 
οὐκ οἶδα· ἐγὼ δ' οὖν καὶ αὐτὸς ὑπ' 
αὐτῶν ὀλίγου ἐμαυτοῦ ἐπελαθόμην, 
οὕτω πιθανῶς ἔλεγον. 

\stopTwoColumns

Old style figures \& superior characters: 567890 / {\sc 567890} --- 1{\sl 1} o{\sl o} re{\sl re}

\stoptext

Palatino linotype under mkiv.png

In this example, the \sl command gives superior characters. Protrusion is enabled, but not expansion (hz). This first lines (\startluacode ... \stopluacode) are the patch written by Taco to get the small cap dottless "i" work properly under LuaTeX. Without patch, activating the small cap lookup (smcp=yes) leads to dotted small cap "i" characters. The following section explains how the patch works.

LuaTeX glyph renaming patch from Taco Hoekwater

This section explains how the patch used in the above example file works. Both patch and explanations have been written by Taco Hoekwater. His original answer, including an attached test file, can be found [here].

To fix the [wrong small cap dotted i] problem nicely, we have to rename one of the two glyphs.

This could be done in an external editor, but as this is a system font, that may not be wise or even possible. Luckily, context allows to do this using a patching system that is active during initial font loading time (when the cache is generated).

In the following, we will be patching the generated cache file before it is saved (by putting some lua code at the beginning of your test file). Remember that you have to delete the generated cache files after each iteration. In my case, they were /opt/tex/texmf- cache/luatex-cache/context/c24894930eb65eadf7b71f1e305ff518/fonts/otf/pala.tm*. If you forget to do this step in between runs, nothing will change in the output!

The existing font patches are in font-pat.lua, and from that file it is possible to deduce that something like this is the correct program structure, theoretically:

\startluacode
function palapatch (data,filename)
    -- to be filled in
end
fonts.otf.enhancers.patches["^pala"] = palapatch
\stopluacode

The two arguments to the patch function are the data table from the luafontloader and the font file name, respectively. The function should patch the data table to our liking and does not have to return anything.

In order to have a good look at the data, the first thing to do is to dump the data to a file. Put this code at the top of your test file, delete the data cache files, and run:

\startluacode
function palapatch (data,filename)
   io.savedata(filename .. '.lua', table.serialize(data))
end

fonts.otf.enhancers.patches["^pala"] = palapatch
\stopluacode

\definefontfeature [...]

Afterwards, open pala.ttf.lua (or pala.TTF.lua. not sure how this works out on an actual XP install) in an editor for browsing.

Looking at the lua code in pala.ttf.lua, you will see that there is a pretty large sub-array called 'glyphs', which happens to be indexed by glyph id. There are two entries in that sub-array called 'i.sc' and we will want to change the second of those to 'i.scturkish' (the one at 0x492, the number we discovered above).

Change the lua code to the code below, save your test file, delete the data cache again, and rerun.

\startluacode
function palapatch (data,filename)
      data.glyphs[0x492].name = "a.scturkish"
end

fonts.otf.enhancers.patches["^pala"] = palapatch
\stopluacode

That's one problem fixed. If you look at the test's pdf, it will now have dotless i's in the smallcaps. But now we have broken the turkish smallcaps code (it will now also use the first i.sc, which is wrong) so it is nice to fix that as well. Some searching back and forth through the pala.ttf.lua code reveals that there are two lookups that use i.sc: ss_latn_l_13_s (for normal latin) and ss_latn_l_14_s (for turkish). These lookups are part of the glyph definition of 'i' which lives at 0x92 (I found that number in the earlier font dump, but you could also count the entries in pala.ttf.lua, if you are bored or like counting stuff).

Named lookups are small arrays (you can deduce that from the double braces in pala.ttf.lua), so the needed patch is:

data.glyphs[0x92].lookups["ss_latn_l_14_s"][1].specification.variant="a.scturkish"

And that will fix the turkish lookup. Now, I want to make sure we only run this code for palatino version 1.40 (it should be obvious why), and it is nice to do a terminal message as well. (note: testing for just the font version ignores the fact that different vendors may use the same font name for different fonts, but that is a complication that I think can be ignored in this particular case).

The end result is:

\startluacode
function palapatch (data,filename)
      if data.version == "1.40" then
         logs.report("load otf", "patching smallcaps i")
 
data.glyphs[0x92].lookups["ss_latn_l_14_s"][1].specification.variant="a.scturkish"
         data.glyphs[0x492].name = "a.scturkish"
      end
end

fonts.otf.enhancers.patches["^palatino"] = palapatch
\stopluacode