Xgridfit
Author: Peter S. Baker

Home Page Project Page Download CVS repository

Preparing files for merging How xgfmerge merges files The Storage Area Instructing composite glyphs XIncludes from other files Merging multiple files Example

# Collaborating with the FontForge auto-instructor

The method described here is deprecated, though it does still work. For a simpler method, click this link.

Recent versions of FontForge do an excellent job of "writing" instructions for TrueType fonts. You have only to follow these simple steps:

1. Use Hints-->Remove Instr Tables to delete everything relating to TrueType instructions.
2. Use Element-->Font Info-->PS Private to insert "BlueValues," "OtherBlues" and "BlueFuzz."
3. In Font View, type Ctrl-A to select all glyphs.
4. Use Hints-->AutoHint to add hints to the font.
5. With all glyphs still selected, use Hints-->AutoInstr to add instructions to the font.

Now, if you generate the font and view it with ftview, you will see that your font is well "hinted."

But auto-instructing may not please you for every glyph. You may want finer control over the most commonly displayed characters in your font, or you may want to add deltas and other refinements to the instructions generated by FontForge. If so, Xgridfit comes with tools that make it easy to collaborate with the FontForge auto-instructor. The steps to follow are straightforward:

1. Generate an Xgridfit program (call it `file-a.xgf`) from the auto-instructed font created by FontForge (see Converting Existing Instructions).
2. Write your own glyph programs (functions, macros and anything else) in one or more separate files (`file-b.xgf` and possibly others), and/or copy FontForge glyph programs that you wish to revise into these files.
3. When you have completed your own programming and revisions, merge `file-a.xgf` and the other files using `xgfmerge`, a utility supplied with Xgridfit.
4. Compile the merged file as usual and run the generated FontForge script to create a font containing a mix of auto-instruction and custom programming.

Note that, while the method outlined here was developed with the FontForge auto-instructor in mind, it should be useful for any TrueType font that contains instructions, if you wish to maintain your own added or revised instructions in separate files.

Details and complications are described in the following sections.

## Preparing files for merging

The file here called `file-a.xgf` is an Xgridfit program extracted from a font containing instructions generated by FontForge. Once you have created this file you should not edit it, though you may open it to copy out control values and glyph programs.

