Quick viewing(Text Mode)

The Apple Font Tool Suite

The Apple Tool Suite

This document is copyright © 2002–2006 by Apple Computer, Inc. All rights reserved.

Table of Contents

Table of Contents...... i

Introduction ...... v

Installing the tools...... vi

Unicode™ ...... vi

Words of warning ...... vii

Using the tools ...... vii

Using this document ...... vii ftxanalyzer ...... 1

Typical uses for ftxanalyzer ...... 4 ftxdiff ...... 7 ftxdumperfuser...... 9 ftxenhancer ...... 15 ftxinstalledfonts...... 17 ftxruler—ATSUI ...... 19 ftxruler—QuickDraw...... 23 ftxvalidator...... 29

How to Use Add Lists...... 33

Introduction ...... 33

Creating an Add List...... 33

The first line ...... 33

The component line(s) ...... 34

Some examples...... 37

Roman numerals ...... 37

Accented ...... 37 i More extreme examples ...... 38

Addendum...... 38

About Morph Input Files...... 41

Introduction ...... 41

A Quick Review of AAT Metamorphosis Effects...... 41

A First Example...... 42

Some general MIF rules...... 43

MIF Format—Headers...... 44

MIF Format—Noncontextual ...... 45

MIF Format— List ...... 45

MIF Format—State Tables...... 47

The class list ...... 48

The state array ...... 48

The action list...... 49

MIF Format—Contextual...... 49

Another example ...... 51

MIF Format—Insertion...... 52

MIF Format—Rearrangement...... 53

MIF Format—Some general considerations...... 54

MIF Templates ...... 58

Using Justification Input Files ...... 61

Introduction ...... 61

How AAT Justification Works...... 61

The Factor Phase ...... 62

The Assignment Phase ...... 62

ii The Postcomp Phase ...... 63

The Justification Class...... 63

Overall JIF Format ...... 63

The Header ...... 64

The “Factors” table part...... 65

The “Classes” table part ...... 65

The “Postcomp” table part ...... 66

Ligature Decomposition actions ...... 67

Unconditional Add actions...... 67

Conditional Add actions...... 68

Stretch actions...... 68

Ductility actions...... 68

Some Examples...... 69

Simple Latin, no intercharacter spacing...... 69

Adding intercharacter spacing ...... 70

iii

Introduction

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

• ftxanalyzer • ftxdiff • ftxdumpfond • ftxdumperfuser • ftxenhancer • ftxfusefond • ftxinstalledfonts • ftxruler • ftxvalidator • klcompiler • klkchrtoxml • kluchrtoxml

Two applications are also included:

• FontProoferX • MorxTester

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 bulk of our 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

v 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 and viewed 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 (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) Using XML makes it unnecessary to include text-parsing code in the tools, which means that the tools are more robust. 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 command-line tools in /usr/bin, the non- command-line tools in /Developer/FontTools, and the framework in /Library/Frameworks. You can move the framework to ~/Library/Frameworks afterwards if you prefer.

Unicode is a new international character set, intended to make it possible to write all the world’s languages with equal ease on any computer system. Unicode is at the core of representing, drawing, and manipulating text on Mac OS X. Although the tools in Apple’s font tool suite may be used to support other character sets, they are specifically designed to help develop for use with Unicode.

Characters are assigned numbers between 0 (0x0000) and 1,114,111 (0x10FFFF), inclusive. These numbers are referred to as “Unicode scalar values.” A Unicode scalar value is written with “U+” followed by four to six hexadecimal digits, so that U+0041 is the Latin letter “A.” Unicode characters are assigned names (such as LATIN CAPITAL LETTER A) and other properties such as directionality.

