The Apple Tool Suite

This document is copyright © 2002 by Apple Computer, Inc. All rights reserved. Table of Contents

Table of Contents...... i

Introduction...... v

Installing the tools...... vi

Words of warning ...... vi

Using the tools ...... vi ftxanalyzer ...... 1

Typical uses for ftxanalyzer ...... 3 ftxdiff ...... 5 ftxdumperfuser ...... 7 ftxenhancer ...... 11 ftxinstalledfonts...... 13 ftxruler ...... 15 ftxvalidator...... 19

How to Use Add Lists ...... 23

Introduction ...... 23

Creating an Add List...... 23

The first line ...... 23

The component line(s) ...... 24

Some examples...... 26

Roman numerals ...... 27

Accented ...... 27

More extreme examples ...... 28

About Morph Input Files...... 29

Introduction ...... 29 i A Quick Review of AAT Metamorphosis Effects...... 29

A First Example...... 30

Some general MIF rules...... 31

MIF Format—Headers...... 32

MIF Format—Noncontextual ...... 33

MIF Format— List ...... 33

MIF Format—State Tables ...... 34

The class list...... 34

The state array ...... 35

The action list...... 35

MIF Format—Contextual ...... 36

Another example...... 37

MIF Format—Insertion...... 39

MIF Format—Rearrangement ...... 40

Using Justification Input Files ...... 41

Introduction ...... 41

How AAT Justification Works...... 41

The Factor Phase ...... 42

The Assignment Phase ...... 42

The Postcomp Phase...... 43

The Justification Class...... 43

Overall JIF Format ...... 43

The Header ...... 44

The “Factors” table part...... 45

The “Classes” table part ...... 45

ii The “Postcomp” table part ...... 46

Ligature Decomposition actions ...... 47

Unconditional Add actions...... 47

Conditional Add actions...... 47

Stretch actions...... 48

Ductility actions...... 48

Some Examples...... 49

Simple Latin, no intercharacter spacing...... 49

Adding intercharacter spacing ...... 50

iii

Introduction

Apple’s font tool suite consists of the following tools:

• ftxanalyzer • ftxdiff • ftxdumperfuser • ftxenhancer • ftxinstalledfonts • ftxruler • ftxvalidator

The tools require that the following framework be installed as well:

• FTX.framework

These tools encompass most of the key functionality of our older font tools and considerable new functionality. We hope to be able to provide fuller functionality as time progresses.

Unlike our older tools, the new tools are all command-line tools. This means that one typically runs them from within the Terminal application and not by double-clicking on them. There are a number of advantages to this:

1) Command-line utilities are faster to launch and run.

2) Command-line utilities can have options specified when they’re launched, rather than by manipulating menus after launch.

3) Command-line utilities can be executed from within scripts.

Suppose, for example, that I want to examine the ‘cmap’ table of a font called MyFont, which is found in the file MyFont.suit in my Documents folder. I would do the following after launching Terminal: cd ~/Documents ftxdumperfuser -t cmap -pu -A d MyFont.suit

When done, a file named MyFont.cmap.xml will be in my Documents folder, which I can then examine and edit.

As the file’s name implies, the new font tool suite, as much as possible, uses XML as a document format. This, too, has advantages:

1) XML files are text-based and can be edited by a large number of existing applications. They can be checked into source repositories such as CVS.

2) XML files have well-defined mechanisms for such things as representing non-ASCII text v (needed in the ‘name’ table), comments, and so on.

3) Using XML allows us to coordinate with other people on producing standard file types and formats for font-related data.

4) XML file can be edited and examined using widely-available, standard tools. Installing the tools

Install the tools by double-clicking the installer package; this will launch the Apple Installer. You must authenticate as an admin user in order to run the Installer.

The package will automatically install the tools in /usr/bin and the framework in /Library/Frameworks. You can move the framework to ~/Library/Frameworks afterwards if you prefer. The package also installs man pages in the /usr/share/man/man1 and /usr/share/man/man3 so that you can get instant information on the various tools while you’re in Terminal. Words of warning

These tools are currently a work in progress, and a byproduct of our own font development efforts. We are making them available to font developers outside Apple in hopes that they will be useful, but Apple makes no promise or representation that these tools are suitable for any particular purpose. These tools are not intended as polished, commercial software. Be sure to back up any or data before using them in conjunction with these tools.

It should also be noted that the XML formats used by the tools are not stable. Apple is working with other vendors to provide a uniform XML format for font data. As time progresses, we will bring our XML formats more closely into alignment with the XML schema, which is currently itself a work in progress. Using the tools

The following sections discuss the individual tools one-by-one.

Note, first, that in general all the tools have an -h option, a -v option, and a -V option. The -h option gives a brief summary of the tool’s parameters, which is also displayed if the tool is executed without any arguments. The -v option puts the tool into “verbose” mode, which provides diagnostic data and can help track down problems. Verbose mode can be very verbose, however, so be warned. -V gives the tool’s current version and, for the more recently- revised tools, the version of the Font Toolbox framework as well.

In general, we try to keep command-line options consistent across tools, but we don’t always succeed.

vi ftxanalyzer Replaces: AAT Font Tool, UniMIFfer ftxanalyzer is used to analyze the content of a font and generate various files based on that content. Unlike ftxenhancer, it won’t do anything to the font itself. Rather, it will generate text files which other tools can use after a human being has had a chance to review them.

The analysis is based on two things, so you should make sure they’re as accurate as possible before you run this tool: the various cmaps in the ‘cmap’ table, and the names in the ‘post’ table.

These are the files ftxanalyzer can generate: -g An “add” file -x An “add” file (in XML)

This is a list of new glyphs that the tool determines the font needs. These new glyphs come in three categories, one of which is optional and only present if the -M option is used: glyphs needed for mirroring, glyphs needed for Unicode decomposition, and (the optional category) glyphs needed for round-trip compatibility with the Mac scripts contained in the font.

