SourceForge.net Logo 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:

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.

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.