The formal definition of Unicode is found in The Unicode Standard, Volume 4.0 (Boston, Addison-Wesley, 2003, ISBN 0-321-18758-1). For more information on Unicode, see the ’s Web site (http://www.unicode.org/). An excellent book on Unicode is Unicode Demystified by Richard Gillam (Boston, Addison-Wesley, 2003, ISBN 0-201-70052-2).

vi 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 fonts 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.

The non-command-line tools have online help that can be accessed from the Help menu. Using this document

The tools are used by Apple internally and are frequently updated as problems are encountered. This document is updated less frequently. Always double-check the usage text shown using the –h option or executing the tool without any arguments in case there are any changes from the options as described herein.

vii 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 the AAT Font Tool, which it replaces, 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 XML “add” file

This is a list of new glyphs that the tool determines the font needs or could be useful. These new glyphs come in four categories, one of which is optional and only present if the -M option is used: glyphs needed for Unicode mirroring, glyphs needed for Unicode decomposition, glyphs such as accented letters which can be made by piecing together other glyphs already in the font, 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.

1 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 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 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. This option is only really needed for Arabic fonts, and even then the result should be double-checked before use. -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 in the font and their alternate representations using combining characters

Support for commonly found (if not commonly used) Latin ligatures (such as fi and ct).

Actions defined for fonts which conform to Apple’s standard model for a particular Unicode script (e.g., , , Gujarati, Thai).

Some actions derived from the font’s ‘GSUB’ table.

2 If the –U option is also specified, the ftxanalyzer will also include the so-called universal or “magic” MIF in the MIF file it generates. This is a large set of actions derived entirely from the Unicode content of a font but except for Korean or Arabic fonts is not very useful. -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. -t A sample-text 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 consists of a series of paragraphs in various languages covered by the font preceded by the English name of the language. -u A Unicode document

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 in the row, and the remaining sixteen for whatever characters should be contained there), the rows can get rather wide. -z A ‘Zapf’ table source

This file contains default data for a ‘Zapf’ table for the font in a format that can be fused into the font using ftxdumperfuser.

Other options for ftxanalyzer are:

3 -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 and -1 (that’s a one, not an el) options 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. The -1 option uses the first font ftxanalyzer finds in the suitcase, and – f lets you specify which font by giving its name. As a rule, if the suitcase consists entirely of different faces in a single family, and each face contains the same glyphs with the same names in the same order—which is always a good idea in such cases—you’ll want to use the -1 option. Otherwise, you should use –f.

If you need to use the -f or -1 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 -g option.

The results of this option 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 ‘prop’ and ‘Zapf’ 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.

Alternatively, you can use the -F option. This generates an input file for the FontProoferX application. FontProoferX provides a simple, unified UI for checking the font’s Unicode repertoire and default glyph composition.

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.xml 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 can be found in the add list:

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: ftxanalyzer -m MyFont.mif MyFont.ttf

4 Warning. If the Universal MIF is included, 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 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 data 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. Full glyph cross-reference data is beyond the capacity of an automatic tool, however. The ‘Zapf’ table data generated by ftxanalyzer should be viewed as the starting point for you to use in adding all the glyph cross-references found in your font.

5

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 MyOldFont.suit MyNewFont.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.

7

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:

• ‘avar’ (axis variation) • ‘bdat’ (bitmap data) • ‘bhea’ (bitmap horizontal header) • ‘bhed’ (bitmap font header) • ‘bloc’ (bitmap location) • ‘cmap’ (character code mapping); this includes full support for all of Unicode using Unicode scalar values • ‘feat’ (layout feature) • ‘fvar’ (font variation) • ‘gasp’ (grid-fitting and scan-conversion procedure) table • ‘glyf’ (glyph outlines) • ‘hdmx’ (horizontal device metrics) • ‘head’ (font header) • ‘hhea’ (horizontal header) • ‘hmtx’ (horizontal metrics) • ‘loca’ (glyph location) • ‘maxp’ (maximum profile) • ‘name’ (name) • ‘opbd’ (optical bounds) • ‘OS/2’ (compatibility) • ‘post’ (glyph name and PostScript compatibility) • ‘prop’ (glyph properties) • ‘vhea’ (vertical header) • ‘vmtx’ (vertical metrics) • ‘Zapf’ (glyph reference)

It can dump but not fuse the following tables:

9 • ‘cvar’ (CVT variation) • ‘gvar’ (glyph variation) • ‘mort’ (metamorphosis) • ‘morx’ (extended metamorphosis)

It can do partial dumps of the following tables:

• ‘just’ (justification) • ‘kern’ (kerning)

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. The verbose form of the ‘glyf’ table dump also allows stripping the hints from an individual glyph.

For the tables with only partial or complete dumps and no fuse operations, ftxdumperfuser’s current format is aimed not at modifying the tables, but at diagnosing simple problems within them. 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.

If you use the -S option together with -A d, spaces in the auto-generated file name will be replaced with underscores. In the case above, the files generated would be MyFont.cmap.xml

10 and MyFont_Bold.cmap.xml. In all cases, a slash or space in the table tag will be turned into an underscore (so that the ‘cvt ’ and ‘OS/2’ tables end up in files ending in cvt_.xml and OS_2.xml, respectively).

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: 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: -I and -N

These options let you dump from (but not fuse to) an installed font. When the -N option is used, the final parameter is interpreted as the name of an installed font.

You could therefore do something like ftxdumperfuser -t post -N Zapfino to get a list of the glyph names in Zapfino.

The name expected by the -N option is the one used by the font manager. On occasion, you may have trouble determining precisely what name the font manager expects. In such cases, you can use the -I option with a numeric font ID instead of a name. The numeric font ID can be found using ftxinstalledfonts. Each line of the output generated by ftxinstalledfonts starts with two numbers. The first is the font’s index in your list of fonts and cannot be used by ftxdumperfuser. The second is the font’s numeric ID.

11 For example, we can use the Unix grep command (which does a search) to find the numeric ID for Zapfino: ftxinstalledfonts -f | grep Zapfino

The vertical bar in this line is an example of a Unix “pipe.” It tells Unix to take the output from ftxinstalledfonts and use it as input for grep. grep will take its input and throw away every line that doesn’t contain the word Zapfino. The output should be something like:

321 8425 Zapfino

Be aware that a font’s numeric ID can and probably will change whenever you restart your machine. Never assume that you know what it is now because of what it was before!

With the numeric ID, we can now do a dump, using the -I option to let ftxdumperfuser that we’re using the font’s numeric ID and not its name. ftxdumperfuser -t post -I 8425

-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.

12 -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:

-x

This tells ftxdumperfuser to use raw hexadecimal codes whenever it encounters an entry in the ‘name’ table it cannot convert to Unicode.

Every entry in the ‘name’ table has a platform ID and a platform-specific ID (the latter is also known as a script ID). For most combinations of platform and platform-specific ID, converting the name to Unicode is relatively straightforward, but not for all. In particular, the combination of Windows platform (3) and Symbol platform-specific ID (0) is good for the ‘cmap’ table, but poison in the ‘name’ table. Where ftxdumperfuser cannot determine or even guess how to convert a name to Unicode, it will fail, unless the –x option is used. With the –x option, rather than failing, it includes the raw, unconverted, and un-human-readable data in the dump.

On occasion, you can dump a name with ftxdumperfuser which you cannot fuse back in. This is because when it encounters a ‘name’ table entry which cannot be converted to Unicode reliably, it scans it to see if it may be ASCII. If it looks like an ASCII name, ftxdumperfuser will act on the assumption that it is ASCII and convert it appropriately. Fusing back in is another matter, however. If there is no well-defined conversion from Unicode to a particular platform/platform-specific ID combination, there’s nothing the tool can do.

In such cases, the problem is that the table has an illegal or nonsensical platform/platform- specific ID combination, which should be removed.

Apple strongly suggests that the only platform/platform-specific IDs that are used in the ‘name’ table use the Unicode platform (any defined platform-specific ID for the Unicode platform), the Macintosh platform (any defined platform-specific ID for the Macintosh platform), and the Microsoft platform with the Unicode platform-specific ID.

13

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.

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.

15

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 0. Thus you could find a font that supports the by using: ftxinstalledfonts -f -U 10400 | grep YES

The -q option returns the QuickDraw (i.e. FOND) names of the fonts.

Note that since QuickDraw cannot render all of Unicode, it’s entirely possible to have a font installed on your system that cannot be used with QuickDraw and will not have a valid QuickDraw font name listed with 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)