The Unicode standard designates a number of characters as being mirrored, meaning that in a right-to-left context they should reverse their shapes. The parentheses are examples of mirrored glyphs. In left-to-right text, the opening parenthesis looks like ( and the closing parenthesis like ). In right-to-left text, such as for Arabic or Hebrew, the opening parenthesis looks like ) and the closing one like (. Most of these mirrored characters come in pairs in Unicode, but not all do. The integral sign is a mirrored character that doesn’t come in pairs. In left-to-right text, the integral sign looks like ∫ and it’s supposed to be the other way around for right-to-left text.

For mirrored glyphs like the parentheses that come in pairs in Unicode, ftxanalyzer looks for mirrored glyphs based on the Unicode code points. If it sees a glyph for U+0028, it looks for a glyph for U+0029 and adds an entry to the “add” file if there isn’t one. For mirrored glyphs like the integral sign, it looks for a glyph whose name is the name of the original character with “_mirror” added at the end. If the glyph for ∫ is called “integral”, it looks for one named “integral_mirror” and generates an entry in the “add” file if it’s missing.

Because of a limitation in the ‘prop’ table format, it's necessary for mirrored glyphs to be physically located near their counterparts. ftxanalyzer therefore includes in the add file a “_clone” glyph to be added to a font whenever a “_mirror” glyph needs to be added.

If every character in a Macintosh script corresponded to precisely one Unicode character, there would be no need for the third kind of “add” file entry. Unfortunately, this is not true. The MacHebrew character 0xA8, for example, maps to the Unicode sequence . If you use the -M option, ftxanalyzer will run through the Macintosh cmap entries

1 in the font. It will check the sequence of Unicode characters produced by each character in each entry and make sure that all the Unicode characters involved are, in fact, present in the Unicode cmap.

The -l option is used in conjunction with the -M option to limit this analysis to the Macintosh scripts corresponding to the font’s ‘FOND’ resource. If the font has a MacHebrew ‘FOND’ but also has, say, a MacIcelandic cmap, you can skip the analysis of the MacIcelandic cmap using the -l option. -j A “JIF”

“JIF” stands for “justification input file.” This can be used by ftxenhancer to produce a ‘just’ (justification) table for the font. It is based on the font’s glyph names. -m A “MIF”

“MIF” stands for “metamorphosis input file.” This can be used by ftxenhancer to add a ‘morx’ (extended metamorphosis) table to a font. The default MIF ftxanalyzer generates contains the following:

A list of the precomposed Unicode characters and their alternate representations using combining characters

Linguistically required actions. There are many languages for which nothing is generated yet. -p A ‘post’ table source

This file contains Apple’s recommend PostScript names for the glyphs in the font in a format which can be fused into the font using ftxdumperfuser. -P A ‘prop’ table source

This file contains default properties for the glyphs in the font in a format that can be fused into the font using ftxdumperfuser. -s A sample document

This is a plain UTF-16 file that can be opened by TextEdit or another Unicode-savvy text editor. It’s used in proofing the font. The output file provides a multi-column display. The left- most column is a precomposed Unicode character. The next column is the same character made out of the combining Unicode characters that can be used to generate it. The third column is the same as the second with zero-width spaces inserted between every character to force them to split up. Finally comes a comment indicating what one should see.

If all has gone well, the first and second columns will look the same. -u A Unicode document

2 This is a plain UTF-16 file that can be opened by TextEdit or another Unicode-savvy editor. It’s used in proofing the font. The output file contains a grid with all the Unicode characters in the font. You can use the grid to determine if any characters look incorrect.

Note that since the grid has seventeen columns (one for the first Unicode code point in the row, and the remaining sixteen for whatever characters should be contained there), the rows can get rather wide. -U Universal MIF

This has ftxanalyzer include in the default MIF generated by the –m option the so-called universal or “magic” MIF. This is a list of all the standard actions which a font may desire to have by defalt. The universal MIF data can be very large. ftxanalyzer uses the -f option to select a single font within a font suitcase. If you have the file MyFont.suit with faces MyFont and MyFont Bold, you’ll have to specify a face using the -f option. If you need to use the -f option but don’t, the tool will tell you and list the fonts between which you must choose. Typical uses for ftxanalyzer

There are two main uses for ftxanalyzer. The first is making sure that the font’s glyph repertoire is sufficiently fleshed out. This is done with the -x and -g options. (They produce pretty much the same output, but in wildly different formats, and only the format from the -g option can currently be used with ftxenhancer.)

The results of these options can be used to add new glyphs to the font, either with ftxenhancer or with the original font-drawing application.

Once the glyph repertoire is settled, the other options can be used to generate a default MIF and JIF and default ‘cmap’, ‘post’, and ‘prop’ table data.

Finally, you can use the -s and -u options to make sure that everything is OK and that the Unicode support you want your font to have is actually there.

For example, if you want a list of the characters your font needs and plan to add them via ftxenhancer, you would do: ftxanalyzer -g MyFont.add MyFont.ttf

If you plan to go back to Fontographer or FontLab and add the new glyphs (which is the recommended course of action), you’ll need to know the Unicode code points. This is provided by the XML add list: ftxanalyzer -x MyFont.add.xml MyFont.ttf

The second main use for ftxanalyzer is to generate the default morph table support for Unicode shaping behavior. The default MIF can be generated via:

3 ftxanalyzer -m MyFont.mif MyFont.ttf

Warning. The default MIF contains a large set of possible Unicode behaviors. ftxenhancer will ignore what it can’t use, but it can make the MIF large and hard to read. You may want to prune this part yourself—you’ll know it by the fact that it refers to characters by Unicode code point, and not glyph name.

Default JIF and ‘prop’ data are really only needed for fonts that contain bidirectional scripts, particularly Arabic. This portion of the tool is currently still in prototype form, and you should thoroughly examine any proposed JIF before adding it to your font.

You can also generate a default ‘Zapf’ (character reference) table using the -z option. The output can then be fused into the font using ftxdumperfuser. This table is used by the Character Palette to present alternatives for a selected character.

4 ftxdiff ftxdiff is straightforward to use, since it has relatively few options. It simply compares the contents of two versions of a font, one against the other. The command line ftxdiff -o MyFontDiff.txt MyNewFont.suit MyOldFont.suit will go through all the fonts in MyNewFont.suit, try to find a matching font in MyOldFont.suit, and do a table-by-table comparison between the two. ftxdiff will always inform you of cases where a table has been added, deleted, or changed. If the table has been added or deleted, it won’t summarize the table’s contents. If the table has been changed, it will always report the fact. For more common tables (‘cmap’, ‘name’) it will also do an analysis of the table and print out the relevant changes.

The ‘morx’ and ‘mort’ tables are complex enough that ftxdiff won’t list all the changes made in those tables. In the case of other tables, the changes listed should be limited to things that make a difference in the final font. That is, if a particular ‘cmap’ subtable has changed from format 4 to format 6 without altering the actual mappings between characters and glyphs, ftxdiff will report that the table has changed but not report any mapping changes.

Where ftxdiff doesn’t know anything about the internals of a font table, it will simply produce a binary dump of the table and its changed counterpart, marking places where changes have been made.

If you want to restrict the comparison to a single font within a suitcase, use the -f option, as for ftxanalyzer.

5

ftxdumperfuser Replaces: DumperFuser; TypeWriter, most of the various dumpers and fusers

This is the workhorse of the font tool suite. It allows individual font tables to be dumped to or read from an XML file. The XML description of the data format (DTD for each dump format is included in the dump. Currently, ftxdumperfuser uses a custom format internal to Apple. We are in active collaboration with other tool-makers, however, and hope to release a version in the near future which uses a cross-platform XML schema.

The -g command-line option can be used to force ftxdumperfuser to use a generic format which is a straight hex dump of the table’s contents. This format is also used for tables of which ftxdumperfuser has no specialized knowledge. ftxdumperfuser has complete knowledge of the following tables:

• ‘cmap’ (character code mapping); this includes full support for all of Unicode using Unicode scalar values • ‘feat’ (layout feature) • ‘hdmx’ (horizontal device metrics) • ‘head’ (font header) • ‘hhea’ (horizontal header) • ‘hmtx’ (horizontal metrics) • ‘loca’ (glyph location) • ‘maxp’ (maximum profile) • ‘name’ (name) • ‘OS/2’ (compatibility) • ‘post’ (glyph name and PostScript compatibility) • ‘prop’ (glyph properties) • ‘vhea’ (vertical header) • ‘vmtx’ (vertical metrics) • ‘Zapf’ (glyph reference)

It has partial knowledge of the following tables:

• ‘glyf’ (glyph outlines) • ‘just’ (justification) • ‘morx’ (extended metamorphosis)

In the case of the ‘glyf’ table, ftxdumperfuser simply dumps each individual glyph’s data as raw hexadecimal. Its main use is to copy and paste data for a particular glyph (including hints) between different versions of the same font.

For both the ‘just’ and ‘morx’ tables, ftxdumperfuser’s current format is aimed not at modifying the tables, but at diagnosing simple problems within them.

7 Future versions of ftxdumperfuser will add support for more tables and extend support for the ‘glyf’, ‘just’, and ‘morx’ to full round-tripping. ftxdumperfuser has a lot of options. We won’t go over them in detail, but rather describe their typical uses. Note that ftxdumperfuser has the standard -h, -v, and -V options, and uses the -f option as does ftxanalyzer, to specify the font to work on within a font suitcase. Use 1: List the tables in a font:

Use the -l option. ftxdumperfuser -l MyFont.ttf Use 2: Delete a table from a font:

Use the -t (table) and -k options: ftxdumperfuser -t addg -k MyFont.ttf Use 3: Dump a table:

There are two ways to do this. The easier is to use the -A d option, which tells ftxdumperfuser to dump the table from every font in the font file and auto-generate a name based on the font’s name. ftxdumperfuser -t cmap -A d MyFont.suit will generate files called MyFont.cmap.xml and MyFont Bold.cmap.xml, assuming that MyFont and MyFont Bold are the two faces in the suitcase. This option is really handy, too, if you’re simply too lazy to supply your own file names.

Otherwise, you use the -o option, which tells ftxdumperfuser the name of the file to which to dump. Note that if you use -o for a font suitcase with more than one font in it, you must also use the -f option to specify which one: ftxdumperfuser -t cmap -f MyFont -o MyFileName.cmap.xml MyFont.suit

If you do use the -o option, we think it may be convenient for your file names to use the same naming convention as the autogenerated ones; but that’s up to you, of course.

If you don’t provide either the -A or -o options, dump output is sent to stdout; it can be redirected, or piped to another command. Use 4: Fuse data into a font

This can also be used to add a table to a font that didn’t have the table previously.

As with dumping, there are two ways. You can use the autogenerated file names with -A f:

8 ftxdumperfuser -t cmap -A f MyFont.suit

Or you can supply your own file name with the -d option: ftxdumperfuser -t cmap -f MyFont -d MyFileName.cmap.xml MyFont.suit

As for the other options in the tool, the most important are:

-p and -G

These have to do with glyph names. Whenever a glyph ID is referenced in a table, the DTD uses the glyphRefID attribute to refer to it. This is always a required attribute, and so must be present when fusing back in.

The -p option tells ftxdumperfuser to also include the (implied) glyphName attribute. For example, a ‘cmap’ dump without the -p option may include the line:

whereas with the -p option it will have:

When fusing in a file, ftxdumperfuser requires the glyphRefID attribute. If the glyphName attribute is also present, the tool will check that they both refer to the same glyph and issue a warning if they don’t. In such a case, it will use the glyphRefID in the actual fusing operation, unless the -G option is being used. In this case, it will give the glyphName precedence over the glyphRefID.

To reuse our example, if we had the line

in our source, but the glyph with the name “colon” was glyph number 35, and glyph 345 had the name “kolon”, then without the -G option, ftxdumperfuser would assign character 0x003A to glyph 345 (named “kolon”) and with the -G option it would assign it to glyph 35 (named “colon”); in either case, it would issue a warning.

If you use the -G option and don’t want these warnings all the time, set the glyphRefID to -1.

-u

This tells ftxdumperfuser to output the Unicode name for a character when dumping cmaps. The Unicode name is always ignored on fuse; it’s a rather cumbersome way to refer to characters, but handy for reference purposes. Using the -p and -u options, we would get:

9

ftxenhancer Replaces: AAT Font Tool

This tool is used to add some of the specialized tables generated by ftxanalyzer to a font. The main uses are to add a JIF to a font, add new glyphs using an add file, and add a morx table using a MIF. (Note that ftxenhancer does not support the ‘mort’ table. The only reason to use a ‘mort’ and not a ‘morx’ would be for ATSUI-savvy applications running on Mac OS 9. There are few enough of those that we are not continuing to support ‘mort’ tables in our tools. You can use the OS 9-based AAT Font Tool to add a ‘mort’ table to a font.)

The -A option uses an add file to add new glyphs to a font

The -j option uses a JIF to add a ‘just’ table

The -m option uses a MIF to add a ‘morx’ and ‘feat’ table

The only other important option is -l, which forces the tool to use the smallest possible lookup tables within a ‘morx’. This makes for smaller tables but tables that may execute more slowly. At the same time, there is a bug currently in the ‘morx’ handling code that may produce unexpected results if the -l option is not used.

Our recommendation is currently to use the -l option at all times when generating a ‘morx’ table.

We also recommend double-checking the ‘feat’ table generated by ftxenhancer just in case something went wrong.

The -v option with ftxenhancer is extremely verbose. It does help catch problems with MIF input, however.

11

ftxinstalledfonts

This tool simply lists the fonts installed in your system. The various options let you specify the font’s PostScript names, unique names, full names, version (release names), and the location where the font is installed. It also has a -U option so you can find fonts that cover a particular Unicode character (or claim to in their cmap). E.g. to find the version of a font installed: ftxinstalledfonts -frl | grep MyFont may return something like: 14 8381 MyFont 1.0 /Library/Fonts/MyFont.suit 15 8382 MyFont Bold 1.0 /Library/Fonts/MyFont.suit

The first column is the font’s index in the list of installed fonts. The second is the system ID used with ATSUI and the Font Manager when referring to the font. The third is the font’s full name (per the -f option); then the font’s version (release) name (per the -r option), and finally the font’s location (per the -l option). We used grep to limit the list to those fonts whose name contains the word “MyFont”. Something like: ftxinstalledfonts -f -U 4E95 | grep YES will list all the fonts in your system covering the Unicode character U+4E95.

The -U option uses Unicode scalar values and supports characters outside Plane 0. Thus you could find a font that supports the Deseret Alphabet by using: ftxinstalledfonts -f -U 10400 | grep YES

The -q option returns the Quickdraw (i.e. FOND) names of the fonts. Note that some fonts without a FOND resource (e.g. raw sfnt files such as Myfont.ttf) will simply return “ERROR” on this option. The example below saves a text file containing the quickdraw names and their paths. ftxinstalledfonts -ql -o QDfontlist.txt may return something like: 101 8299 Gill Sans /Library/Fonts/GillSans.dfont 102 8300 Gill Sans-Bold /Library/Fonts/GillSans.dfont

The order of the listing is alphabetic within system storage location, so the list may not be entirely alphabetically arranged, but be split up into sub-sorts of fonts alphabetized within each of their storage locations. Where multiple font copies are installed in different locations, the following order of precedence applies (zero is highest priority):

0. [Application specific font directories] (Application) 1. ~/Library/Fonts (User) 2. /Library/Fonts (Local) 3. /Network/Library/Fonts (Network) 4. /System/Library/Fonts (System) 5. [Classic System Folder]/Fonts (Classic)

13

ftxruler Replaces: FontRuler ftxruler provides a text dump of the metrics actually returned by the system in real life. This tool is useful for comparing different versions of the same font to make sure changes won’t cause document reflow. ftxruler takes a single parameter, the input file, which is a text file containing commands to be executed. It works on installed fonts – not font files.

Lines beginning with “%” are considered comment lines and are skipped.

Lines beginning with “#” are considered command lines and change something. Commands must all be followed by a colon and are case-sensitive. For example: # Font: Geneva …on a line switches the font to Geneva.

Multiple commands can be included in the file to change the settings at any stage. Tabs and spaces are ignored within a command line. i.e. ”# Font:” is treated the same as ”#Font:”

Recognized commands are:

Font: The font name to use for subsequent text. The default font is the system’s application font (Helvetica on OSX). The fontnames recognized are the Quickdraw names. Use ftxinstalledfonts -q -o QDfontlist.txt to get the list of active fonts on your system.

Size: The size to use for subsequent text. The default point size is the system’s application font size (12 point on OSX).

Style: The styles to use for subsequent text. The style is set using the following all-lowercase strings: [“bold”, “italic”, “underline”, “outline”, “shadow”, “condense”, “extend”]. The default style is plain which is an empty string. Multiple styles can be set by combining style strings separated by a blank character. E.g. “bold italic”.

As always in typesetting, there are two ways to select some styles: either choose the family name and set the style; or leave the style plain and choose the face directly. E.g. Lucida Grande; Style = bold vs Lucida Grande-Bold; Style = “” (plain). Confirm the effect of your setting by inspection of the data output.

In the output file, the style setting is given as both a numeric and a verbal value. The numeric values are standard Mac style codes which are integer numbers. Plain = 0; Bold = 1; Italic = 2; Underline = 4; Outline = 8; Shadow = 16; Condensed = 32; Extended = 64. The default style is plain (0). Multiple styles are represented by adding style codes together. E.g. Bold Italic = 3.

Width: Where to break the line as a decimal number in points. The default column width is 612 points (8.5 inches = US Letter page width). Use a large value (e.g. 32000) to avoid linewrap.

15 Tag: An ID string passed directly to output so parsing apps can relate the output of the tool back to the input.

FractEnable: Sets quickdraw option for sub-pixel/fractional metrics. Use "True" and "False" string values. Default is off (“False”)

OutlinePreferred: Sets quickdraw option to prefer outlines to bitmaps. Use "True" and "False" string values. Default is off (“False”)

All other non-empty lines which aren’t comments or commands are treated as input lines and rendered using the current settings and wrapped to fit within the column width as necessary.

Note that the End Of Line (EOL) delimiter used is the Unix LineFeed (LF). Without this the input file will not be processed. To create LF delimited text, use OSX’s TextEdit, or BBEdit with “Unix linebreak” option set in the file’s attributes (it is ‘Mac’ by default). Also watch out for the “Translate Linebreaks” checkbox in the open dialog so you don’t convert your input files back to Carraige Return (CR) delimiters when updating them.

The output file is filled with information blocks about each input line. If wrapping has occurred, then each sub-string of the input line is output with its own data block.

The goal is to run the same text input file on two different systems or with two different versions of the same font. A standard comparison tool can then be used to compare the output files.

To profile specific behaviours of the font or API (e.g. To identify irregularities in lineheight or string widths across different pointsizes or to check stringlength variation across styles), more structured input files can be created and automatically parsed using the Tag ID fields.

Sample input file: LGAlphabetTestIP.txt

% Demo of a ftxruler input file % Create Date: Sep 4, 2002 % Author: PGL

#Font: Lucida Grande #Size: 10 #Width: 150

#Style: bold #Tag: LINE00000 Lucida Grande 10 point alphabet length test

#Style: bold italic #Tag: LINE00001 Lucida Grande 10 point alphabet length test

#Style: #Width: 32000 #Tag: LINE00002 abcdefghijklmnopqrstuvwxyz

16 #Tag: LINE00003 ABCDEFGHIJKLMNOPQRSTUVWXYZ

#Tag: LINE00004 = std digit string 0123456789

#Tag: LINE00005 = ascii symbols !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

#Tag: LINE00006 A

#Tag: LINE00007 B

#Tag: LINE00008 C

Executing the above sample input file thus: ftxruler -v -o LGAlphabetTestOP.txt LGAlphabetTestIP.txt

Produces output of the following form:

Taking input from "LGAlphabetTestIP.txt" ############################################################################ File: LGAlphabetTestIP.txt Entering ProcessFile() gSavePort == 0x00077F70, gSaveWorld = 0x000B3084 NewGWorld() == 0 Entering ProcessData() Line 5 == "#Font: Lucida Grande" Switching to font "Lucida Grande" (QD ID 1024) Line 6 == "#Size: 10" Line 7 == "#Width: 150" Line 9 == "#Style: bold" Line 10 == "#Tag: LINE00000" Next input line: "Lucida Grande 10 point alphabet length test" Tag: LINE00000 Fract enabled: F Outline preferred: F Font: Lucida Grande (ID 1024) Point size: 10 Style: 1 bold Line width: 150 Break code: 0 Input line number: 11 Starting position on line: 0 Bytes on line: 23 Text width: 125 yMax: 8 yMin: -2 yDelta: 10 Font QD ascent: 10 Font QD descent: 2 QD Leading: 0 Total QD height: 12

17 Text on line: "Lucida Grande 10 point "

Tag: LINE00000 Fract enabled: F Outline preferred: F Font: Lucida Grande (ID 1024) Point size: 10 Style: 1 bold Line width: 150 Break code: 2 Input line number: 11 Starting position on line: 23 Bytes on line: 20 Text width: 106 yMax: 8 yMin: -2 yDelta: 10 Font QD ascent: 10 Font QD descent: 2 QD Leading: 0 Total QD height: 12 Text on line: "alphabet length test"

Line 13 == "#Style: bold italic" Line 14 == "#Tag: LINE00001" Next input line: "Lucida Grande 10 point alphabet length test" Tag: LINE00001 Fract enabled: F Outline preferred: F Font: Lucida Grande (ID 1024) Point size: 10 Style: 3 bold italic Line width: 150 Break code: 0 Input line number: 15 Starting position on line: 0 Bytes on line: 23 Text width: 125 yMax: 8 yMin: -2 yDelta: 10 Font QD ascent: 10 Font QD descent: 2 QD Leading: 0 Total QD height: 12 Text on line: "Lucida Grande 10 point "

Tag: LINE00001 Fract enabled: F Outline preferred: F Font: Lucida Grande (ID 1024) Point size: 10 Style: 3 bold italic Line width: 150 Break code: 2 . . . etc.

18 ftxvalidator Replaces: FontValidator ftxvalidator inspects the given font file(s) for errors. You can control which font tables are examined by using the -t (-table) or -t! (-table!) options. You can also control how extensive the report is by using the -r (-report) or -r! (-report!) options.

A list of options and their descriptions follows. -r

Use this option to limit what is included in the report. ftxvalidator can report errors, warnings, notices, or general information. These are represented by the letters e, w, n, and i, respectively, as options to the -r option. Thus, to report only errors, you would use ‘-r e’. To report both errors and notices, you would use ‘-r en’.

-report

The same as -r -r!

This is the reverse of the -r option; it reports everything except the specified category.

-r! i is the same as

-r ewn in that errors, warnings, and notices are reported, but general information is not. -report! is the same as r! -t

Use this option to test only a particular table. This is handy if you want only one or two tables tested and not the entire font. -table is the same as -t -t!

19 This is the reverse of the -t option; it tests all but the specified tables. -table!

The same as t!

These are the tables and font data that can be tested with ftxvalidator

• ‘FOND’ Not a font table, but a resource found in Mac OS font suitcases. It’s used for QuickDraw applications. • ‘avar’ The axis variation table. • ‘bdat’ The bitmap data table. • ‘bhed’ The bitmap font header table. • ‘bloc’ The bitmap location table. • ‘bsln’ The baseline table. • ‘cmap’ The character code mapping table. • ‘cvar’ The CVT variation table. • ‘fdsc’ The font descriptor table. • ‘feat’ The layout feature table. • ‘fmtx’ The font metrics table. • ‘fpgm’ The font program table. • ‘fvar’ The font variation table. • ‘glyf’ The TrueType glyph outline table. • ‘gvar’ The glyph variation table. • ‘hdmx’ The horizontal device metrics table. • ‘head’ The font header table. • ‘hhea’ The horizontal header table. • ‘hmtx’ The horizontal metrics table. • ‘just’ The justification table. • ‘kern’ The kerning table. • ‘lcar’ The ligature caret table. • ‘loca’ The glyph location table. • ‘mort’ The metamorphosis table. • ‘name’ The name table. • ‘opbd’ The optical bounds table. • ‘OS/2’ The compatibility table. • ‘post’ The glyph name and PostScript compatibility table. • ‘prep’ The control value program table. • ‘prop’ The properties table. • ‘trak’ The tracking table. • ‘vhea’ The vertical header table. • ‘Zapf’ The glyph reference table.

Thus, to find all the errors in your ‘cmap’ table, you would type: ftxvalidator -r e -t cmap MyFont.ttf ftxvalidator lists all the possible errors in a font if no reporting options or tables are specified

20 For example: ftxvalidator MyFont.ttf will tell ftxvalidator to examine all the tables in the font and report all the possible errors found.

21

How to Use Add Lists Introduction

This document describes the format of an add list, which is a plain text file you can provide to ftxenhancer to add new glyphs to a font. The glyphs you add are composites made up of glyphs which already exist in the font; which glyphs those are and where they are placed relative to each other is up to you. Once ftxenhancer is finished adding the glyphs, it will also add the tables needed to access those glyphs (assuming they aren’t just immediately keyboard accessible), but note that the resulting font can also be used in a non-AAT system, and the glyphs will still be there. You might want to use ftxdumperfuser to edit the new font, since it lets you add entries to existing ‘cmap’ tables (or add new ‘cmap’ tables), which is necessary to access your new glyphs. Creating an Add List

To create an add list you can use any word processor which allows you to save as plain text, or use a text editor such as TextEdit or BBEdit. You can also use ftxanalyzer to generate an add list. Each new glyph you wish to add to the font is represented by several lines in the text file; each of these lines comprises several tab-delimited fields and is terminated with a carriage return. There are several examples of complete add lists in the examples section of this document. The first line

The first line of an add list entry contains information about the new glyph you’re adding. The first field on this line is the PostScript® name of the new glyph. If you want ftxenhancer to include the new glyph in the morph tables it builds, you should choose a name from the list of names ftxenhancer recognizes; however, you may also add glyphs which aren’t on that list. See http://developer.apple.com/fonts/DataFiles/PostScriptNames.txt for exact names you can use.

The next field on the first line is the count of the number of component glyphs making up this new glyph.

After the count, one or several optional flags may appear on the first line, separated by spaces. These flags are defined as follows:

Use Cluster Advance (“-C”)

The “-C” flag tells ftxenhancer to use the accumulated width for all of the component pieces in determining the advance width of this new glyph. This is not the default case, which is why you have to specify it. The default is to just use the advance width of the first component. This is the usual case for the “baseform plus accent” combination, where you want the width of the new glyph to be the same as the width of the baseform.

23 Zero Sidebearings (“-Z”)

The “-Z” flag tells ftxenhancer to zero the sidebearings of the new glyph; you will not usually specify this for Roman fonts.

Force Advance Width (“-W glyph”)

The “-W” flag tells ftxenhancer to copy the advance width of another glyph for this new glyph being added. The glyph specified after the “-W” can be either a numerical glyph index or a valid name. The component line(s)

After the first line comes one or more lines, one per component glyph making up this new glyph. We’ll call these the “component lines.” The first component line is sometimes referred to as the “baseform line” since it is usually (though not always) the main component, the piece which “anchors” the whole new glyph.

The first field on a component line is either a glyph index or else a PostScript name. In order to use the name, you should make sure the font has a real ‘post’ table, which is to say a ‘post’ table in a format other than 3. If the font has a format 3 ‘post’ table, you can tell ftxenhancer to build a real ‘post’ table by providing a name list, which is just a plain text file naming all the glyphs in the font, one name per line. You can also use ftxdumperfuser to create a ‘post’ table.

The next two fields are the delta-X and delta-Y values. The baseform line will usually have zeroes for these values, though it need not do so. These are signed values, and are expressed in font units. Note, however, that certain flags (see below) can change the interpretation of one or both of these delta values. In the absence of any flags, these deltas are relative to the natural origin of the component. Thus, if you specified several components with zero deltas and no flags, the new composite glyph would have the glyphs overlaid on top of each other, aligning them on their origins.

After the delta-X and delta-Y values, several different flags may appear. These flags are defined as follows:

Link to Prior Component (“-L”)

If this flag is present, the delta-X for this component is not interpreted as a distance. Rather, it is the index of a previous component at whose natural advance this new component is to be placed. Thus, if you wanted to make a single new glyph of the word “Hello” you would specify 5 components, where the first (the “H”) didn’t have any flags, where the “e” has the “-L” flag and a delta-X of zero (meaning the “zeroth”—or baseform—component), the first “l” has the “-L” flag and a delta-X of one, the second “l” has the “-L” flag and a delta-X of two, and so on. In this way you can create linked aggregates of glyphs. The first example in the examples section below shows this use.

24 Relative Positioning in Zones (“-Z”)

Sometimes you want to specify relative positioning where you don’t explicitly know the deltas. Or perhaps you’re creating an add list to be used with many different fonts, some wide like Avant Garde, some narrow like Onyx. In order to satisfy this need, add lists can use the concepts of “zones” with the “-Z” flag. Don’t confuse this component flag with the “-Z” flag that appears on the first line as described above; they are completely separate. If the zone flag is present on a component line, then the delta-X and delta-Y values are not interpreted as actual distances. Rather, they refer to zones where the component will be positioned. Consider the following diagram:

There are five horizontal zones, and five vertical zones. The heavy line drawn around the center nine zones is where the referent component is conceptually placed. The referent is some previous component—usually component zero (i.e. the baseform), but see the discussion of the “-R” flag below. The new component is then placed relative to the referent component based on the zones specified, as follows:

Zone 1

As a delta-X zone, zone 1 means that the right edge of this new component’s bounding box will be aligned with the left edge of the referent’s bounding box. As a delta-Y zone, zone 1 means the top edge of this new component’s bounding box will be aligned with the bottom edge of the referent’s bounding box.

Zone 2

As a delta-X zone, zone 2 means that the left edge of this new component’s bounding box will be aligned with the left edge of the referent’s bounding box. As a delta-Y zone, zone 2 means the bottom edge of this new component’s bounding box will be aligned with the bottom edge of the referent’s bounding box.

25 Zone 3

As a delta-X zone, zone 3 means that the center of this new component’s bounding box will be aligned with the center of the referent’s bounding box. As a delta-Y zone, zone 3 means the center of this new component’s bounding box will be aligned with the center of the referent’s bounding box.

Zone 4

As a delta-X zone, zone 4 means that the right edge of this new component’s bounding box will be aligned with the right edge of the referent’s bounding box. As a delta-Y zone, zone 4 means the top edge of this new component’s bounding box will be aligned with the top edge of the referent’s bounding box.

Zone 5

As a delta-X zone, zone 5 means that the left edge of this new component’s bounding box will be aligned with the right edge of the referent’s bounding box. As a delta-Y zone, zone 5 means the bottom edge of this new component’s bounding box will be aligned with the top edge of the referent’s bounding box.

Add Small Gap (“-G”)

All the positioning happens with respect to the tight bounding boxes of the components, and not with respect to their advances or sidebearings. This gives tighter control. For zones 1 and 5, you may additionally specify the “-G” or “gap” flag, which means that after the alignment described above takes place, a small gap (about 5% of the em square) is added. This is useful, for instance, if you don’t want your accents to touch the baseforms. The second example below shows how the “-Z” and “-G” flags are used.

Specify Relative Component (“-Rn”)

Sometimes it’s useful to position a component not relative to the baseform, but rather relative to a different previous component. You may specify this by using the “-Rn” flag, where n is the number of a prior component. Remember that component zero is the baseform; this case is so common that you don’t ever need to include an “-R0” flag, because it’s the default in the zone case. The third example below shows how this can be useful.

Scale Component (“-S scalefactor”)

The default behavior for all components is to be used at 100% of their regular size. You may change that by using the “-S” flag and specifying a scale factor, expressed as a decimal number where 1.0 means 100% (i.e. the regular size). Some examples

This section gives some examples of how add lists work. You can try copying them into a plain text file and actually running them with a real font to see the results.

26 Roman numerals

For the first example, let’s say you wanted to add some Roman numerals to a font. By adding them as separate glyphs you can maintain separate semantics for them. Here is how an add list would look to add 1 through 5: oneroman 1 I 0 0 tworoman 2 -C I 0 0 I 0 0 -L threeroman 3 -C I 0 0 I 0 0 -L I 1 0 -L fourroman 2 -C I 0 0 V 0 0 -L fiveroman 1 V 0 0

The new “one” and “five” glyphs are made up of only one component, with zero delta-X and delta-Y values. The “two,” “three,” and “four” glyphs are made up of two or three pieces. The “-C” flag on the first line for these indicates that the new glyph is to have the cumulative advance of all its components. The “-L” flag indicates this is a linked glyph. The value in the delta-X slot in these cases is not actually a delta-X, but rather a reference to which component this one is to link. Remember that the first component is number zero, not number one. Accented glyphs

The next example involves adding a new accented glyph, upper-case and lower-case, to a font. Let’s say you need to add an “F” with a “caron” (or “hachek”) above it. You might use an add list like:

Fcaron 2 F 0 0 caron 3 5 -Z -G fcaron 2 f 0 0 caron 34 5 -Z -G

The absence of the “-C” flag on the first line tells ftxenhancer to use just the advance width of the baseform letter as the advance width of the new composite glyph. The baseform has no delta-X or delta-Y applied. The presence of the “-Z” flag indicates that those components’ delta-X and delta-Y values are not actual distances, but rather zone identifiers. The Y-Zone is 5 for both glyphs, meaning the components should be positioned atop the baseform. The X- Zone of 3 for the upper-case letter means to center the caron. The X-Zone of 34 for the lower- case letter means to position the caron halfway between the 3 (centered) and 4 (right edges aligned) positions.

27 More extreme examples

Now let’s try a more whimsical example. Suppose we wish to create a new glyph that is an “F” with two carons atop it, side-by-side. Here’s the add list that does the trick:

Fdblcaron 3 F 0 0 caron 2 5 -Z -G caron 5 3 -Z -R1

The interesting thing to note in this list is the third line, which has the “-R1” flag. This flag means that the positioning of this component is to be relative to the bounding box of the first caron, and not of the baseform.

28 About Morph Input Files Introduction ftxanalyzer and ftxenhancer simplify much of the process of adding Apple Advanced intelligence to a font.

But sometimes you would like to add AAT features for glyphs which aren’t in ftxanalyzer pre-canned repertoire. For example, suppose you have a font with unique ligatures—a “Gr” ligature, say. Since this ligature isn’t in ftxanalyzer’s standard repertoire, ftxanalyzer won’t automatically add the tables needed to access this special ligature. In the past, the only recourse you had was to use TrueEdit to construct special-purpose tables yourself. Unfortunately, TrueEdit is fairly limited in the kinds of features it knows how to add to a font—for instance, it doesn’t do rearrangement or insertion actions at all, and it is limited to ligatures of no more than three glyphs; nor is it currently available for Mac OS X.

With ftxenhancer, you now have a way to add virtually any kind of feature to a font. To do this, you tell ftxenhancer to read a special file you have created, called a morph input file (or MIF for short). This document describes the format of a MIF, and gives lots of examples to get you started creating your own unique AAT fonts. A Quick Review of AAT Metamorphosis Effects

Before describing how to do the effects, let’s quickly review the five kinds of effect you can express in the metamorphosis table in an AAT font:

• Noncontextual (or Swash) • Contextual • Ligatures • Insertion • Rearrangement

A noncontextual effect is simply the substitution of one glyph for another, irrespective of the context. An example of this is changing lower-case letters to upper case, or choosing decorative variants of a letter.

A contextual effect is similar, in that it changes one glyph for another. The key difference lies in how this substitution happens: there has to be some particular context before the substitution happens. For instance, your font may contain a decorative set of capital letters which are designed to only appear at the beginning of a line. Or perhaps you would like to use a special form of a letter when it appears in a particular word. These are examples of contextual effects.

A ligature effect combines several glyphs into a single new glyph. Substituting an “fi” ligature for the sequence “f” followed by “i” is an example of this. You may combine up

29 to eight glyphs into a single new glyph. ftxenhancer supports ligature lists, which are simply rules for combining glyphs into ligatures. A future version will support a more generic ligature capability.

An insertion effect adds glyphs to the text which weren’t there to start with. Suppose you wanted to add fleurons around every occurrence of the word “Dave”—that would be an example of insertion.

A rearrangement action changes the order of glyphs in the line. While mostly useful for languages exhibiting this behavior (such as Hindi), it can also be used for special effects in other scripts. Think Pig Latin, here.

An understanding of how AAT processes a line of text is crucial for understanding the information in this document, so here’s a brief recap. For each feature present in the font, AAT checks to see if the user chose it (or if it is on by default). If the feature is chosen, AAT starts looking at the glyphs on the line, one by one, either starting at the front of the line and working along it, or else starting at the back of the line and working forward (the feature tells AAT which of these to choose). For every glyph it sees, AAT decides whether or not to do something with that glyph. It can decide to leave it alone, or it can decide to change it then and there, or it can remember it for possible future changes. Sometimes, when it changes a glyph, it leaves another glyph in its place. Other times, when it changes a glyph it leaves a special marker called a “deleted glyph” in its place, meaning that glyph has been eliminated from the line. That’s how ligatures work: an “f” followed by and “i” is usually changed into a “fi” followed by the special deleted glyph.

So the important thing to remember is that AAT is looking at the glyphs one at a time, and doing its changes in this manner. A First Example

To give you the flavor of this capability, let’s do a silly example. Suppose you want to create a feature which, when chosen by the user, changes some letters into “lookalikes”. For instance, a lower-case “c” is changed into the copyright sign, or an upper-case “Y” is changed into the yen sign.

Here’s a MIF you could use to get this effect; don’t worry so much about details for now (they’ll be explained below):

Type Noncontextual Name Lookalike Letters Namecode 64 Setting Use Lookalikes Settingcode 1 Default no Orientation HV Forward yes Exclusive yes

30 Y yen eight infinity c copyright r registered B germandbls L sterling E summation t dagger o degree S integral v radical i exclamdown f florin

Like all MIFs, this one starts with a header, which is the first group of lines (from the “Type” line through the “Exclusive” line). This header gives information about the kind of feature being added to the font.

Because the type of this MIF is “Noncontextual,” what follows is a simple list of original glyphs in the first column and their replacements using this feature in the second column.

That’s it! To add this feature to a font, you run ftxenhancer with the –m option, and you’re done. Once the font is installed, you can use it with an AAT application. Some general MIF rules

A MIF is just a text file, so you can create one with any text editor or word processor capable of writing plain text files. You can also use a spreadsheet program, as long as you remember to save as text.

You can use upper-case or lower-case letters in a MIF. The only time you need to be specific is when you’re specifying a glyph using its name. “A” is different than “a” when you’re identifying a glyph. Similarly, when you’re giving the name of a feature or setting (e.g. “Lookalike Letters” or “Use Lookalikes” above) case is significant, because these are the strings you’ll see when you use a AAT application with the font.

A single MIF can have multiple features. You just concatenate them one after the other in the file. You can use a line of dashes to separate them, if you like; lines of all dashes, spaces or tabs are ignored by ftxenhancer when it reads a MIF.

When you need to specify glyphs in a MIF, you may do so in one of two ways. You may use the glyph’s name (as found in the font’s ‘post’ table), or you may specify the glyph’s number in the font. In some special cases, you may also use the name DEL (note all upper-case) to mean the deleted glyph. For more details about this, see the format of the contextual MIF, below.

31 MIF Format—Headers

All MIFs share a common header, which appears first. This header comprises 9 lines which describe overall aspects of the feature being added.

The first line identifies what kind of feature is being added. It should be one of the following: Noncontextual, Contextual, LigatureList, Rearrangement or Insertion.

The second line has the name of the feature being added.

The third line has the numeric value for the feature being added. You should consult the Font Feature Registry at for the current list of defined codes, and use these codes if possible. If you are adding a feature not in the Registry, use a code with a value between 16000 and 32000 (don’t use commas or other punctuation).

The fourth line has the name of the setting for the feature being added. This is the string that appears in the menu of the AAT application when you’re editing text.

The fifth line has the numeric value for the setting being added. As with the name code described above, you should consult the Font Feature Registry to see if a setting already exists for your purposes. If not, use a value between 16000 and 32000 (again, no punctuation).

The sixth line indicates whether this feature should be on by default. The value should be yes or no. If you specify the feature is on by default, then a AAT application will show this feature when your font is chosen, without the user having to explicitly choose the feature from a menu. They can still, of course, turn the feature off if they so desire.

The seventh line indicates the orientations under which this feature should happen. The choices here are H (for horizontal only), V (for vertical only), or HV (for both). An example of a vertical only feature would be the substitution of different punctuation forms in a line of vertical Japanese.

The eighth line indicates whether the text should be processed forward or backward when doing this feature. You will usually choose forward processing, but there are times when backward processing is useful (see the Roman Numerals example below).

The ninth line indication whether the settings of this feature are mutually exclusive. For instance, settings in the “Letter Case” feature are usually mutually exclusive; you don’t want upper-case and lower-case to be applied at the same time. In contrast, ligatures are usually done non-exclusively, because different kinds of ligatures (“Common,” “Rare,” and so on) can be toggled on or off independent of one another.

32 MIF Format—Noncontextual

For a noncontextual feature, after the header comes a group of lines identifying which glyphs are to become which other glyphs. See the initial example above for a noncontextual table. MIF Format—Ligature List

For a ligature feature specified by a ligature list, the header is followed by a list of ligature lines, possibly preceded by a list of glyphs to be ignored during ligature formation. Let’s look at two examples, one without an “ignore” list and one with an “ignore” list.

Here’s a MIF to do some logo-like replacements:

Type LigatureList Name Ligatures Namecode 1 Setting Wacky Ligatures Settingcode 16 Default no Orientation HV Forward yes Exclusive no

List copyright c O registered r O trademark T M bullet b u l l e t

Here we see the keyword “List” after the header, which designates the start of the ligature list proper. The entries in the list must be indented (use a one or more tabs or spaces). First on each line is the name of the resulting ligature. After this is a list of the inputs making up that ligature. Thus, we see for example that typing the string “bullet” with this feature turned on will result in the bullet being substituted. Typing a “T” followed by an “M” will result in the trademark glyph being substituted, and so on.

Here’s an example MIF to do an Arabic ligature without letting a vowel interrupt the formation of the ligature (note that this table just does one ligature as an example; a real Arabic MIF for ligatures would have many more entries than this):

Type LigatureList Name Ligatures Namecode 1 Setting Common Ligatures Settingcode 2 Default yes Orientation H Forward no Exclusive no

33 Ignore damma kasra fatha

List lammeeminitial laminitial meemmedial lamjeeminitial laminitial jeemmedial

We see here a list of glyphs to be ignored. What this means is that the sequence initial “lam” followed by medial “meem” will form the initial “lam-meem” ligature, even if there is an intermediate “fatha,” “damma” or “kasra” vowel.

Warning: you should only include glyphs in the “Ignore” list which are designated as floaters in the font’s property table. MIF Format—State Tables

The remaining three kinds of feature require MIFs that are considerably more complex than the simple ones we’ve discussed so far. A common element in all of the remaining kinds of MIF is the state table. AAT uses state tables to allow fonts to have intelligence built-in, so that the font designer can control the font’s behavior without requiring direct application support.

All state tables have three parts in common: a class list, a state array, and an action list. Specific feature types may require additional information, but all the remaining MIF formats have at least these three parts. The class list

The class list lets you gather together glyphs which behave similarly into a single group, with a name for that group. For instance, if you want to have some behavior that depends on the presence of a letter (as opposed to a space, punctuation, etc.), you can create a class containing all the letters. The format of a class list is simply a group of lines, one class per line. A class line starts with the name of the class, and is followed by the members of the class. For instance, the following class list names three classes, “Zero” containing one member, “Early” containing three members, and “Rest” containing six members:

Zero zero Early one two three Rest four five six seven eight nine

In addition to the classes you explicitly name, there are four additional fixed classes, which are always present. The out-of-bounds class (or “OOB”) is the class you get for any glyph not covered by one of your explicit classes. Thus, given the three classes defined above, if AAT sees the letter “A” it assigns it to the out-of-bounds class, because “A” isn’t a member of any of the classes you defined.

34 The deleted-glyph class (or “DEL”) is the class assigned to a special code called the deleted glyph. The deleted glyph is left behind whenever AAT does ligature-like substitutions that result in some glyphs being eliminated. Thus, for instance, when an “f” plus “i” becomes an “fi” ligature, what really happens internally is that the “f” gets replaced by the “fi” and the “i” gets replaced by the deleted glyph, which doesn’t appear visibly on output but acts as a kind of placeholder.

The end-of-text (“EOT”) and end-of-line (“EOL”) classes are special classes that AAT arrives at when the particular style run or line comes to an end. If you’re setting up a contextual table to substitute special line-end swashes, for instance, you would set your state table up to perform substitutions when it sees the end of line. The distinction between end-of-line and end-of-text is this: in a line of text, whenever there’s a font change, the end-of-text class is used after the last character in the font run. The end-of- line class is used at the end of the last font run on the whole line. The state array

The state array is the heart of a state table. The job of the state array is to tell the font what action to take when it sees a glyph of a particular class in a particular context. Think of it as a mini-spreadsheet, with classes along the top and states down the side. Remember the description above of how AAT processes a line of text: it looks at the glyphs one by one and decides what to do with each one. The state array is what drives this process. Let’s look at an example, using the classes listed above:

EOT OOB DEL EOL Zero Early Rest StartText 1 1 1 1 2 1 1 StartLine 1 1 1 1 2 1 1 SawAZero 1 3 4 1 1 5 1

We see the classes (the 4 fixed classes and the ones you defined) along the top edge, and the names of the “states” along the left edge. The first two states (“StartText” and “StartLine”) are fixed, and must always be the first two lines in a state array. Any extra states come afterwards, such as the “SawAZero” state listed here. The number at the intersection of a state and a class is the number of an action in the action list (described below). Thus, when the line starts out, AAT starts off in the “StartText” state. If it sees a member of class “Zero” it goes and does action #2 from the action list. If it sees a member of any other class, it goes and does action #1 from the action list. As the line gets processed, if AAT finds itself in the “SawAZero” state and encounters an out-of-bounds glyph (i.e. a glyph not in any of your classes), it does action #3, and so on. The action list

The action list contains descriptions of the particular actions AAT should take when it is in a particular state and sees a glyph of a particular class. An action always specifies a new state to go to, as well as specifying other things AAT should do with the glyph it is looking at. Some examples of the kinds of actions you can specify are to remember (or “mark”) a glyph for future action, to specify that a glyph be changed into another

35 glyph, or to tell AAT whether it should move on to the next glyph in the line yet. Each different kind of feature being added has its own special action list format, so let’s proceed with the format description for a contextual feature to see how this all works together. MIF Format—Contextual

To make it easier to understand, let’s do a real example of a contextual table. Suppose I have a special decorative swash “A” which I want to automatically appear at the start of a line but nowhere else. Here’s how the MIF would look for this feature:

Type Contextual Name Smart Swashes Namecode 8 Setting Line Initial Swashes Settingcode 4 Default yes Orientation HV Forward yes Exclusive no

A A

EOT OOB DEL EOL A StartText 1 1 1 1 1 StartLine 1 1 1 1 2

GoTo Mark? Advance? SubstMark SubstCurrent 1 StartText no yes none none 2 StartText no yes none SwashA

SwashA A Aswash

We see here the five parts of a contextual MIF. The header is the first part, as described above. The state table portion is next, with the class list (pretty simple in this case, a single class named “A” comprising a single member, the glyph named ‘A’), the state array, and the action list. After the action list is the last of the five parts, the substitution lists (only one list in this example, named “SwashA”).

So how does this work? Let’s say we are starting off at the beginning of a line, and the first letter is indeed an ‘A’. We always start off in the StartLine state if we’re at the start of a line, so we look up the entry in the StartLine state for the “A” class, and see the number 2. This means the action we take for this glyph is specified in the action list in entry number 2. Looking there, we see the “SubstCurrent” field gives the name for a substitution list to be used for the “current” glyph. This list’s name is “SwashA.” Looking in that list, we see that an ‘A’ glyph should become an ‘Aswash’ glyph, so the substitution happens as we wanted.

If the first glyph on the line were something other than an ‘A’ then what happens? Because any other glyph doesn’t belong to any of the classes we set up, it will be

36 automatically put into the out-of-bounds class. If we look at the “OOB” entry in the “StartText” line, we see action number 1, which has “none” for its “SubstCurrent” list, so no substitution happens.

In both of the above cases, the “GoTo” entry tells us what new state line to use for the next glyph we process. Since both action 1 and action 2 specify to go to the “StartText” state, then for the rest of the line—even if we encounter another ‘A’—no further substitutions will be done.

The other columns in the action list need some explaining. The “Mark?” column allows you to “remember” a place in the line, even if you move past it. We’ll do an example below that uses this column, and its related “SubstMark” column. The “Advance?” column allows you to specify whether or not AAT will automatically advance to the next glyph in the line after finishing this action. Sometimes it is useful to not advance right away, but rather to do some extra processing first. Even if you don’t want AAT to advance to the next glyph, you still get to specify a new state to go to, so things don’t end up in an endless loop. Another example

Let’s do another example using marks. Suppose we’d like to set up a font so that the ‘v’ in the word “Eva” is replaced by a special swash form of ‘v’—in this example, let’s use the “radical” sign. What we need is a contextual table that changes the shape of the ‘v’ but only if it occurs in the right context, namely the word “Eva.” We don’t want this effect to happen in longer words which happen to start with the “Eva” string, like “Evaluate.” Here’s a MIF that effects this change:

Type Contextual Name Smart Swashes Namecode 8 Setting Special “Eva” Settingcode 1 Default no Orientation HV Forward yes Exclusive yes

E E v v a a Other A B C D F G H I J K L M N O P Q R S T U V W X Y Z b c d e f + g h i j k l m n o p q r s t u w x y z Adieresis Aring + Ccedilla Eacute Ntilde Odieresis Udieresis aacute agrave + acircumflex adieresis atilde aring ccedilla eacute egrave + ecircumflex edieresis iacute igrave icircumflex idieresis + ntilde oacute ograve ocircumflex odieresis otilde uacute + ugrave ucircumflex udieresis germandbls AE Oslash ae oslash + Agrave Atilde Otilde OE oe ydieresis Ydieresis fi fl + Acircumflex Ecircumflex Aacute Edieresis Egrave Iacute + Icircumflex Idieresis Igrave Oacute Ocircumflex Ograve + Uacute Ucircumflex Ugrave Lslash lslash Scaron scaron + Zcaron zcaron Eth eth Yacute yacute Thorn thorn Gbreve

37 + gbreve Idotaccent Scedilla scedilla Cacute cacute Ccaron + ccaron dbar

EOT OOB DEL EOL E v a Other StartText 1 1 1 1 3 2 2 2 StartLine 1 1 1 1 3 2 2 2 Flush 1 1 2 1 2 2 2 2 SawE 1 2 3 1 2 4 2 2 Sawv 1 2 5 1 2 2 6 2 Sawa 7 7 6 7 2 2 2 2

GoTo Mark? Advance? SubstMark SubstCurrent 1 StartText no yes none none 2 Flush no yes none none 3 SawE no yes none none 4 Sawv yes yes none none 5 Sawv no yes none none 6 Sawa no yes none none 7 StartText no yes EvaTable none

EvaTable v radical

Here we have divided the font into 4 classes of glyphs: the glyph ‘E,’ the glyph ‘v,’ the glyph ‘a,’ and all other letter glyphs. Notice that classes with lots of members can be specified across multiple lines by putting a plus-sign ‘+’ at the start of each continuation line.

This table tells AAT to wait until it sees an ‘E’ at the beginning of a word, then to look for a ‘v’, then an ‘a’ and then a non-letter before changing the ‘v’ into the swash form. You can follow this by looking at the names of the states along the left-hand edge of the state array; it’s generally a good idea to choose names that suggest how the feature works, because it makes it easier to debug later.

Once we’ve seen an ‘E’ at the start of a word, if we see a ‘v’ we do action #4, which “marks” the ‘v’ for future reference (look at the intersection of the “SawE” row and the ‘v’ column). Marking is a way of remembering a particular glyph to which changes will be made later on.

We reach the “Sawa” state when the string “Eva” has been seen. If another letter is encountered at this point, then the “Eva” was really the start of a longer word, so we take action #2 in this case, which takes us to the “Flush” state and skips over letters until reaching a nonletter. On the other hand, if after encountering the “Eva” we encounter something out of bounds (i.e. a nonletter), or reach the end of the line or of the style run, then we go ahead and change the ‘v’ (which we marked above, remember) into a radical.

This may all seem like a pretty complicated way to have the font do special effects, and to a certain extent, you’re right; it is. Making state tables is like writing computer programs, telling AAT how to make changes in the line. And, as is the case with computer programming languages, you have tremendous flexibility in getting just exactly the kinds of effect you want to get out of your font.

38 MIF Format—Insertion

The insertion feature allows to add extra glyphs to the line, glyphs which don’t have to correspond to anything the user may have typed. This kind of effect is linguistically necessary in certain scripts (the Southern Indian scripts or Burmese, for instance), but can also be useful for special text effects.

Like the Contextual MIF, the Insertion MIF comprises five parts: the standard header, the three standard parts of a state table, and then a list of glyphs to be inserted with some other information. Let’s look at the action list first. Here’s an example:

GoTo Mark? Advance? InsertMark InsertCurrent 1 StartText no yes none none 2 SawPossibleI yes yes none none 3 SkipRest no yes none none 4 StartText no yes Before1 Before2 5 SawPossibleI no yes none none

You should be comfortable with the “GoTo,” “Mark?” and “Advance?” columns by now. Just as the Contextual MIF has columns for “Substitute for Marked Glyph” and “Substitute for Current Glyph,” the Insertion MIF has columns for “Insert at Marked Glyph” and “Insert at Current Glyph.” If a particular action doesn’t make any changes, then both of these columns get “none” as their value. If something other than “none” appears in one or both of these columns, then that symbol is the name of an insertion list, which appears after the action list. Here are the two insertion lists referred to by line 4 of this action list:

Before1 IsKashidaLike yes InsertBefore yes Glyphs greater greater greater

Before2 IsKashidaLike yes InsertBefore yes Glyphs less less less

The name of the insertion list appears in the left-hand column, and its contents are indented one level. An insertion list is made up of three parts. The first part specifies whether the insertion is “-like” or not. This table can specify two kinds of insertion: “kashida-like” and “split vowel-like.” The former means extra glyph(s) will be added directly before or after the specified glyph (marked or current). The latter means the extra glyph(s) will be inserted some distance away from the current or marked glyph. For more details on this, consult the ‘mort’ chapter of the TrueType book; for now, always specify “yes” for this line.

The second line tells AAT whether to insert glyphs before or after the specified glyph. The third line lists the glyphs to be inserted. There is a limit of 31 glyphs permitted in the glyph list of an insertion list.

39 MIF Format—Rearrangement

The rearrangement feature allows you to change the order of glyphs in the line. It is linguistically necessary for scripts like Devanagari, but can also be useful even for Latin scripts.

The rearrangement MIF comprises the header and the standard three parts of a state table (class list, state array and action list), and nothing else. The formats of the class list and state array are the same as for the other tables. The format of the action list is shown in the following example:

GoTo MarkFirst? MarkLast? Advance? DoThis 1 StartText no no yes none 2 SawCapital yes no yes none 3 SawCapital no no yes none 4 StartText no yes yes xD->Dx

Instead of just one “Mark?” column like we’ve seen before, this list has two: whether to mark the current glyph as the first glyph of a group to be rearranged, and whether to mark the current glyph as the last glyph of a group to be rearranged. Rearrangement happens on groups of glyphs whose first and last members you mark in this way.

The actual rearrangement happens as a result of the command you give in the “DoThis” column. To show how this works, let’s imagine you have a string of numbers “123456789” with the ‘1’ marked as first and the ‘9’ marked as last. This table shows you the 16 choices you can put into the “DoThis” column, and what happens to that string for each of them:

To get this effect.... Use this command 123456789 -> 123456789 none 123456789 -> 234567891 Ax->xA 123456789 -> 912345678 xD->Dx 123456789 -> 923456781 AxD->DxA 123456789 -> 345678912 ABx->xAB 123456789 -> 345678921 ABx->xBA 123456789 -> 891234567 xCD->CDx 123456789 -> 981234567 xCD->DCx 123456789 -> 892345671 AxCD->CDxA 123456789 -> 982345671 AxCD->DCxA 123456789 -> 934567812 ABxD->DxAB 123456789 -> 934567821 ABxD->DxBA 123456789 -> 893456712 ABxCD->CDxAB 123456789 -> 893456721 ABxCD->CDxBA 123456789 -> 983456712 ABxCD->DCxAB 123456789 -> 983456721 ABxCD->DcxBA

The “->“ is just a hyphen followed by a greater-than sign. The “x” in the command represents some connected chunk of text. The ‘A,’ ‘B,’ ‘C,’ and ‘D’ represent single glyphs. Thus, the “Ax->xA” command is saying to take the single glyph at the start of the marked range and move it to the end, as you can see from the illustration where “123456789” becomes “234567891”.

40 Using Justification Input Files Introduction

One of the tables that can be added by ftxenhancer controls how the glyphs in a font will look in justified lines of text. This table is called the Justification Table, and controls many different aspects of how the text will look when it is justified, including how much whitespace (if any) will be added between letters, whether certain glyphs should take up more space than others, how much space should be added before ligatures break apart, and so on. While the default JIF generated by ftxanalyzer is good enough in many cases, there may be times when you wish to specify particular behaviors. To do that, you prepare a special text file, called a “Justification Input File” (or JIF, for short). This tutorial will review how AAT justification works, and then describe how to make your own JIFs to allow your fonts to behave in different ways. How AAT Justification Works

Before describing how to make a JIF, let’s look at how AAT line layout does justification. This section describes this process, as well as defining some terminology which will be used in later sections.

AAT Line Layout happens in two passes. First, a nonpositional pass alters the identities of glyphs, fusing glyphs into ligatures or changing them into swashes. Second, a positional pass adjusts the positions of the glyphs with respect to one another. This positional pass comprises two parts: the non-justification part, and the justification part.

In the non-justification part of the positioning pass, adjustments to glyph positions are made using kerning, tracking, baseline, optical edge and manual letterspacing controls. Once these are done, the justification part may do further processing. This justification part is itself subdivided into several phases: the factor phase, the assignment phase, and the postcomp phase. Note that some of the justification actions may take place even on unjustified lines of text: for example, if loose tracking is applied to a line, enough letterspacing may be added so that ligatures should be broken apart. Ligature decomposition happens in the postcomp phase, so this phase needs to happen even if the line itself is not justified.

Irrespective of justification, a line of text has a “natural” width, called the unjustified width, which is roughly the sum of the widths of all the glyphs making up the line. I say “roughly” here, since there are other factors taken into account in AAT which affect this width. For instance, the line may start with a hung punctuation glyph; in this case, the width of that glyph is not counted in the line’s unjustified width. Similarly, any kerning, tracking or manual letterspacing the user has specified alter the effective widths of glyphs, and thus the total unjustified width.

41 The Factor Phase

Now let’s look at the three phases of justification in more detail. First is the factor phase. This phase begins by computing the unjustified width of the line, and sees what justified width the user has specified. The unjustified width is subtracted from the justified width to get the base gap that needs to be filled. For example if the unjustified width of the line is 300 points, and the justified width is specified as being 450 points, then the base gap is +150 points. When the base gap is positive, it is called the grow case, because the line needs to grow to fill the gap. When the base gap is negative, it is called the shrink case. In this case, the line needs to be squeezed to fit the specified width.

In either the grow or shrink cases, the user may not want all the gap to be filled; an example of this is specifying, say, an 80% ragged right edge. In AAT this is done by setting the justification for the line to some value other than 0 or 1. The base gap is adjusted by one minus this value, resulting in the final gap to be filled.

Once the final gap is calculated, AAT consults with the justification table in the font, as well as any user overrides, to determine how much distance is available on each side of each glyph for justification purposes. This distance is specified in ems—that is, in points for one-point text. This gets multiplied by the pointsize of the actual glyphs to get the actual available distance. The resulting numbers (one for the left side of each glyph and one for the right side) are called the justification factors. To take an example, if the font designates a left-side factor of 0.2 and a right-side factor of 0.3 for a particular glyph, then that glyph at 10-point will have available (0.2 times 10) or 2 points on the left and (0.3 times 10) or 3 points on the right. Note that AAT doesn’t do anything with this distance yet; it represents a potential, a means of helping fill the final gap.

As well as determining the justification factors, the factor phase also determines two other critical pieces of information for each glyph on the line: the justification priority, and the unlimited status. The justification priority controls the order in which glyphs will be changed later in the assignment phase. There are four priorities, called by convention the kashida priority, whitespace priority, intercharacter priority, and the null priority, with kashida priority the highest and null priority the lowest. All glyphs of a higher priority will be adjusted before any glyphs of a lower priority are considered. If a glyph has the unlimited status, then that glyph is permitted to absorb all of the remaining gap, even in excess of its justification factors. If a line contains one or more unlimited glyphs of a given priority level, then any glyphs of lower priority levels won’t be touched during the assignment phase. The Assignment Phase

With these data (the left and right factors, the priority and the unlimited status), the factor phase is finished and the assignment phase begins. The assignment phase is needed to allow for cases where the total justification factors available on the line exceed the needed final gap, or are insufficient to cover that gap. The assignment

42 phase starts at the highest priority present on the line, adds up the total factors at that level, and sees if that amount is enough to satisfy the final gap. If it is then the final gap is apportioned proportionally to the factors, and the assignment phase is done. If there is still gap left over, then the next lowest priority level is considered, and so on. If all the priority levels are used up, and there is still gap left over (and there were no unlimited glyphs), then the assignment phase goes back to the highest priority that was present on the line and gives the remaining gap to those glyphs; note that this will violate their factors, but this case only happens in extremis. The Postcomp Phase

Once the factors have been apportioned in this way, the glyph positions are modified accordingly. By positioning the glyphs further apart, whitespace is introduced. In many cases this suffices; however, there are cases (like connected scripts) where whitespace is not permitted between glyphs. These cases are handled by the final phase, the postcomp phase. Here decisions are made about creative alternatives to just separating glyphs by whitespace. For example, an extra glyph can be inserted between two glyphs in order to change the whitespace added into something else. A wider version of a glyph can be substituted for an existing glyph to help swallow some of the space. Ligatures can decompose if needed. A variation axis can be used to change the widths of all the glyphs (called copyfitting). The Justification Class

One of the most powerful aspects of AAT Line Layout is its ability to make decisions based on context. This means that the same glyph might behave differently in different contexts: for instance, a glyph at the end of the line or in a particular word might be changed into a swash variant glyph.

This ability to make decisions based on context is present for justification as well. In the factor phase and the postcomp phase, the values associated with a particular glyph are looked up not only by glyph index but also by a contextually determined value called the justification class. This value is a number from 0 to 127 which can be used to give the same glyph different behaviors. If you don’t need contextual behavior in your justification table, you can just use a justification class of zero everywhere. If you wish to have contextual behaviors, then you can include a justification class state table in your font. Overall JIF Format

The format of a JIF starts with a direction header line, and is followed by table parts which describe one or more of the factors, classes and postcomp actions. To get things started, let’s look at a simple JIF:

43 ------Direction H

TablePart Factors

Whitespace space Interchar (all others)

Interchar 0 BeforeGrow 0.05 BeforeShrink -0.02 AfterGrow 0.05 AfterShrink -0.02 GrowFlags intercharacterPriority ShrinkFlags whitespacePriority

Whitespace 0 BeforeGrow 0.2 BeforeShrink -0.02 AfterGrow 0.2 AfterShrink -0.02 GrowFlags whitespacePriority unlimited ShrinkFlags whitespacePriority ------

The effect of this JIF is to divide the glyphs in the font into two categories: whitespace (the space glyph), and everything else. When space is added (the grow case), the space gets whitespace priority and everything else gets intercharacter priority. As described above, this means that any spaces on the line will be the first things to be expanded when the line is being justified. Furthermore, since the unlimited flag is also specified, whitespace will be the only thing expanded on the line; intercharacter spacing won’t ever be used (unless the line contains no whitespace at all). The Header

The first line in a JIF is an indication of which direction the following table parts are for. The choices are “H” or “V”—in our example, we’re looking at the data for a horizontal justification table. You may include both directions in a single JIF: after the last table part for the first direction, include another “Direction” line with the other direction, followed by its table parts.

Each table part starts with the “TablePart” identifier. There are three different table parts you may include in a JIF: Factors, Classes, and Postcomp. You should always include at least the Factors table part in your JIFs; the other two are optional, and less frequently used. Each table part is described in more detail in the following sections.

You may use lines of all hyphens as separators in your JIF. You may include comments in your JIF by placing them between /* and */ delimiters, or at the end of a line after a // delimiter.

44 The “Factors” table part

The “Factors” table part contains information describing the characteristics of glyphs when they are justified. It has two main pieces: the grouping piece and the values pieces.

The grouping piece allows you to gather together glyphs which have the same behaviors, and to give a single name to this collection of glyphs. The name of the group appears in the leftmost column, and it is followed by a list of the members of the group, which may be specified by either their names or their glyph numbers. If your class is very long, you may continue it over multiple lines by including a plus-sign (‘+’) at the start of each continuation line, like this:

------UpperCaseLetters A B C D E F G H I J K L + M N O P Q R S T U V W X Y Z ------

The values piece lets you associate justification values with the different groups you just defined. Each part of the values piece starts with the name of the group for which values are being specified in the leftmost column. This is followed on the same line by the justification class for which these values are to be used. There are six lines after this containing the actual values for this combination of group and justification class. The “Classes” table part

The concept of a justification class was described above in the description of how AAT justification works. You can specify a state table for the contextual determination of the justification class for a glyph in your JIF by including a “Classes” table part. To focus the discussion, let’s look at an example of a state table used to give a justification class of zero to “fi” and “fl” ligatures which occur in words, and a justification class of one if these same ligatures appear by themselves (that is, surrounded by non letters):

------TablePart Classes " Forward yes " Liggie fi fl Letter A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d + e f g h i j k l m n o p q r s t u v w x y z Adieresis Aring + Ccedilla Eacute Ntilde Odieresis Udieresis aacute agrave + acircumflex adieresis atilde aring ccedilla eacute egrave + ecircumflex edieresis iacute igrave icircumflex idieresis + ntilde oacute ograve ocircumflex odieresis otilde uacute + ugrave ucircumflex udieresis germandbls AE Oslash ae oslash + Agrave Atilde Otilde OE oe ydieresis Ydieresis fi fl + Acircumflex Ecircumflex Aacute Edieresis Egrave Iacute + Icircumflex Idieresis Igrave Oacute Ocircumflex Ograve + Uacute Ucircumflex Ugrave Lslash lslash Scaron scaron + Zcaron zcaron Eth eth Yacute yacute Thorn thorn Gbreve

45 + gbreve Idotaccent Scedilla scedilla Cacute cacute Ccaron + ccaron dbar " " EOT OOB DEL EOL Liggie Letter StartText 1 1 1 1 2 3 StartLine 1 1 1 1 2 3 SawLig 5 5 4 5 3 3 SawLetter 1 1 3 1 3 3 " GoTo Mark? Advance? MarkClass CurrentClass 1 StartText no yes 0 0 2 SawLig yes yes 0 0 3 SawLetter no yes 0 0 4 SawLig no yes 0 0 5 StartText no yes 1 0 ------

This table works by walking through the line, looking for either a letter or a ligature. If it sees a letter first, it goes to the SawLetter state, where it scans through and ignores both letters and ligatures until it sees something that is neither (that is, the end of the word—this is the “1” in the OOB column of the SawLetter state). If it sees a ligature first, it goes to the SawLig state and marks the ligature it just saw. Once in that state, it ignores any deleted glyphs (leftovers from the process that formed the ligature), and only sets the justification class of the marked ligature to 1 if it sees no further letters. The “Postcomp” table part

There are many different ways of filling up space in a line of text which is being justified. The “Factors” table part, described above, lets you control how extra gap is distributed within a line, but it says nothing about how that gap actually appears. In Latin text, the default behavior is to add whitespace, but in other writing systems, there are other approaches. The “Postcomp” table part allows you to control how gap is filled in the line.

To get the discussion started, here’s a sample “Postcomp” table part:

------TablePart Postcomp fiLig fi flLig fl fiLig 0 Decomposition LowerLimit 0 UpperLimit 0.5 Order 1 DecomposeInto f i fiLig 0 Decomposition LowerLimit -0.1 UpperLimit 0 Order 1 DecomposeInto f dotlessi

46 flLig 0 Decomposition LowerLimit -0.1 UpperLimit 0.5 Order 1 DecomposeInto f l ------

You can see the standard “TablePart” tag, which identifies this as the postcomp table part. This is always followed by a list of glyph group names, along with which glyphs belong to those groups. This is followed by the list of one or more specific actions, which are associated with a particular group and a particular justification class (as described above). Ligature Decomposition actions

In this example we’re specifying how the ‘fi’ and ‘fl’ ligatures should decompose under various justification conditions. The standard TablePart tag is followed by a list of glyph group names, along with which glyphs belong to those groups. Then, for each group, one or more action specifications are made. In the ‘fi’ ligature case, there are two specifications, so that the ligature will break apart into its component “f” and “i” glyphs under expansion, but will differently decompose into an “f” followed by a dotless “i” under compression. The lower and upper limits are expressed in ems, and represent the amount of gap (cumulated on both sides of the ligature) which will trigger the specified action. The order is a number controlling which ligatures decompose first on a line; lower order numbers decompose before higher ones. Unconditional Add actions

There may be times when, in order to fill some justification gap, you wish to insert an extra glyph after an existing one. In Arabic, for instance, extra glyphs called “” are inserted when text is justified, in order to avoid the connected letters from being broken apart by whitespace. You can accomplish this by specifying an Unconditional Add action. Here’s an example:

------TablePart Postcomp lower a b c d e f g h i j k l m n o p q r s t u v w x y z lower 0 UnconditionalAdd AddGlyph period ------

Here, a period will be added after every lower-case letter to help fill in the gap. Conditional Add actions

The Unconditional Add action is useful, but sometimes you’d like more subtle control over the process. Specifically, you may use the Conditional Add action to control the

47 threshold beyond which a glyph will be added, and also whether the glyph in question can itself be changed into another glyph. To take a simple example, let’s say you wish to change a simple ‘W’ into a wider swash ‘W’ when the line is being expanded under justification. Here’s a postcomp table part that does this:

------TablePart Postcomp

W W

W 0 ConditionalAdd Threshold 0.05 AddGlyph (none) SubstGlyph Wswash ------

Here the ‘W’ will change into the swash ‘W’ if 0.05 ems (or more) are being added around the ‘W’. The special “(none)” value means no glyph will be added here, so this is a simple substitution. The Threshold factor only applies to the substitution; if there’s an AddGlyph specified, it will always be added. Stretch actions

There may be times when, in order to fill in gap, you wish to stretch an existing glyph. An example here might be an em-dash, which the font designer adds with square edges so it can be stretched horizontally without distortion. The stretch action is very simple; here’s an example with the em-dash:

------TablePart Postcomp dash emdash endash dash 0 Stretch ------

Note that there is no extra information, beyond the kind of action (i.e. “Stretch”). Ductility actions

A more sophisticated form of stretching can also be specified if the font has been designed with variation axes (a Multiple Masters font, say, or a TrueType variations font). In this case, you may designate a variation axis which will be modified to copyfit glyphs when the line is being justified. Here’s an example:

------TablePart Postcomp toCopyFit A B C D E F G H I J K L M N O P Q R S T U V W X Y Z + a b c d e f g h i j k l m n o p q r s t u v w x y z toCopyFit 0 Ductility

48 VariationAxis duct Minimum 0.5 NoStretch 1.0 Maximum 2.0 ------

In this example the upper-case and lower-case Latin letters are specified as being allowed to vary under justification. The axis being used has the 4-character tag ‘duct’, and has the specified minimum, default, and maximum values.

For more information on how postcomp information is used by the line layout justification algorithm, please see the description of the ‘just’ table, or the justification algorithm documentation. Some Examples

While the above sections described all the possible inputs for the various table parts, it is always more instructive to take some real examples. This section will include some examples of real justification tables, showing how to put together the information described above in creative ways. Simple Latin, no intercharacter spacing

To start off, let’s do an example for a Latin font where you don’t ever want to see intercharacter spacing when a line is expanded. If a line must be shrunk, you want space to be removed uniformly from both intercharacter and whitespace. To accomplish this, you’ll need to make the space glyph a higher priority than any of the other glyphs, and you’ll need to designate it as an “unlimited” glyph. Here’s a JIF that would give you this effect:

------Direction H

TablePart Factors " Whitespace space Interchar (all others) " Interchar 0 BeforeGrow 0 BeforeShrink -0.05 AfterGrow 0 AfterShrink -0.05 GrowFlags intercharacterPriority ShrinkFlags intercharacterPriority " Whitespace 0 BeforeGrow 1 BeforeShrink -0.05 AfterGrow 1 AfterShrink -0.05 GrowFlags whitespacePriority unlimited

49 ShrinkFlags intercharacterPriority ------

This JIF specifies factors for horizontal text. There is only one table part, a factors part. Two groups are defined: one named “Whitespace” comprising solely the space glyph, and one named “Interchar” comprising all other glyphs in the font. The “(all others)” should be typed exactly as it is here. This special wording is recognized by ftxenhancer and it will group all glyphs not already named into the specified group.

The factors for intercharacter and whitespace in the shrink case are the same, and the shrink flags indicate that glyphs of both groups will get the same priority (intercharacterPriority) assigned to them. Notice that the shrink factors are negative, and that they are the same for whitespace and intercharacter. This means that if a line needs to shrink, uniform amounts of space will be removed from between every pair of glyphs, irrespective of whitespace considerations.

In the grow case, the space glyph gets a nonzero value (1 in this case, although this value doesn’t really matter in this example); it also gets assigned to a higher priority (whitespacePriority) and gets the unlimited flag. This means that the layout process won’t even bother looking at any lower priority glyphs on the line—everything will be added to the spaces only. Adding intercharacter spacing

Let’s modify this example slightly to permit a very small amount of intercharacter spacing to be added:

------Direction H

TablePart Factors " Whitespace space Interchar (all others) " Interchar 0 BeforeGrow 0.01 BeforeShrink -0.05 AfterGrow 0.01 AfterShrink -0.05 GrowFlags intercharacterPriority ShrinkFlags intercharacterPriority " Whitespace 0 BeforeGrow 1 BeforeShrink -0.05 AfterGrow 1 AfterShrink -0.05 GrowFlags whitespacePriority ShrinkFlags intercharacterPriority ------

50 The only change between this new JIF and the previous one is the removal of the “unlimited” flag from the whitespace’s grow flags, and the changing of the intercharacter grow factors from zero to 0.01. What does this mean in practical terms? Let’s say we’re laying out a line of 12-point text whose natural width is 350 points and we need to justify it to 400 points. Because 400 is greater than 350, this is the grow case, so AAT will only look at the grow numbers and flags to fill the 50 point gap. The values of 1 for both before and after factors for whitespace mean that (1 times 12) or 12 points of space will be added both before and after any space glyphs on the line. Let’s imagine that this line has two space glyphs on it. Each of these will have a total of 24 points of padding added (12 before and 12 after), so that takes up 48 points of the 50 point gap. After whitespace priority is finished, AAT moves down to the next priority level, intercharacter. The factors of 0.01 for before and after mean that no more than (0.01 times 12) or 0.12 points of padding may be added on either side of a glyph. If there are enough intercharacter positions available to fill up the 2 points remaining, then the gap is evenly distributed and processing stops.

51