domenica 22 gennaio 2012

ConTeXt and Fonts, Part 1

In my opinion, font handling has been -- and still is -- one of the trickiest part of my TeX experience. With font handling I don't mean using the fonts provided by a particular TeX installation; on the contrary, I mean installing and using new typefaces into TeX -- and ConTeXt. Nowadays things are way easier: both XeTeX and LuaTeX provide simple font interfacing and intuitive OTF feature leveraging. ConTeXth can use these engines too, with LuaTeX becoming the default engine for ConTeXt.

So why stick with pdfTeX? The main reason is that changing typeset engine leads to slightly different outputs in most cases, and plain wrong output in some cases. The most blatant gotcha is, in my humble opinion, when we typeset a document in two columns and want to lay out a float spreading the whole page width. If we use pdfTeX or XeTeX as typesetting engines we can use \startcolumns..\stopcolumns and place a floating object on the top of a page; if we use LuaTeX, we must use columnsets or we just can't do it. Moreover, while XeTeX is far easier to use (I used it to typeset some long documents) allows for inferior typographic control. This leaves me with only one choice: ConTeXt + pdfTeX, with its complex font handling mechanism.


Some starting notes

To install -- and use -- fonts in ConTeXt, we must first install them in (pdf)TeX. There is a fairly complete walkthrough about the joyful process of installing truetype fonts in a TeX system. I advise you to read it, even if you -- like me -- know little about the intricacies of TeX. It might be boring, but in the end, you will know more about font handling in plain tex.

When you're done reading this tutorial, you will surely be more than happy to learn that the fine folks at Pragma-ADE, the home of ConTeXt, have created texfont, an utility that eases you the pain of installing Truetype and Type1 fonts in a TeX system. This utility should work also for Open Type fonts, but as it is, it is buggy, since it can't install correctly OTF files. Don't worry, tho': since it is a Perl script I think I've corrected the bug (that is, it works on my machine, a Win7/x64 notebook with Strawberry Perl 5.12.3 installed... YMMV) and I'll have the corrected script available for your consumption.

Let's go back to font installation, then. Let's say we have downloaded some fine truetype fonts from here or there and want to use it. The correct approach would be this:

  1. Download the families you need
  2. Unzip and place each family in its own directory
  3. Install each family in a subdirectory scheme resembling this: /[vendor]/[family]/[font file]

While there's nothing wrong with this approach (infact, it reduces map file loading times) I prefer installing lots of
fonts in a single collection. Following the example above, I'd install all downloaded fonts under a single vendor directory and under a single collection name. This approach leads to slightly higher load times, but -- imho -- helps you reduce clutter in your TeX directory.

So, let's say you have unpacked all your truetype files in a single directory. You would then launch a DOS shell, go to the path where you have copied your font files and launch this command:


texfont --vendor=[vendorname] --collection=[collectionname] --encoding=[encodingname] --ma --install

Let's elaborate upon vendorname, collectionname and encodingname

    vendorname is the name of your font provider (monotype, google, etc.) collectionname is a unique name that identifies your font collection. It might be the font family's name if you're installing a single font family; you can use any name you like if you install more than one family in a single pass. encoding: this is how TeX encodes your character input to get the desired output. ec and texnansi are good starting values, with the first being the default choice, while the second being a complete encoding suitable for most languages.