17 3. /Network/Library/Fonts (Network) 4. /System/Library/Fonts (System) 5. [Classic System Folder]/Fonts (Classic)

18 ftxruler—ATSUI

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 two types of input file: one, the original input file format, is used to test a font using QuickDraw; the other is an XML file used to test a font using ATSUI. In both cases, ftxruler works on installed fonts—not font files. You can use a font management utility such as Font Book to install the font you’re working on, if necessary.

When testing a font with ATSUI, ftxruler requires the –A option. Without the –A option, ftxruler defaults to using QuickDraw input files as described below.

The options other than –A, -h, -v, and –V control the output produced with the ATSUI tests. Since ATSUI breaks your text up into lines and, for each line, turns an array of Unicode characters into an array of glyphs, you can control how much information or how little you get about each line: whether or not the characters corresponding to the line are shown, whether or not their Unicode names are included, whether or not each glyph on each line is shown, whether or not their glyph names are included, and so on.

Like the QuickDraw mode for ftxruler, the ATSUI mode controls font, point size, line width, and so on in the input file. You can also choose to use CoreGraphics for rendering, or turn antialiasing on or off.

A simple input file would look like this:

]> Hello, world.

The output file is also in XML. If I were to run this file with all the possible options (c, f, g, O, p, P, u), we will see something like this:

19

]>

20 flags="0x08000002" originalOffset="2" realPos="8" />

This format does not lend it self, of course, for easy parsing by human beings, but is ideally suited for use with computer comparison. If the computer detects a change from earlier versions of the font, it’s easy to isolate the difference and find precisely where it took place.

21

ftxruler—QuickDraw

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 two types of input file: one, the original input file format, is used to test a font using QuickDraw; the other is an XML file used to test a font using ATSUI. In both cases, ftxruler works on installed fonts—not font files. You can use a font management utility such as Font Book to install the font you’re working on, if necessary.

When testing a font with QuickDraw, ftxruler takes a single parameter, the input file, which is a text file containing commands to be executed. The input file must be in a text encoding which is an extension of ASCII. In particular, the very first line of the file must be entirely in ASCII. No line may contain any ASCII control codes other than tab, line break, and carriage return.

This makes it possible to use the Unix convention of starting a text file with “#!” followed by the path of the command to execute in order to make the text file itself executable.

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 and their QuickDraw names.

Note that since QuickDraw cannot render all of Unicode, it’s entirely possible to have a font installed on your system which cannot be used with QuickDraw.

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”.

23 As always in , 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.

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

24 #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

#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

25 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 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

26 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.

27

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!

29 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

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

31

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.

33 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.

34 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.

35 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).

36 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.

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

37 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. 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. Addendum

The format for add lists changed with the March 2004 release of the Font Tool Suite, the new format being based on XML. (As always, XML has the significant advantage that the syntax of the data can be checked independently of its use in a font tool.) The new format also allows you to specify which Unicode character the new glyph should be associated with.

Changing from the old format to the new one is relatively straightforward. For example, instead of: 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

You now have:

38 ]>

39

The DTD contains sufficient information to convert other add lists to the new format.

40 About Morph Input Files Introduction ftxanalyzer and ftxenhancer simplify much of the process of adding Apple Advanced Typography 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

41 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

42 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.

43 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 ).

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 “” 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.

44 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 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

45 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.

Determining the order for entries in the ligature subtable can be difficult, because the intermediate forms may interact. For example, if we have the standard:

Type LigatureList Name Ligatures Namecode 1 Setting Common ligatures Settingcode 0 Default no Orientation HV Forward yes Exclusive no

List fi f i fl f l ff f f ffi f f i ffl f f l

The ffi and ffl ligatures will not form as expected. In essence, this is because the glyph sequence will turn into <fi>, and the table doesn’t know to turn <fi> into the ffi ligature. This would imply that the best way to handle the situation is to put the longer strings first in your list of ligatures:

List ffi f f i ffl f f l fi f i fl f l ff f f

In point of fact, things are a little more complex than this. If you examine the ‘morx’ table documentation, you’ll see that ligature subtables are not, in fact, stored internally by lists, but by state tables. This allows for a somewhat more compact format and also provide in theory for contextual ligatures, although contextual ligatures are not