The other files (we'll pretend there is just one, `file-b.xgf`) constitute an Xgridfit program that you have written. There are several restrictions on this file. Any functions it contains should not have the `num` attribute, as these are not compatible with the <legacy-functions> element that `file-a.xgf` almost certainly contains. In general, it should not already contain legacy programming—that is, programming taken from an existing font using TTX and `ttx2xgf`. This is because two <legacy-functions> elements cannot be merged, and because hard-coded (numerical) references to control values and functions will break in this file (but not in `file-a.xgf`) when the two files are merged.

If `file-b.xgf` contains only a little legacy programming, the situation is not hopeless. You can convert numerical references to control values and functions into symbolic ones pretty easily. You'll need to search for MIRP and MIAP instructions and change the <push> elements that precede them. For example, this sequence:

        <push>5 10</push>
        <command name="MIRP" modifier="11100"/>

could become this (remembering that, since control values are indexed from zero, the <control-value> with index 10 will actually be the eleventh <control-value> in the list):

        <push>5 lc-vert-stem</push>
        <command name="MIRP" modifier="11100"/>

Likewise function numbers in <push> elements can be replaced with function names.

You can use XIncludes and the <no-compile> element in `file-b.xgf` to import glyph programs and other material from `file-a.xgf`. These are ignored when xgfmerge runs (see below for XIncludes from other files).

## How `xgfmerge` merges files

When you run `xgfmerge`, it applies these rules in merging `file-a.xgf` and `file-b.xgf`:

- <glyph-select>, <infile>, <outfile>, <outfile-base> and <outfile-script-name> are taken from `file-b.xgf` if available; if not, they are taken from `file-a.xgf`.
- <no-compile> is ignored unless you ask for it via the `-n` option. The <no-compile> element in the merged file will contain all the <glyph> elements contained in the <no-compile> elements of all the files being merged. Duplicate <glyph> elements are omitted.
- If a <default> element with attribute `type="legacy-storage"` is present in `file-a.xgf` (and it probably is), its value is compared with the value of a <default> element with `type="max-storage"` (if present) in `file-a.xgf`. The greater of these, which may be no less than 64, is added to the value of a <default> element with `type="max-storage"` in `file-b.xgf` (this is also not permitted to be less than 64). This sum (which may not be less than 128) becomes the value of a new <default> element with `type="max-storage"`.
- The value of a <default> element with `type="max-stack"` in `file-a.xgf` is compared with the same element in `file-b.xgf`, and the larger is used as the value of a new <default> element with `type="max-stack"`. If either <default> element is not present the default value of 256 is assumed; if the result of the comparison is 256, no <default> element is generated.
- Other <default> elements are copied from `file-b.xgf` when available, otherwise from `file-a.xgf`.
- Global <constant>, <alias>, <variable> or <round-state> elements are taken from `file-b.xgf` when available. Any of these elements in `file-a.xgf` whose `name` elements do not clash with those in `file-b.xgf` are also taken.
- <control-value> elements from `file-a.xgf` are all retained in their original order. However, if a <control-value> in `file-b.xgf` has the same name as one in `file-a.xgf`, its value is used instead of the one from `file-a.xgf`.
- <control-value> elements from `file-b.xgf` are all retained, positioned after the ones from `file-a.xgf`. Any <control-value> with the same name as one in `file-a.xgf` is skipped, since that one has already been inserted above.
- The <legacy-functions> element from `file-a.xgf` is copied exactly. `file-b.xgf` should not contain <legacy-functions>.
- <function> elements from `file-a.xgf` are retained, though there probably should be none. Any <function> with the same name as one in `file-b.xgf` is skipped.
- <function> elements from `file-b.xgf` are retained.
- <macro> elements are treated like <function> elements.
- The <pre-program> is constructed by merging programming from `file-a.xgf` and `file-b.xgf`. First <alias> and <variable> elements are copied from both places (though there should be none in `file-a.xgf`), then programming from `file-a.xgf` is copied, and finally programming from `file-b.xgf`. If the `-p` option is present, the <pre-program> from `file-b.xgf` is substituted for the one in `file-a.xgf`, if available; if not, the one in `file-a.xgf` is retained.
- <glyph> elements from `file-a.xgf` are copied, but any whose `ps-name` attribute matches that of a <glyph> in `file-b.xgf` is skipped.
- <glyph> elements from `file-b.xgf` are copied.

These rules are designed to produce a file in which two basically independent sets of glyph programs coexist peacefully. If the programming in `file-b.xgf` has been correctly written (without hard-coded references to control values, functions and the storage area), the merger should be invisible to end-users. Complications, inevitable in such an undertaking as this, are discussed below.

## The Storage Area

Xgridfit and its utilities are extremely cautious about the TrueType Storage Area, which is where Xgridfit stores information about the graphics state and the variables you declare. The reason for this caution is that, when insufficient storage is declared in an Xgridfit program, strange bugs can appear in areas of the program apparently unrelated to storage. So the default size of the Storage Area for Xgridfit programs is 64 (though few Xgridfit programs need so much), and `ttx2xgf` always reserves at least 64 storage locations for "legacy storage" in a converted font, no matter what information it finds in the font itself. The minimum storage reserved in an Xgridfit program produced by `xgfmerge` is 128.

This is almost certainly more storage than you need, especially since the FontForge auto-instructor claims to use none at all. Before generating a production version of your font, you may wish to experiment with the <default type="legacy-storage"> and <default type="max-storage"> elements in your merged Xgridfit file. Try commenting out the <default type="legacy-storage"> element; if the value of <default type="max-storage"> is 64, see how much you can reduce it before your programming breaks.

## Revising FontForge's instructions

You can revise the instructions generated by FontForge, refining them or inserting deltas. The recommended method is to copy the glyph program you want to revise from `file-a.xgf` to `file-b.xgf` and revise it there (start by deleting the `init-graphics` attribute if you plan to insert any Xgridfit programming). Copying the <glyph> will protect it from being overwritten if you run the auto-instructor again.

There is a danger, however, that references to control values and functions will become obsolete if you re-run the auto-instructor and regenerate `file-a.xgf`. The best solution, of course, would be to do this work late enough that it is not necessary to run the auto-instructor again. If you must, however, you can take several steps to protect this programming. Here are some tips.

- Use XInclude to import control values from `file-a.xgf`. The <xi:include> element that does this must come before any <control-value> elements in `file-b.xgf`. Insert <alias> elements in `file-b.xgf` referring to these <control-values>, and use comments to indicate their original values, e.g.

      	<alias name="ff-cv-ab" target="cv-01"/> <!-- 345 -->

  Finally, locate the references to control values in the glyph program(s) you have copied from `file-a.xgf` and change them to refer instead to the aliases you've made. You can locate the places that need revision by searching for MIRP and MIAP instructions:

      	<push>5 ff-cv-ab</push>
      	<command name="MIRP" modifier="11111"/>

  Now, if you have to re-run the auto-instructor, you only need to check your list of <aliases> and edit it if necessary.
- Use XInclude to import <legacy-functions> from `file-a.xgf`. Use <constant> elements to create named references to the functions contained in <legacy-functions>, and revise the <push> elements that immediately precede CALL and LOOPCALL instructions:

      	<push>1 ff-func-aa</push>
      	<command name="CALL"/>

  If you have to re-run the auto-instructor, you only need to check these <constant> elements.
- You may (or may not) find it useful to name some points in the <glyph> programs you've pasted from `file-a.xgf`. If so, simply insert <constant> elements into the glyph programs after you've pasted them.

You can freely mix Xgridfit programming with the <push> and <command> elements imported from `file-a.xgf`. You can substitute high-level Xgridfit elements for these low-level elements, and you can add <delta> and any other elements you like.

## Instructing composite glyphs

FontForge does not auto-instruct glyphs that are made of references to other glyphs. Yet it is often desirable to write some minimal instructions for these, to make sure that accents do not collide with base characters and are correctly positioned horizontally. When you instruct glyphs that have been auto-instructed by FontForge, programming for the accent and base glyph is likely to be in `file-a.xgf` while programming for the composite glyphs is in `file-b.xgf`. This raises special problems—at least if, as recommended, you avoid editing `file-a.xgf`, which contains only automatically generated code.

The method recommended here is that you use XInclude to import into <no-compile> the programs for the glyphs that are the targets of the references in your composite glyph. Then, since you cannot insert <constant> elements in those target glyph programs, make some useful <constant> elements: some global and others in the composite glyph itself, as appropriate. Thus:

        <no-compile>
          <xi:include href="file-a.xgf#a"/>
          <xi:include href="file-a.xgf#macron"/>
        </no-compile>

        <constant name="a-top" value="34"/>
        <constant name="a-total" value="56"/>
        <constant name="macron-bottom" value="3"/>
        <constant name="macron-left" value="5"/>

        <glyph name="amacron">
          <constant name="mark-bottom" value="a-total + macron-bottom"/>
          <constant name="mark-left" value="a-total + macron-left"/>
          <constant name="mark-contour" value="2"/>
          <set-vectors axis="y"/>
          <call-function name="ensure-diacritic-gap">
            <with-param name="char-top" value="a-top"/>
            <with-param name="diacritic-bottom" value="mark-bottom"/>
            <with-param name="diacritic-contour" value="mark-contour"/>
          </call-function>
          <set-vectors axis="x"/>
          <delta>
            <point num="mark-left"/>
            <delta-set size=3" distance="8"/>
            <delta-set size=5" distance="8"/>
          </delta>
          <shift>
            <reference>
    	  <point num="mark-left"/>
    	</reference>
    	<contour num="mark-contour"/>
          </shift>
        </glyph>

## XIncludes from other files

The sections above assume that all of your XIncludes come from `file-a.xgf`. It is a minor complication if some of your XIncludes come from that file and some from elsewhere (e.g. a library of functions or another font). If this is the case, use xgfmerge's `-x` option to resolve XIncludes before merging files:

        $ xgfmerge -x file-a.xgf file-b.xgf > new-file.xgf

The `-x` option causes xgfmerge to suppress any XIncludes from `file-a.xgf`; only those from other files are included. Note, however, that for XIncludes from `file-a.xgf` to be suppressed, the filename on the command line must be identical with that in the `href` attribute of the <xi:include> element. If one of these is, say, the name of a symlink, or if the form in the `href` attribute is `file-a.xgf` while that on the command line is `./file-a.xgf`, then xgfmerge will not recognize that the two filenames refer to the same file.

Xgfmerge does not copy <xi:include> elements literally into the merged file. It must either resolve them (only in files other than `file-a.xgf`) or ignore them.

## Merging multiple files

Xgfmerge is happy to merge multiple files with the one automatically generated file named first on the command line. Given a command line like this one:

        $ xgfmerge -o final.xgf file-a.xgf file-b.xgf file-c.xgf

the merge program is first run for `file-a.xgf` and `file-b.xgf`, and then once more for the result of the first merge and `file-c.xgf`. You can use wildcard filenames (e.g. `MyFont*.xgf`) as well as a list.

As explained above, the rules for the first file in the list (`file-a.xgf`) are different from those for the second (`file-b.xgf`). When you merge multiple files, "file-b" rules are applied to all files after the first in the list, and "file-a" rules are applied to all the intermediate results. It's as if you ran these two commands:

        $ xgfmerge -o intermediate.xgf file-a.xgf file-b.xgf
        $ xgfmerge -o final.xgf intermediate.xgf file-c.xgf

The rules applied by xgfmerge are meant to be friendly to such multiple merges; and yet the program may at times operate with unnecessary redundancy, raising the possibility of error. This is particularly true when the `-x` option is used to bring in XIncludes. Then, since you are likely to have imported, say, <control-value> elements into all your files, these will be merged over and over again. The result should not be duplicate <control-value> elements, and yet it seems worthwhile to avoid such redundancy.

You can do so if you have routinely used the "compile-globals" default to suppress compilation of global elements. In general, <control-value>, <function> and other global elements should be compiled in only one of the files that constitute the programming for a single font. This element suppresses it in the others:

        <default type="compile-globals" value="no"/>

If you include the `-c` option on the `xgfmerge` command line, the program will look for that <default> element in each file after the first, and it will ignore those global elements in any file where it is found. In general, you should consider using the `-c` option whenever you are merging multiple files with the `-x` option.

## Example

For an example, see Tutorial 3.