The --ma parameter means that texfont creates appropriate subdirectories to store font files for TeX consumption, while the --install parameter means that fonts get installed into TeX system (we can choose to install fonts in a subdirectory of choice and copy this folder upon TeX's font folder later). With an eye to our sample fonts, a good command line would look like this:

texfont --vendor=google --collection=downloadedfonts --encoding=texnansi --ma --install

After launching this command you will see a lot of system messages, telling you the results of font installation process.

A real example

Let's say I have downloaded some families families from Google Fonts and want to install them in my ConTeXt environment. For this example, I will use the following families

  • Neuton, good all-round serif font
  • Volkhov, another good serif font
  • Vollkorn, another serif font whose boldfaces make good title fonts
  • Lato, a versatile sans serif face
  • Rammetto One Regular, a heavy sans serif typeface useful for headlines

I should end up with 25 truetype files, all stored in a single directory. Once I'm set, I open a command shell, navigate to the path containing my font files and launch the following command:

texfont --vendor=google --collection=myfonts --ma --install

After some time, lots of processing and lots of messages we should end up with a message like this:

updating map file : texnansi-google-myfonts.map (for pdftex)
     updating map file : texnansi-google-myfonts.map (for dvipdfm)
     updating map file : texnansi-google-myfonts.map (for dvips)

            generating : ls-r databases

mktexlsr: Updating c:/tex/share/texmf-local/ls-R...
mktexlsr: Updated c:/tex/share/texmf-local/ls-R.
mktexlsr: Done.

The texnansi-google-myfonts.map (note the encoding-vendor-collection naming scheme) contains the information we need to start referencing font files in our ConTeXt environment. The .map file is a text file we must open to get physical font names and wrap them into some logical containers. But where is this font?

If we launch the command kpsewhich texnansi-google-myfonts.map we should get the whole path to our map file. On my system kpsewhich yields the following result:

c:/tex/share/texmf-local/fonts/map/pdftex/context/texnansi-google-myfonts.map

Let's open it and we'll find a text like this:

% This file is generated by the TeXFont Perl script.
%
% You need to add the following line to your file:
%
%   \pdfmapfile{+texnansi-google-myfonts.map}
%
% In ConTeXt you can best use:
%   \loadmapfile[texnansi-google-myfonts.map]


texnansi-raw-Lato-Black Unknown 4 < Lato-Black.ttf texnansi.enc
texnansi-raw-Lato-BlackItalic Unknown 4 < Lato-BlackItalic.ttf texnansi.enc
texnansi-raw-Lato-Bold Unknown 4 < Lato-Bold.ttf texnansi.enc
texnansi-raw-Lato-BoldItalic Unknown 4 < Lato-BoldItalic.ttf texnansi.enc
texnansi-raw-Lato-Hairline Unknown 4 < Lato-Hairline.ttf texnansi.enc
texnansi-raw-Lato-HairlineItalic Unknown 4 < Lato-HairlineItalic.ttf texnansi.enc
texnansi-raw-Lato-Italic Unknown 4 < Lato-Italic.ttf texnansi.enc
texnansi-raw-Lato-Light Unknown 4 < Lato-Light.ttf texnansi.enc
texnansi-raw-Lato-LightItalic Unknown 4 < Lato-LightItalic.ttf texnansi.enc
texnansi-raw-Lato-Regular Unknown 4 < Lato-Regular.ttf texnansi.enc
texnansi-raw-Neuton-Bold Unknown 4 < Neuton-Bold.ttf texnansi.enc
texnansi-raw-Neuton-ExtraBold Unknown 4 < Neuton-ExtraBold.ttf texnansi.enc
texnansi-raw-Neuton-ExtraLight Unknown 4 < Neuton-ExtraLight.ttf texnansi.enc
texnansi-raw-Neuton-Italic Unknown 4 < Neuton-Italic.ttf texnansi.enc
texnansi-raw-Neuton-Light Unknown 4 < Neuton-Light.ttf texnansi.enc
texnansi-raw-Neuton-Regular Unknown 4 < Neuton-Regular.ttf texnansi.enc
texnansi-raw-NeutonCursive-Regular Unknown 4 < NeutonCursive-Regular.ttf texnansi.enc
texnansi-raw-RammettoOne-Regular Unknown 4 < RammettoOne-Regular.ttf texnansi.enc
texnansi-raw-Volkhov-Bold Unknown 4 < Volkhov-Bold.ttf texnansi.enc
texnansi-raw-Volkhov-BoldItalic Unknown 4 < Volkhov-BoldItalic.ttf texnansi.enc
texnansi-raw-Volkhov-Italic Unknown 4 < Volkhov-Italic.ttf texnansi.enc
texnansi-raw-Volkhov-Regular Unknown 4 < Volkhov-Regular.ttf texnansi.enc
texnansi-raw-Vollkorn-Bold Unknown 4 < Vollkorn-Bold.ttf texnansi.enc
texnansi-raw-Vollkorn-BoldItalic Unknown 4 < Vollkorn-BoldItalic.ttf texnansi.enc
texnansi-raw-Vollkorn-Italic Unknown 4 < Vollkorn-Italic.ttf texnansi.enc

Lines starting with % are comments and are ignored by ConTeXt. What we need is the physical font name. We can make this out this way:

  1. Let's examine this line: texnansi-raw-Lato-Black Unknown 4 < Lato-Black.ttf texnansi.enc. It's made of some "words". The first of them is the following: texnansi-raw-Lato-Black.
  2. Now let's remove "-raw" from the aforementioned word. We are left with texnansi-Lato-Black. This is the physical font name of Lato Black typeface, encoded using texnansi encoding.
  3. I can use this information by defining a \font command. Look at the sample document below:
% load map file containing font mapping we need
\loadmapfile[texnansi-google-myfonts.map]

% define two font synonyms
\font\NeutonBold texnansi-Neuton-Bold at 18pt
\font\LatoBlack texnansi-Lato-Black at 66pt

\starttext

{\LatoBlack Title }

{\NeutonBold hold your fire, young grasshopper fi flat}

\stoptext

We compile it usint texexec and we should be greeted by a PDF displaying a title typeset using Lato Black, and a line of text using Neuton Bold. Yay!

However, this method is quite cumbersome. For instance, it is extremely font-dependent. If we distribute our tex document to someone who hasn't installed our fonts, ConTeXt won't compile it. Moreover, for every font at every size used in our document, we will have to define a synonym. Is there a more comprehensive way to encapsulate fonts?

Rejoice, for there is such a way. And it will be the topic of the next post.

Nessun commento:

Posta un commento