46 supported by ftxenhancer. ftxenhancer translates the list found in your MIF into a state table.

In practice, this means that even reordering your ligature list so that the longer entries come first may not work as expected. If all else fails, remember that you can split the ligature list up into two different lists:

Type LigatureList Name Ligatures Namecode 1 Setting Common ligatures Settingcode 0 Default no Orientation HV Forward yes Exclusive no

List ffi f f i ffl f f l

Type LigatureList Name Ligatures Namecode 1 Setting Common ligatures Settingcode 0 Default no Orientation HV Forward yes Exclusive no

List fi f i fl f l ff f f

The ‘morx’ parsing engine always parses the subtables in order from first in the table to last, and ftxenhancer always translates subtables in the MIF into ‘morx’ subtables, one by one, without changing their order. Splitting the subtable into two thus forces the ‘morx’ parser to see the full list before looking for either of its valid sublists, or . 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.

47 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.

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

48 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 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

49 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 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.

50 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 + 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

51 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. 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

52 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 “kashida-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.

WARNING! As of Mac OS X 10.4, insertion actions do not work, either in ATSUI or in Cocoa. This is a known bug that is planned to be addressed in a future release of Mac OS X. We leave the documentation for them here, but be warned that they will not function properly in your fonts. 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

53 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”. MIF Format—Some general considerations

There can be no doubt but that MIFs are difficult to write. There are some general considerations that can help make things easier or more flexible.

1) Remember that you can always split a subtable into two. So long as the header is repeated exactly, you won’t confuse ftxenhancer and both subtables will be executed with identical feature settings.

We showed an example of this earlier with the ligature table type. To force the text display engine to see certain glyph lists before it sees sublists, we split the subtable into

54 two pieces. This trick is also handy when working with very complex contexts for contextual substitutions. The state table format is powerful and can specify a lot of different contexts; but you may need more than it can do. In this case, just split the subtable into two.

In fact, two different subtables with the same feature and setting do not even need to be the same type. Dave Opstad’s famous “pig-Latin” font took advantage of this to create two subtables, one a rearrangement table (to move the first consonant cluster in a word to its end), and the second an insertion table (to add –ay at the end of each word). (Of course, since insertion actions are broken as of Mac OS X 10.4, this does not currently work.)

2) You can use non-existent glyphs in your font, so long as you make sure they get cleaned up later.

This is an extension of the previous trick.

The ‘morx’ parsing engine doesn’t see glyphs ID’s as anything but numbers; it never checks to see if they are valid or not. So long as what gets handed off to render consists of valid glyph ID’s, you can put invalid intermediates in.

For example, we could use a strange method to form a fi ligature:

Type Contextual Name Ligatures Namecode 1 Setting Standard ligatures Settingcode 0 Default yes Orientation HV Forward yes Exclusive no f f i i

EOT OOB DEL EOL f i StartText 1 1 1 1 2 1 StartLine 1 1 1 1 2 1 Sawf 1 1 3 1 2 4

GoTo Mark? Advance? SubstMark SubstCurrent 1 StartText no yes none none 2 Sawf yes yes none none 3 Sawf no yes none none 4 StartText no yes ChangeF DelI

ChangeF f 32767

DelI i DEL

55 Type Noncontextual Name Ligatures Namecode 1 Setting Standard ligatures Settingcode 0 Default yes Orientation HV Forward yes Exclusive no

32767 fi

In this case, when we see , we turn into the invalid glyph ID 32767 and delete the . Our second subtable now turns glyph 32767 into <fi>.

We can use this trick to work around ftxenhancer’s lack of support for contextual ligatures. We can have the following:

Type Contextual Name Ligatures Namecode 1 Setting Weird ligatures Settingcode 20 Default yes Orientation HV Forward yes Exclusive no a A a c c t t

EOT OOB DEL EOL a c t StartText 1 1 1 1 2 1 1 StartLine 1 1 1 1 2 1 1 SawA 1 1 3 1 2 4 1 SawAc 1 1 5 1 2 1 6

