Advanced Search
Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

About Morph Input Files

Introduction

The AAT Font Tool simplifies much of the process of adding Apple Advanced Typography intelligence to a font. You just drag the font onto the AAT Font Tool icon, and just like magic the font becomes an AAT-rich font, with intelligence to do common ligatures, case conversion, kerning, and so on, in many different writing systems.

But sometimes you would like to add AAT features for glyphs which aren't in the AAT Font Tool's pre-canned repertoire. For example, suppose you have a font with unique ligatures -- a "Gr" ligature, say. Since this ligature isn't in the AAT Font Tool's standard repertoire, the AAT Font Tool 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.

With the AAT Font Tool, you now have a way to add virtually any kind of feature to a font. To do this, you tell the AAT Font Tool 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 to eight glyphs into a single new glyph. AAT Font Tool 1.2 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 new AAT Font Tool 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

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 launch the AAT Font Tool, choose the "Append from Morph Input..." command and point it to your MIF, then "Open and Process..." the font and you're done. Once the font is dragged into the Fonts folder, you can use it with a 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. Some example files are included in the AAT Font Tool folder.

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 the AAT Font Tool 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.

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 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 (no internal punctuation).

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

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

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

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

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

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

MIF Format -- Noncontextual

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

MIF Format -- Ligature List

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

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

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

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

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

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

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

Ignore
                    damma
                    kasra
                    fatha

List
                    lammeeminitial      laminitial meemmedial
                    lamjeeminitial      laminitial jeemmedial

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

Warning: you should only include glyphs in the "Ignore" list which are designated as floaters in the font's property table.

MIF Format -- State Tables

The remaining three kinds of feature require MIFs that are considerably more complex than the simple ones we've discussed so far. A common element in all of the remaining kinds of MIF is the state table. AAT uses state tables to allow fonts to have intelligence built-in, so that applications don't have to do the work of processing the text themselves.

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

           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.

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

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

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. There are two kinds of insertion this table can specify: "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.

MIF Format -- Rearrangement

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

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

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

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

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

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

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