SourceForge.net Logo Home Page Project Page Download CVS repository

Managing large projects

Instructions for large fonts and font families may be split into parts so as to speed compilation for testing purposes, distribute work among members of a team, or create libraries of shared functions. Xgridfit's mechanism for splitting projects is XInclude, the W3C "XML Inclusions" specification. XInclude is extremely flexible and simple to use: it allows you to structure a complex project in a number of ways.

To use XInclude in an Xgridfit file requires just two steps. First, include the XInclude namespace declaration in the <xgridfit> element:

    <xgridfit xmlns:xi="http://www.w3.org/2001/XInclude">
  

Next, to merge part of another file into the file you're editing, add an <xi:include> element:

    <xi:include href="Junicode-Regular-Basic.xgf#xpointer(//glyph)"/>
  

Here the portion of the href attribute before the "#" is a URI (usually just the name of a file in the present directory), and the portion after the "#" is an XPointer (usually a simple XPath expression). In the case above, xpointer(//glyph) pulls in all the <glyph> elements from the file Junicode-Regular-Basic.xgf. An alternative syntax is to use an xpointer attribute on the <xi:include> element:

    <xi:include href="Junicode-Regular-Basic.xgf" xpointer="//glyph"/>
  

In addition, several elements can take an xml:id attribute, and can be included by referencing that id: <xgridfit>, <pre-program>, <function>, <macro>, <glyph>: To fetch this <function> element

    <function name="myfunc" xml:id="jun-reg-myfunc">
       . . .
    </function>
  

use one of these <xi:include> elements:

    <xi:include href="Junicode-Regular-common.xgf" xpointer="jun-reg-myfunc"/>

    <xi:include href="Junicode-Regular-common.xgf#jun-reg-myfunc"/>
  

Some XSLT engines can handle XInclude and others cannot. The XInclude capability in xsltproc (the engine invoked by the xgridfit and xgridfit-ttx shell scripts) is turned on by simply including the parameter --xinclude on the command line (this is done for you in the shell scripts). For some other engines, turning on XInclude capability is an arcane and difficult matter: you must check the documentation for your preferred engine.

Example of a large project

XInclude is flexible enough to permit you to structure your project in many different ways (you must just remember to avoid recursive includes). Here is a simple example involving the Junicode font (complete source code available at the download site).

Instructions for Junicode-Regular are compiled by running xgridfit against a master file, Junicode-Regular.xgf, which contains nothing but <xi:include> elements:

    <?xml version="1.0"?>
    <xgridfit xmlns:xi="http://www.w3.org/2001/XInclude">
      <xi:include href="Junicode-Regular-common.xgf#xpointer(/xgridfit/infile)"/>
      <xi:include href="Junicode-Regular-common.xgf#xpointer(/xgridfit/outfile)"/>
      <xi:include href="Junicode-Regular-common.xgf#xpointer(/xgridfit/constant)"/>
      <xi:include href="Junicode-Regular-common.xgf#xpointer(//control-value)"/>
      <xi:include href="Junicode-Regular-common.xgf#xpointer(//function)"/>
      <xi:include href="Junicode-Regular-common.xgf#xpointer(//macro)"/>
      <xi:include href="Junicode-Regular-common.xgf" xpointer="jun-reg-prep"/>
      <xi:include href="Junicode-Regular-Basic.xgf#xpointer(//glyph)"/>
      <xi:include href="Junicode-Regular-Latin1.xgf#xpointer(//glyph)"/>
      <xi:include href="Junicode-Regular-LatExtA.xgf#xpointer(//glyph)"/>
      <xi:include href="Junicode-Regular-LatExtB.xgf#xpointer(//glyph)"/>
      <xi:include href="Junicode-Regular-IPA.xgf#xpointer(//glyph)"/>
      <xi:include href="Junicode-Regular-SpacMod.xgf#xpointer(//glyph)"/>
      <xi:include href="Junicode-Regular-CombDiac.xgf#xpointer(//glyph)"/>
      <xi:include href="Junicode-Regular-LatExtAdd.xgf#xpointer(//glyph)"/>
      <xi:include href="Junicode-Regular-GenPunct.xgf#xpointer(//glyph)"/>
      <xi:include href="Junicode-Regular-PUA.xgf#xpointer(//glyph)"/>
      <xi:include href="Junicode-Regular-NoEncode.xgf#xpointer(//glyph)"/>
    </xgridfit>
  

The file Junicode-Regular-common.xgf contains no <glyph> elements, but only global elements: <infile>, <outfile>, <constant>, <control-value>, <function>, <macro>, <pre-program>. These are included with the first seven xi:include elements (the <pre-program> is included by xml:id) Eleven more files contain only <glyph> elements organized by Unicode range. Each of the twelve files validates against the Relax NG schema xgridfit-strict.rnc.

When working with any particular Unicode range, most or all of the other <xi:include> elements can be commented out in the master file, speeding compilation. If more than one developer were working on this font, the file Junicode-Regular-common.xgf might be controlled by the lead developer so as to avoid conflicts introduced by individual contributors, who when necessary would submit patches on that file for approval.

Shared functions and libraries

You very likely have some favorite functions that you insert in all your fonts. In addition, similar members of a font family (such as Bold and Bold Italic) are likely to share functions. For a library of shared functions, simply create an Xgridfit program file in which the only children of the <xgridfit> element are <function> elements. An Xgridfit program file can very easily merge the functions from this library anywhere in the sequence of your own functions:

    <function name="local-function">
      . . .
    </function>

    <xi:include href="My-Library.xgf#xpointer(//function)"/>

    <function name="another-local-function">
      . . .
    </function>
  

Alternatively, you can merge a single function from the library if you have supplied that function with an xml:id attribute:

    <function name="local-function">
      . . .
    </function>

    <xi:include href="My-Library.xgf#set-left-sidebearing"/>

    <function name="another-local-function">
      . . .
    </function>
  

Note that the included function must be called by its required name attribute and not by the xml:id attribute, which is needed only when a function is merged, before it gets compiled. The name and xml:id attributes should probably be the same when both are present.