GoTo Mark? Advance? SubstMark SubstCurrent 1 StartText no yes none none 2 SawA no yes none none 3 SawA no yes none none 4 SawAc yes yes none none 5 SawAc no yes none none 6 StartText no yes ChangeCT ChangeCT

ChangeCT c 32767 t 32766

Type Contextual Name Ligatures Namecode 1 Setting Weird ligatures Settingcode 20 Default yes Orientation HV

56 Forward yes Exclusive no c 32767 t 32766 i i o o n n

EOT OOB DEL EOL c t i o n StartText 1 1 1 1 2 1 1 1 1 StartLine 1 1 1 1 2 1 1 1 1 SawC 1 1 2 1 2 3 1 1 1 SawCt 1 1 4 1 2 1 5 1 1 SawCti 1 1 5 1 2 1 1 6 1 SawCtio 1 1 6 1 2 1 1 1 7

GoTo Mark? Advance? SubstMark SubstCurrent 1 StartText no yes none none 2 SawC no yes none none 3 SawCt yes yes none none 4 SawCt no yes none none 5 SawCti no yes none none 6 SawCtio no yes none none 7 StartText no yes ChangeC none

ChangeC 32767 32765

Type LigatureList Name Ligatures Namecode 1 Setting Weird ligatures Settingcode 20 Default no Orientation HV Forward yes Exclusive no

List ct 32767 32766

Type Noncontextual Name Ligatures Namecode 1 Setting Weird ligatures Settingcode 20 Default yes Orientation HV Forward yes Exclusive no

32767 c 32766 t 32765 c

57 This complex example shows how to turn ct into a ct-ligature only when preceded by “a” or “A” and not followed by “ion”. It also illustrates:

3) Don’t forget the DEL glyph!

This is a gotcha which can get even experienced MIF writers. Remember that previous actions may leave the DEL glyph in the middle of your glyph stream. If you’re writing a contextual action, you may find it doesn’t work all the time—when this happens, it’s usually because you’ve forgotten to allow for the fact that the DEL glyph may be part of your context.

Don’t forget that, in particular, the DEL glyph shows up as a part of ligature formation. No morx action reduces the number of glyphs; with the exception of insertions (broken as of Mac OS X 10.4), the glyph count is left the same. We never actually turn the two glyphs into the single glyph <fi>, therefore. Rather, turns into <fi>.

4) Keep subtables in the right order.

We’ve also implicitly taken advantage of this in our examples.

The ‘morx’ parsing engine runs through the ‘morx’ chains and subtables in order, first to last. For each subtable, it checks its flags to see if it should be executed or not and, if it should, completely finishes executing it before it moves on. ftxenhancer puts all your MIF subtables into a single ‘morx’ chain and does so in the order in which they’re found in the MIF, and only ligature subtables get converted to a significantly different form along the way. This means that you control what happens and when by controlling the order of your subtables. ftxanalyzer takes advantage of this when generating its default MIF for a font. The very first thing it does is to generate a series of subtables which convert, to the extent possible, accented glyphs to their precomposed forms. This prevent problems later on.

To give an example, suppose a user has typed the text “fì” using the sequence of Unicode characters . A typical MIF would have provisions to turn the glyphs into <fi>. If this is done before accent composition, we’d end up with the glyphs <fi><`>, which is wrong. Accent composition has to take place first, turning <`> into <ì>, which is correct. MIF Templates

If you’re procuding a number of fonts with consistent glyph names and similar features, you can write a MIF template. This adds functionality to ftxanalyzer, telling it to add support for these features automatically. MIF templates are used by Apple for south Asian scripts such as Devanagari. Apple’s MIF templates live inside the

58 FTX.framework bundle, in FTX.framework/Resources, but ftxanalyzer also looks for them inside /usr/share/ftx/, which is where you should put yours.

There are four pieces to a MIF template.

First, is the file ScriptsWithMIFs.plist. This is a standard Mac OS X plist file list a list of your user-defined MIF templates. Let’s work with a single script, Foobar. Our ScriptsWithMIFs.plist would therefore look like:

Foobar

Second is, for each script in ScriptsWithMIFs.plist, a file called



© 2022 Docslib.org