xgridfit/0000755000175000017500000000000011572451660011725 5ustar peterpeterxgridfit/Makefile0000644000175000017500000001032311354676727013377 0ustar peterpeter#!/usr/bin/make -f # # Makefile by Kestutis Biliunas 2007 # Revised by Peter Baker 2007-2009 # Contributions by Nicolas Mailhot 2009 # SHELL=/bin/bash include version.mk DESTDIR = PREFIX = /usr/local # %{_bindir} in rpm speak BINDIR = $(PREFIX)/bin # %{_datadir}/xml in rpm speak XMLDIR = $(PREFIX)/share/xml #%{_mandir} in rpm speak MANDIR = $(PREFIX)/share/man # Could be changed to $(XMLDIR)/$(PACKAGE)-$(VERSION) MAINDIR = $(XMLDIR)/$(PACKAGE) install: @install -d -m 0755 $(DESTDIR)$(BINDIR) @install -p -m 0755 bin/* $(DESTDIR)$(BINDIR) @which python > /dev/null ; \ if [ $$? -eq 0 ] ; then \ PYTHONPROG=`which python` ; \ for file in $(DESTDIR)$(BINDIR)/{ttx2xgf,xgfconfig,xgfmerge,xgfupdate,xgridfit,getinstrs} ; do \ sed -i -e "s|@xgridfit_dir@|${MAINDIR}|g" -e "s|@version@|$(VERSION)|" -e \ "s|@python_prog@|$$PYTHONPROG|" $$file ; done ; \ else \ echo "Python is required for xgridfit." ; \ rm -f $(DESTDIR)$(BINDIR)/{ttx2xgf,xgfconfig,xgfmerge,xgfupdate,xgridfit,getinstrs} ; \ fi @install -d -m 0755 $(DESTDIR)$(MAINDIR)/{lib,schemas,utils} @for dir in lib schemas utils ; do \ install -p -m 0644 $$dir/* $(DESTDIR)$(MAINDIR)/$$dir ; \ done @for file in $(DESTDIR)$(MAINDIR)/schemas/*.xml ; do \ sed -i "s|@xgridfit_dir@|${MAINDIR}|g" $$file ; \ done @install -d -m 0755 $(DESTDIR)$(MANDIR)/man1 @install -p -m 0644 man/*.1 $(DESTDIR)$(MANDIR)/man1 @cd python ; python setup.py install --root=$(DESTDIR)/ @echo "Xgridfit installed successfully." install-mac: @install -d -m 0755 $(DESTDIR)$(BINDIR) @install -p -m 0755 bin/* $(DESTDIR)$(BINDIR) @which python > /dev/null ; \ if [ $$? -eq 0 ] ; then \ PYTHONPROG=`which python` ; \ for file in $(DESTDIR)$(BINDIR)/{ttx2xgf,xgfconfig,xgfmerge,xgfupdate,xgridfit,getinstrs} ; do \ sed -i "" -e "s|@xgridfit_dir@|${MAINDIR}|g" -e "s|@version@|$(VERSION)|" -e \ "s|@python_prog@|$$PYTHONPROG|" $$file ; done ; \ else \ echo "Python is required for xgridfit." ; \ rm -f $(DESTDIR)$(BINDIR)/{ttx2xgf,xgfconfig,xgfmerge,xgfupdate,xgridfit,getinstrs} ; \ fi @install -d -m 0755 $(DESTDIR)$(MAINDIR)/{lib,schemas,utils} @for dir in lib schemas utils ; do \ install -p -m 0644 $$dir/* $(DESTDIR)$(MAINDIR)/$$dir ; \ done @for file in $(DESTDIR)$(MAINDIR)/schemas/*.xml ; do \ sed -i "" "s|@xgridfit_dir@|${MAINDIR}|g" $$file ; \ done @install -d -m 0755 $(DESTDIR)$(MANDIR)/man1 @install -p -m 0644 man/*.1 $(DESTDIR)$(MANDIR)/man1 @cd python ; python setup.py install --root=$(DESTDIR)/ @echo "Xgridfit installed successfully." install-docs: @mkdir -p $(DESTDIR)$(PREFIX)/share/doc/$(PACKAGE)/html @cp docs/* $(DESTDIR)$(PREFIX)/share/doc/$(PACKAGE)/html @echo "Xgridfit documentation installed in $(DESTDIR)$(PREFIX)/share/doc/" install-all: $(MAKE) -f Makefile install $(MAKE) -f Makefile install-docs install-all-mac: $(MAKE) -f Makefile install-mac $(MAKE) -f Makefile install-docs uninstall: rm -f $(DESTDIR)$(MAINDIR)/lib/* rmdir $(DESTDIR)$(MAINDIR)/lib rm -f $(DESTDIR)$(MAINDIR)/schemas/* rmdir $(DESTDIR)$(MAINDIR)/schemas rm -f $(DESTDIR)$(MAINDIR)/utils/* rmdir $(DESTDIR)$(MAINDIR)/utils rmdir $(DESTDIR)$(MAINDIR) rm -f $(DESTDIR)$(MANDIR)/man1/$(PACKAGE).1* rm -f $(DESTDIR)$(MANDIR)/man1/xgfupdate.1* rm -f $(DESTDIR)$(MANDIR)/man1/ttx2xgf.1* rm -f $(DESTDIR)$(MANDIR)/man1/xgfconfig.1* rm -f $(DESTDIR)$(BINDIR)/$(PACKAGE) rm -f $(DESTDIR)$(BINDIR)/xgfupdate rm -f $(DESTDIR)$(BINDIR)/ttx2xgf rm -f $(DESTDIR)$(BINDIR)/xgfconfig rm -f $(DESTDIR)$(BINDIR)/xgfmerge rm -f $(DESTDIR)$(BINDIR)/getinstrs uninstall-docs: rm -f $(DESTDIR)$(PREFIX)/share/doc/$(PACKAGE)/html/* rmdir $(DESTDIR)$(PREFIX)/share/doc/$(PACKAGE)/html rmdir $(DESTDIR)$(PREFIX)/share/doc/$(PACKAGE) uninstall-all: $(MAKE) -f Makefile uninstall $(MAKE) -f Makefile uninstall-docs dist: $(MAKE) -f Makefile clean tar -C .. -zcvf $(PACKAGE)-$(VERSION).tar.gz \ --exclude=CVS --exclude=*.tar.bz2 --exclude=.* --exclude=*.*~ \ --exclude=*~ --exclude=*.tar.gz $(PACKAGE) clean: rm -f *.tar.gz *.*~ *~ rm -f bin/*~ rm -f docs/*.*~ rm -f lib/*.*~ rm -f schemas/*.*~ rm -f utils/*.*~ rm -f man/*.*~ .PHONY: install install-mac install-docs install-all install-all-mac \ uninstall uninstall-docs uninstall-all dist clean xgridfit/ChangeLog0000755000175000017500000007356711572445466013533 0ustar peterpeter2011-06-04 Peter Baker * Makefile: Minor message change. * xgridfit.rnc, xgridfit.rng, xgridfit.xsd: set-dropout-control threshold max is 255. 2010-03-30 Peter Baker * Makefile: added --root option to setup.py install * xgridfit-python.xsl, xgflib.py: restored functionality of -S option in Python mode. * xgflib.py: fixed bug that caused script to crash when numerical options were used. * *.html: Updates various docs to reflect changes in 2.2. 2010-03-28 Peter Baker * ttx2xgf, xgfconfig, xgridfit, xgflib.py, setup.py: Most of the Bash scripts of version 2.1 and earlier have been rewritten as Python scripts depending on a Python library, xgflib.py. libxml2 and its Python bindings are now required. * xgfconfig: The config system has changed significantly: see man page for details. In general, xgridfit now searches through a priority list to find an appropriate processor or validator; xgfconfig changes the order of the priority list (new) and specifies the location of jar files (as before). The config file is now XML. * xgridfit: Validation is now performed by default. Use --skip-validation option to, er, skip validation. * *.xsl: Code for passing macro and glyph parameters has been rewritten to allow nested and recursive calls. There are not a lot of limitations on how macros and glyph programs can call each other. * points.xsl: line, set and range elements are now allowed as the content of macro and glyph param elements. * xgridfit.rnc, xgridfit.rng, xgridfit.xsd: line, set and range elements are now allowed as the content of macro and glyph param elements. * prep.xsl: Fixed a bug that could cause a TrueType program generated by merge-mode to write to the wrong storage area. 2009-12-18 Peter Baker * getinstrs: New utility uses FontForge Python extension to extract instructions from a font; presents them as valid Xgridfit code. * xgridfit-merge.xsl, xgridfit-python.xsl: outfile-script-name and outfile-script-base don't make any sense when the output is Python. * *: Xgridfit namespace http://xgridfit.sourceforge.net/Xgridfit2 is now required on the xgridfit element. Use xgfupdate to add it automatically. * xgfupdate: Now mainly takes care of adding namespace in xgridfit and xi:include elements; use option -v 1 to make it do what it used to do. * ttx2xgf, xgfmerge: Now namespace-aware. * ff-functions.xgf: File contains macros that provide access to the functions inserted into a font by the FontForge auto-instructor. These functions are well crafted and extremely useful! * xgridfit-merge.xsl, xgridfit: Data can now be saved in a file instead of in font.persistent. So data can still be available when project is saved as ttf. Use -F option or element to name the datafile. * xgridfit-merge.xsl: auto-instruct now skips any glyphs that are going to be installed by the script: less redundancy. * xgridfit-python.xsl: when compile-globals=no (-c no), Python code leaves global elements completely undisturbed. Assumes indexes to functions, control-values, storage area are correct! * xgridfit-merge.xsl: when compile-globals=no (-c no), merge-mode leaves global elements completely undisturbed. Looks for font.persistent data or the same in a file so it can fix up indexes; exits with a message if it can't find what it needs. The idea is that one should be able to run first the script with global elements, then any number of scripts containing just glyph programs. * xgridfit.xsl, xgridfit-python.xsl, xgridfit-merge.xsl, xgridfit-debug.xsl: Check for xgridfit namespace and issue helpful message if not found. * catalog.xml: Local catalog entries for schemas. * xgridfit.xml: Possible entries for global catalog. But our installer does not install these! * Makefile: Various changes, refinements to support 2.1 changes; Makefile now has an install-mac command to support Mac OS (where sed has slightly different options). * docs/*.html: Lots of minor revisions re: namespace; extensive revision of merge-mode documentation. * xgridfit.xsd: XML Schema generated automatically from xgridfit.rnc. Why not, since XML Schema can do most of what Relax NG can do? * xgridfit: Can control choice of output language with environment variable XGRIDFIT_OUTPUT_LANG, set to either ff or py. 2009-12-01 Peter Baker * numbers.xsl, *.xsl: Replace get-number-literal and push-value with a single named template, expression, for resolving all numbers. * xgridfit-python.xsl: Exception handling means that script does not always stop on error, but rather displays a message. We no longer make super-long lines. * xgridfit-merge.xsl: Merge-mode generates a script that cleanly merges Xgridfit instuctions with existing instructions in any font. * xgridfit-merge.xsl: Can now set blue values (or any PS private dictionary entry) via the ps-private element. * numbers.xsl, xgfdata.xml: There were significant bugs in the way some templates addressed the storage area, and errors in xgfdata.xml. * xgridfit*.xsl, std-vars.xsl: Some standard variables (which do not differ among the various modes) are defined in std-vars.xsl, imported by all modes. * flow.xsl, numbers.xsl: we can force cv indexes to show up as numbers in compile-if element even in merge-mode: allows evaluation of cv indexes for compatitibility with older code. * function.xsl: bug fix: default code in param element was not getting compiled. * function.xsl: we no longer try to check the correctness of with-param elements in call-macro and call-glyph. This is better done by the schema. * function.xsl: code passed to a macro via with-param was not always getting compiled. * xgridfit: Python is now the default output; new options to support mrge-mode. * xgridfit.rnc, xgridfit.rng: schema support for ps-private and a few new attribues to support merge-mode. * Makefile: changes to support Fedora contributed by Nicolas Mailhot; revisions and addition of SHELL directive ensure that it works with Ubuntu/Debian. * all: Files now moved from /usr/[local/]share/ to /usr/[local/]share/xml. 2009-06-18 Peter Baker * xgridfit.rnc, xgridfit.rng: I forgot to update the schemas for 1.19a, so this is done in 1.19b. * xgridfit.xsl, xgridfit-debug.xsl, xgridfit-python.xsl, convert-ttx.xsl: The correct setting for MaxFunctionDefs is one higher than the highest function number, NOT the number of function definitions (as the spec says, and as permitted by FreeType). This means that we have no use for a count of function definitions, and we can use MaxFunctionDefs in any correctly formed font as the first number for Xgridfit's pre- and user-defined functions. However, it is still recommended that users check the legacy-functions element after running ttx2xgf. 2009-06-09 Peter Baker * numbers.xsl: store-value was flummoxed if asked to store to a variable or control-value passed to a macro as a param. Now it can handle these cases. * convert-ttx.xsl: This script used to produce a silly empty function as a template for others. It got in the way of using ttx2xgf in Makefiles. Now it's gone. 2009-01-31 Peter Baker * xgfconfig, defaults.xml: Configuration utility now uses locate to try to find needed jar file if it doesn't find it in /usr/share/java. * xgridfit: typo disabled -b option; now corrected. * xgridfit.1: Error explaining -f option; now fixed. * install.html, xgfconfig.1: takes into account the minor changes in xgfconfig. 2009-01-06 Peter Baker * xgfmerge, merge.xsl: Now is happy to merge a series of file with the main target file (the first in the list). Rules somewhat refined so that an element in file-a is replaced by an equivalent in file-b, but kept if there is no equivalent. * xgfmerge, sort-glyphs.xsl: glyphs can be sorted in output file. * xgfmerge: -o option causes output to be saved in a file. * xgridfit: New -f option pipes output of Xgridfit compiler directly to FontForge. * xgridfit, xgfconfig, configure.xsl, defaults.xml: The system of templates that Xgridfit uses to generate command lines includes an "outfile-template"; this allows the outfile parameter to the XSLT processor to be omitted, causing output to be sent to stdout and allowing it to be piped to FontForge. Downside is that anyone who has run xgfconfig to choose a processor has to run it again, since the old template no longer works. * tutorial3.html: New tutorial shows by example how to fix up a glyph auto-instructed by FontForge. 2008-12-27 Peter Baker * ttx2xgf: Fix of test for ttx file, which was being done too soon. * xgfmerge, xinclude.xsl: minor refinements; and xgfmerge can now execute XIncludes in "file-b" before performing the merge. XIncludes whose source is "file-a" are automatically excluded. * xgridfit: More routine output suppressed when -q option is present. 2008-12-24 Peter Baker * xgridfit, *.xsl, xgfdata.xml: Default color can be set with a command-line option or with default element (type="color"); it should affect default in command element where color bits are used. New round-gray() operator added. Internal renaming of variables to make this all work. * xgridfit, ttx2xgf, xgfupdate: Better file checking in executables. * xgfmerge, merge.xsl: new utility for merging Xgridfit programs. * fontforge.html: new doc on collaborating with the FontForge auto-instructor. * numbers.xsl: get-number-literal can now resolve a function name to a number. Useful in push elements. * messages.xsl: silent-mode takes a string parameter instead of an expression. * convert-ttx.xsl: ttx2xgf now puts an xml:id attribute on every glyph element. It is the same as the ps-name attribute, except for ".notdef" which has a name that is not a valid xml:id. 2008-12-12 Peter Baker * xgfconfig, configure.xsl, defaults.xml, xgridfit: a new system for configuring Xgridfit: instead of choosing among different Xgridfit binaries for the different XSLT processors, use a new utility, xgfconfig, to choose processors and also validators. This writes a configuration file to be read by the xgridfit Bash script, which then invokes the right processor and validator. The specialized xgridfit executables (xgridfit-saxon-6, etc.) have been removed, and also the script choose-processor. * xgridfit: new -x option suppresses compilation (use when only validation is needed). New -e option echoes command lines before they are executed (for debugging). * xgridfit: minor changes promote Mac friendliness. * xgridfit.xsl, xgridfit-debug.xsl, flow.xsl: 4xslt didn't like the way exslt:document was used. Fixed that, and now 4xslt runs fine, tho slowly (old XPath problems apparently fixed). * defaults.xml: Xgridfit now works with the 4xslt processor and with Jing, MSV, RNV and xmlstarlet validators. 2008-12-07 Peter Baker * xgridfit.rnc, xgridfit.rng: Xgridfit schemas extensively rewritten, providing improved checking of correctness of Xgridfit programs. Users should at least use -V option to take advantage of this. * xgridfit-saxon-6: Corrected a bug that made it impossible to keep temp files. * xgridfit.1: minus signs were not escaped. * graphics.xsl: set-dropout-control requires number literals. * schema.html: New documentation explaining whys and hows of the Xgridfit schema. * reference.html: Schema fragments removed, since the new organization of the schema makes this uninformative. Each entry for an element has instead "Content" and "Attributes" sections explaining what is required or allowed. 2008-11-22 Peter Baker * xgridfit.xsl, xgridfit-debug.xsl, numbers.xsl, graphics.xsl, function.xsl, prep.xsl, primitives.xsl, func-predef.xsl: New mechanism for handling leading newlines. We don't try to guess where they won't be wanted, but just generate them and peel them off when necessary. * xgridfit.xsl, xgridfit-debug.xsl: init-graphics parameter to control whether graphics variable tracking is initialized at the beginnings of glyph programs. * xgridfit (and related files): G option controls init-graphics param. * convert-ttx.xsl: We now supply attribute init-graphics="no" for each glyph. * prep.xsl, function.xsl, xgridfit.xsl, xgridfit-debug.xsl: New variant element allows for variant versions of functions to be defined in the cvt program. * numbers.xsl, graphics.xsl: New set-control-value and with-control-value elements for setting control values with either pixel units or font units. * xgridfit.rnc, xgridfit.rng: Some tightening of rules to better capture requirements of language. 2008-11-07 Peter Baker * numbers.xsl, primitives.xsl: push-list element had to look at with-leading-newline to avoid breaking legacy-functions element. 2008-11-04 Peter Baker * *.xsl: Deprecated elements and attributes have now been removed. * *.xsl: All templates that need to place multiple numbers on the stack now use a single, well-optimized routine, push-list. * xgridfit.xsl, xgridfit-debug.xsl, numbers.xsl: push-break parameter causes long push instructions to be broken up. By default it is delta-break * 2. * xgfdata.xml: This file was not committed before last release, so point operator was non-functional. * xgridfit-transitional.rnc, .rng: removed. * xgridfit-strict.rnc, .rng: renamed to xgridfit.rnc, xgridfit.rng. * xgridfit (and variants): Validation now only against xgridfit.rng; so -V option does not take an argument. * xgridfit (and variants): -p option specifies a value for push-break. * xgridfit variants (those that use xmllint for Xinclude processing): These now use mktemp to create a temporary file when needed. 2008-10-13 Peter Baker * function.xsl: Reorganized code for pushing function parameters onto stack before call: macro and glyph params and now visible from inside call-function elements. * numbers.xsl: macro and glyph params were not visible in some expressions. This is now fixed. * numbers.xsl, xgfdata.xsl: There is now a point operator that causes its argument to be treated just like the num attribute of a point element. * move-els.xsl: min-amount attribute on diagonal-stem element is now deprecated. Use of it generates a warning message (use xgfupdate to fix it). * points.xsl: Requirement that distance attribute of move element must be the name of a control-value element is relaxed so that function parameter can be used. * xgridit-strict.rnc: obsolete offset attribute on point and with-param elements removed; obsolete min-amount attribute on diagonal-stem removed. Use xgfupdate to update files that used these. * xgf-update.xsl: This script (accessed from the xgfupdate shell script) now updates an Xgridfit program file to the current version, rather than to version 1.0. 2008-08-17 Peter Baker * xgridfit-saxon-6, xgridfit-saxon-9, xgridfit-xalan-c, xgridfit-xalan-j, xgridfit-xsltproc: executables for specific processors. These may be copied to xgridfit before installation. * choose-processor: a script for selecting one of five supported XSLT processors for running Xgridfit. * xgridfit: -V option runs xmllint to validate program file before compilation. * xgridfit-strict.rng, xgridfit-transitional.rng: Relax NG schemas, long form, for use by xmllint. * xgridfit-transitional.dtd: an old fashioned DTD for those who want it. * xgridfit-saxon-6, xgridfit-saxon-9, xgridfit-xalan-c, xgridfit-xalan-j: When processor is not xsltproc, xmllint may be run so that XIncludes can be done. -T option names a temporary file in which to store results of running XInclude. * xgridfit-saxon-6, xgridfit-saxon-9, xgridfit-xalan-j: -j option specifies a classpath for the Java virtual machine. * messages.xsl: Line numbers are now displayed with warnings and error messages when the processor is xsltproc, saxon-6, saxon-9, xalan-j. Space added above and below warnings and above errors to make them look better when Xalan is the processor. 2008-08-06 Peter Baker * xgridfit-saxon-6: Added experimental executable that uses Saxon 6.5.5 (the version packaged with Ubuntu) rather than xsltproc. * delta.xsl: Deltas now correctly process a control value with index over 255 and a point with number over 255 * delta.xsl: delta element can now start with a default point, so point can often be omitted in delta-set element. * function.xsl: It is now possible to pass code to a macro or glyph program in a parameter. 2008-07-29 Peter Baker * delta.xsl: Fixed bug that prevented compilation of delta nested in move element when compile-if attribute was present. * func-predef.xsl: Fixed a bug that sometimes caused RUTG to be set instead of ROFF. * graphics.xsl: Fixed a bug that causes the wrong round state to be restored after move with round attribute. * move-els.xsl: min-distance attribute of element diagonal-stem now takes a value like move, not just yes|no. * xgfdata.xml, numbers.xsl: added read-only values for access to GETINFO; also constants to test for various engine versions. * misc.xsl, numbers.xsl: Added getinfo element. * numbers.xsl: added permanent debugging code. 2008-04-06 Peter Baker * xgridfit: -O option specifies the name of an output file, rather than the default. * xgridfit.xsl: infile and outfile elements are now independent: an outfile element is functional even if infile is not present, and outfile is not assumed from infile. * xgridfit.xsl, xgridfit-default.xsl: compile-globals param and default/@type and prevent cvt, fpgm, prep and maxp from being compiled. * xgridfit.xsl, xgridfit-debug.xsl: Parameters and options to support use of Xgridfit in Makefiles: -S output separate file for each glyph; -c suppress compilation of functions, control-values, pre-program, maxp entries. * xgridfit.xsl, xgridfit-debug.xsl, numbers.xsl, function.xsl: If enclosed in a no-compile elements, glyph is visible for reference purposes but is not compiled. * xgridfit.xsl, xgridfit-debug.xsl, flow.xsl: -g (glyph-select) option overrides no-compile element; -c option now requires yes|no value. * xgridfit.xsl: Xgridfit now saves the output of the outfile element in a separate script file when the -S option is present. Use the -z option or the outfile-script-name element to name this file. * xgridfit-strict.rnc, xgridfit-transitional.rnc: Schemas brought up to date with no-compile, outfile-base, outfile-script-name elements. Also compile-globals default type. 2008-03-06 Peter Baker * numbers.xsl: alias element for accessing things under different names. * xgridfit.xsl: glyph element can now be treated as a macro. It can take parameters (including a special "offset" parameter automatically added to all point numbers) and be called from any glyph program via the call-glyph element. This is intended to support those who prefer not to use the TrueType component mechanism. * graphics.xsl: restore-default element for restoring default values of graphics variables. * function.xsl: Improved setting up of variable frame: it is set up only when needed, and saved/altered only when necessary. A small efficiency. * move-els.xsl: Fixed bug that caused some deeply nested move elements to misbehave. * *.xsl: various minor efficiencies and improvements. 2008-02-09 Peter Baker * function.xsl: We now check to make sure the function we are trying to call actually does exist. * function.xsl: Code that pushes function parameters onto the stack rewritten for neatness and improved optimization: we now push all numbers with a single instruction whenever all params can be resolved at compile time (before this was true only for bytes). * flow.xsl, xgridfit.xsl, xgridfit-debug.xsl: Compile a single glyph, as in last release, or a list of glyphs. On command line, separate glyph-names with a plus-sign. Or in the program file, use a glyph-select element, separating glyphs with either a plus-sign or spaces. Can't use space separator on the command line. * message.xsl: We now display line numbers with warning and error messages. Only if Saxon line-number extension function is supported (it is in xsltproc). 2008-01-28 Peter Baker * xgridfit: All Xgridfit's XSLT params are now accessible via the command-line of the xgridfit executable. Debug mode is available. Multiple files can now be compiled with one command. * *.xsl: Hooks for debug mode added to all elements that produce code. * xgridfit-debug.xsl: New Xgridfit file implements debug mode. * xgridfit.xsl, xgridfit-debug.xsl: It is now possible to compile a single glyph. * messages.xsl: no-warning element suppresses warning messages for all code it contains. 2008-01-19 Peter Baker * move-els.xsl, move-lib.xsl: Wholly revised code that rounds points after an interpolate or shift. We now use low-level instructions to do the rounding, avoiding all problems with changed reference pointers. There is no need to save and restore RP0, RP1 and RP2, so all that code has been deleted. 2008-01-15 Peter Baker * move-els.xsl: Fixed a bug that caused RP0 to be wrongly restored after an interpolate or shift with rounding embedded in a move element. * move-els.xsl: RP1 and RP2 must sometimes be saved before rounding an interpolated point and restored afterwards. 2008-01-08 Peter Baker * flow.xsl: Fixed a bug that caused else to be wrongly interpreted when compile-if was nested in if. * move-els.xsl, numbers.xsl: Fixed a bug that sometimes made the compiler fail when evaluating point numbers in glyph/constant format. * move-els.xsl: An optional round attribute for interpolate and shift cause points to be rounded to the grid after being interpolated or shifted. Works only on point elements, not range or set. Revision to move element prevents this feature from messing up handling of RP0 when interpolate or shift is nested. * numbers.xsl, xgfdata.xml: Added four new operators for obtaining the coordinates of points in expressions: x-coord, initial-x-coord, y-coord, initial-y-coord. * numbers.xsl, xgfdata.xml: Added two new operators for obtaining the distance between two points in expressions: -- for the current outline and --- for the original outline. * xgfdata.xml, expressions.xsl: -- and --- are now fourth-precedence operators. All operators that were fourth-precedence are now fifth-precedence. 2008-01-01 Peter Baker * xgfdata.xml, expressions: Added operators: round-black and round-white round a value with "colors"; coord returns the current coordinate of a point (depending on projection vector); initial-coord returns the coordinate of a point at the beginning of the glyph program. 2007-12-24 Peter Baker * numbers.xsl, expressions.xsl: Fixed a bug that caused compiler to fail when evaluating expressions like round(stem-width / 2.0). 2007-11-17 Peter Baker * ttx2xgf: A new executable creates an Xgridfit file from a TTX file in one step. * xgfupdate, xgf-update.xsl, add-blanks.sed: A new executable, with supporting scripts, updates any Xgridfit file < version 1.0 to version 1.0. * *.xsl: All container elements (, , , , , , ) are no longer necessary and are deprecated. * *.xsl: "id" attribute deprecated in function, macro, control-value, variable: use "name" instead. "function-id," "macro-id," "param-id" attributes deprecated: use "name" instead. The change is required for function, macro and control-value. * numbers.xsl: "num" attribute for is deprecated: use "value" instead. * xgridfit-ttx, misc.xsl: TTX mode is removed. "max-instructions" default type is deprecated and is no longer consulted; asm element is no longer permitted: use convert-asm.sed script to convert to command elements. * function.xsl: "param-set" not always required in call-function and call-macro if there is only one set of parameters. * xgridfit-strict.rnc, xgridfit-transitional.rnc: xgridfit.rnc is removed. Now the "strict" schema requires all changes to Xgridfit language, while the "transitional" schema allows features that have been deprecated but not removed. * numbers.xsl, xgridfit.xsl: Variable can be assigned a default value via "value" attribute. * numbers.xsl: A bug interfered with passing variable name as parameter to a macro. * *.xsl: Switched to using key (fast indexing) to locate control-value, function and macro elements. * xgridfit.xsl: "fmflags" attribute on passes flags to FontForge "Generate" command. * xgridfit.xsd, xgridfit.dtd: DTD and XML schemas no longer provided. Get Trang and make your own! 2007-10-15 Peter Baker * move-els.xsl, points.xsl, func-predef.xsl, xgridfit-ttx.xsl, xgridfit.xsl: Added flip-on and flip-off elements, which move ranges of points on and off of lines; also a new predefined function to make sure the parameters to the corresponding TrueType instructions are always in the right order. * points.xsl: It is now possible to pass a set, line or range to a macro by defining it as the child of a with-param element. * function.xsl: Function and macro parameters are checked for validity by the compiler, since the schema is a bit vague. * func-predef.xsl: Fixed a bug that would have kept round states from being correctly restored in some circumstances. 2007-09-30 Peter Baker * *.xsl: Internal cleanups and improvements: conflating templates that didn't have to be separate. * *.xsl: Implemented new set element: an arbitrary collection of points. * *.xsl: programming for range and line elements recast, so that they (along with set) can now be passed by name to macros as parameters. * numbers.xsl: new operator nan makes it possible to detect when an expression can't be resolved at compile time. Useful for detecting macro parameters. * *.doc: updated documentation to reflect these changes. Also more examples in reference.html. 2007-09-15 Peter Baker * numbers.xsl: Increased the number of operators evaluated at compile time. Includes and or not + - = != < <= > >=. * move-els.xsl: multiple delta, align, interpolate, shift and move elements are now permitted inside a move element. compile-if attributes are implemented for all elements permitted inside a move. * flow.xsl: a compile-if element permits conditional compilation. It can include an else element as the last child. * delta.xsl: compile-if attribute now permitted on a delta element. * functions.xsl: (from July: it somehow didn't get into the ChangeLog then). Implemented parameterized macros. 2007-01-13 Peter Baker * move-lib.xsl, graphics.xsl: Fixed a bug that would sometimes have prevented round states from being inherited properly when move elements were nested. 2007-01-13 Peter Baker * convert-asm.sed, convert-ttx.xsl: Scripts for creating a new Xgridfit program file from a font containing instructions (requires TTX). * deltas.xsl: It's now possible to embed delta elements in move elements. The first delta is executed before any shifts, aligns or interpolations; the second is executed after. If a delta within a move element lacks a point element, it operates on the point that is the child of the move. A delta element may be empty. * move-els.xsl: Move elements can now be nested: nested move elements take the point in the parent move as a reference point (if no reference/point is present), and they do not leave RP0 set behind them. * deltas.xsl: A long push before a DELTAP or DELTAC instruction now is broken into segments; the size of the segments can be set via the delta-break param or default. * numbers.xsl: A new index operator gets an index of (pointer to) a control value or variable in contexts where the value would normally be returned. This permits passing function parameters by reference rather than by value. * xgfdata.xml: A new variable operator treats the argument as the index of a variable and returns the value. * function.xsl: New legacy-function element contains function definitions inherited from a font that was converted for use with Xgridfit. * primitives.xsl: New to-stack element takes any value and places it on the stack: much more flexible than the push element, but it cannot push multiple values. * xgridfit.xsl, xgridfit-ttx.xsl: Corrected bug that could sometimes prevent setting defaults. 2006-03-16 Peter Baker * xgridfit-ttx.xsl: This file adds TTX mode, which merges compiled instructions into a TTX file (an XML representation of a font). * xgridfit-ttx: A simple script for running Xgridfit in TTX mode in Linux. * delta.xsl: Delta code cleaned up to be more portable. * xgridfit.xsl: Hook for delta code removed as no longer necessary. * xgridfit, xgridfit-ttx: Simple scripts revised so that file extensions matter less. xgridfit will handle extensions .xgf or .xml; xgridfit-ttx will handle .xgf, .xml or .ttx. 2006-03-07 Peter Baker * xgridfit.xsl: The script generated by Xgridfit now can read and write TrueType font files as well as FontForge source files. * xgridfit.xsl: profile/infile and profile/outfile added so that changes need not be written back to the same file. profile/font-file is now deprecated. * xgridfit.xsl: params always override corresponding entries in profile. * xgridfit.xsl: param var-max-storage is renamed max-storage. Its value can never be less than 24. * delta.xsl, xgridfit.xsl: All FontForge-specific code now in xgridfit.xsl * schemas: profile/infile and profile/outfile added. * xgridfit.dtd: Documentation removed from xgridfit.dtd (use element reference instead). xgridfit/lib/0000755000175000017500000000000011572451641012472 5ustar peterpeterxgridfit/lib/xgridfit.xsl0000644000175000017500000006254511572446750015063 0ustar peterpeter 25 64 256 10 !!nofile!! !!nofile!! !!nofile!! !!nofile!! \n \n \n 0 " [ ] You may not push more than 255 numbers at one time. 01 10 00 1 0 1 0 When setting a vector, the "axis" attribute must be either "x" or "y." 1 0 1 0 1 0 1 0 0 1 A <pre-program> element must be present, even if empty. Open(" ") No font file specified. You may have to edit the script or run it in the FontForge GUI. ClearTable("cvt") i=0 while ( i< ) FindOrAddCvtIndex( 2*i ) ++i endloop ReplaceCvtAt( , ) AddInstrs("fpgm",1, ") Saving to file Your XSLT engine does not support -S (outfile_base) SetMaxpValue("TwilightPntCnt", ) SetMaxpValue("StorageCnt", ) SetMaxpValue("MaxStackDepth", ) 0 SetMaxpValue("FDEFs", ) Saving to file Your XSLT engine does not support -S (outfile_base) Save() Save(" ") Generate(" " ,"", ) Unrecognized file extension . No file will be saved. AddInstrs("prep",1, ") x Compiling glyph AddInstrs(" ",1, ") xgridfit/lib/xgridfit-merge.xsl0000644000175000017500000013030111572446750016142 0ustar peterpeter 25 64 256 !!nofile!! !!nofile!! !!nofile!! \n \n\ [ ] You may not push more than 255 numbers at one time. push( ) 01 10 00 1 0 1 0 When setting a vector, the "axis" attribute must be either "x" or "y." 1 0 1 0 1 0 1 0 0 1 { } ^ ^ CURRENT_FONT.private[' '] = , the BlueFuzz value, is not a number CURRENT_FONT = fontforge.open(" ") No font file specified. You must do so before running this script. if CURRENT_FONT.persistent == None: CURRENT_FONT.persistent = dict() XGRIDFIT_DICTIONARY = dict() MAXP_DICTIONARY = dict() if DELETE_ALL or AUTO_INSTR: # Remove all existing instructions, including fpgm and prep. # Zero out all maxp entries, and build an empty xgridfit # dictionary. XGRIDFIT_DICTIONARY = dict() for g in CURRENT_FONT.glyphs(): g.ttinstrs = "" CURRENT_FONT.setTableData('cvt', None) CURRENT_FONT.setTableData('fpgm', None) CURRENT_FONT.setTableData('prep', None) CURRENT_FONT.maxp_FDEFs = 0 CURRENT_FONT.maxp_storageCnt = 0 CURRENT_FONT.maxp_twilightPtCnt = 0 CURRENT_FONT.maxp_maxStackDepth = 0 extract_font_globals() XGF_DICT_ALTERED = True else: # We may be working with a clean font, but assume we're not. # Get the xgridfit dictionary, if one exists; if not, build it try: XGRIDFIT_DICTIONARY = pickle.load(open(' ', 'r')) except IOError: try: XGRIDFIT_DICTIONARY = CURRENT_FONT.persistent['xgridfit'] except (KeyError, TypeError): XGRIDFIT_DICTIONARY = dict() extract_font_globals() XGF_DICT_ALTERED = True try: XGRIDFIT_DICTIONARY = pickle.load(open(' ', 'r')) CURRENT_FONT.persistent['xgridfit'] XGRIDFIT_FUNCTION_NUMS = XGRIDFIT_DICTIONARY['xgffunc'] CVT_DICTIONARY = XGRIDFIT_DICTIONARY['cvt'] MAXP_DICTIONARY = XGRIDFIT_DICTIONARY['omaxp'] except IOError: except (KeyError, TypeError): print "There is no Xgridfit dictionary for this font, but this script" print "requires one. Try first using Xgridfit's merge-mode to compile" print "an Xgridfit program containing functions, control-values and" print "pre-program, run that Python script, and then try this again." sys.exit(1) if AUTO_INSTR: # If autohint, we've already cleaned out the font. Autohint # those glyphs for which we do not have Xgridfit instructions # and populate the Xgridfit dictionary. for g in CURRENT_FONT.glyphs(): if g.glyphname not in GLYPH_DICT: auto_instr_glyph(g.glyphname) extract_font_globals() def extract_font_globals(): # Set up the private xgridfit dictionary, which stores the # original state of the font's programming. If we get a # chance, we'll store this in the sfd file. global MAXP_DICTIONARY XGRIDFIT_DICTIONARY['oprep'] = CURRENT_FONT.getTableData("prep") XGRIDFIT_DICTIONARY['ofunc'] = CURRENT_FONT.getTableData("fpgm") if XGRIDFIT_DICTIONARY['oprep'] == None: del XGRIDFIT_DICTIONARY['oprep'] if XGRIDFIT_DICTIONARY['ofunc'] == None: del XGRIDFIT_DICTIONARY['ofunc'] XGRIDFIT_DICTIONARY['omaxp'] = MAXP_DICTIONARY = dict() MAXP_DICTIONARY['fdefs'] = CURRENT_FONT.maxp_FDEFs MAXP_DICTIONARY['storage'] = CURRENT_FONT.maxp_storageCnt MAXP_DICTIONARY['twilight'] = CURRENT_FONT.maxp_twilightPtCnt MAXP_DICTIONARY['stack'] = CURRENT_FONT.maxp_maxStackDepth def get_xgridfit_dictionary(dict_key): try: this_dict = XGRIDFIT_DICTIONARY[dict_key] except KeyError: XGRIDFIT_DICTIONARY[dict_key] = this_dict = dict() return this_dict def find_cvt_value(val): if len(CURRENT_FONT.cvt) == 0: return(-1) else: return(CURRENT_FONT.cvt.find(val)) def install_cvt(name, value, index): try: index = int(index) except ValueError: pass tmpindex = -1 try: tmpindex = CVT_DICTIONARY[name] except KeyError: if isinstance(index, int): if index >= len(CURRENT_FONT.cvt): index = 'append' else: tmpindex = index if index == 'auto': tmpindex = find_cvt_value(value) if tmpindex < 0: tmpindex = len(CURRENT_FONT.cvt) CURRENT_FONT.cvt += (value,) CVT_DICTIONARY[name] = tmpindex if CURRENT_FONT.cvt[tmpindex] != value: print "The value of control-value", name, "does not match that in the" print "control-value table in the FontForge file. Updating the value." print "old value: ", CURRENT_FONT.cvt[tmpindex] print "new value: ", value CURRENT_FONT.cvt[tmpindex] = value def replace_from_dict(target_string, delimiter, dicty): for thiskey in dicty.keys(): keystring = delimiter + thiskey + delimiter if target_string.find(keystring) >= 0: try: target_string = \ target_string.replace(keystring, str(dicty[thiskey])) except KeyError: print "Cannot resolve value ", thiskey, "." print "Have you run the script that would install functions" print "and control-values in this font?" sys.exit(1) return target_string def replace_with_add(source, dea, deb, addn): while source.find(dea) >= 0: target = source[source.find(dea):source.find(deb) + 1] nums = target[1:len(target) - 1] source = source.replace(target, str(int(nums) + addn)) return source def make_push_string(push_list, push_type): push_string = "PUSH" + push_type if len(push_list) <= 8: push_string = push_string + "_" + str(len(push_list)) else: push_string = "N" + push_string + INST_NEWLINE + str(len(push_list)) for num in push_list: push_string = push_string + INST_NEWLINE + str(num) return push_string def fix_pushes(pstr): while pstr.find("push(") >= 0: op_start = pstr.find("push(") string_before = pstr[:op_start] string_after = pstr[op_start:] op_end = string_after.find(")") push_count = int(string_after[5:op_end]) string_after = string_after[op_end+2:] push_type = "I" push_list = list() push_string = "" while push_count > 0: sep_loc = string_after.find(INST_NEWLINE) if (sep_loc >= 0): this_num = int(string_after[:sep_loc]) string_after = string_after[sep_loc+1:] else: this_num = int(string_after) string_after = "" if (this_num >= 0 and this_num <= 255): new_type = "B" else: new_type = "W" if push_type != new_type: if len(push_list) > 0: push_string += \ make_push_string(push_list, push_type) + INST_NEWLINE push_list = list() push_type = new_type push_list.append(this_num) push_count = push_count - 1 if len(push_list) > 0: push_string += make_push_string(push_list, push_type) if not push_string.endswith(INST_NEWLINE): push_string += INST_NEWLINE pstr = string_before + push_string + string_after if pstr.endswith(INST_NEWLINE): pstr = pstr[:len(pstr)-1] return pstr def legacy_twi_pts(): try: return MAXP_DICTIONARY['twilight'] except (KeyError, TypeError): return 0 def legacy_stack(): try: return MAXP_DICTIONARY['stack'] except (KeyError, TypeError): return 256 def legacy_storage(): try: return MAXP_DICTIONARY['storage'] except (KeyError, TypeError): return 0 def fix_instructions(instrs): return fix_pushes(replace_from_dict(replace_from_dict(\ replace_with_add(instrs, "{", "}", legacy_storage()), \ "%", XGRIDFIT_FUNCTION_NUMS), "^", CVT_DICTIONARY)) def auto_instr_glyph(name): if AUTO_HINT: CURRENT_FONT[name].autoHint() CURRENT_FONT[name].autoInstr() def install_glyph_program(name, instrs): try: CURRENT_FONT[name].ttinstrs = \ fontforge.parseTTInstrs(fix_instructions(instrs)) except TypeError as detail: print "Warning: can't install instructions for glyph ", name print detail except ValueError as detail: print "Warning: can't install instructions for glyph ", name print detail A <pre-program> element must be present, even if empty. import fontforge import sys import pickle INST_NEWLINE = " " DELETE_ALL = True False # In merge-mode delete_all works only when compile_globals=yes AUTO_INSTR = True False # In merge-mode auto_instr works only when compile_globals=yes AUTO_HINT = True False COMBINE_PREP = True False XGF_DICT_ALTERED = False # These are the instructions for the glyphs in this font. GLYPH_DICT = { , \ } CVT_DICTIONARY = get_xgridfit_dictionary('cvt') XGF_CVT = ( , (" ", , " auto ") ) for n, v, f in XGF_CVT: install_cvt(n, v, f) XGRIDFIT_DICTIONARY['cvt'] = CVT_DICTIONARY XGF_FUNCTIONS = (("__fn0__"," "), ("__fn1__"," "), ("__fn2__"," "), ("__fn3__"," ") , (" ", " ") ) # functions with variants: we do not install them in fpgm XGF_VAR_FUNCTIONS = ( (" ", "."), ) None # try to get legacy or auto-generated function code. try: CURRENT_FUNCTION = MAXP_DICTIONARY['fdefs'] except KeyError: CURRENT_FUNCTION = 0 try: ALL_FUNCTION_CODE = fontforge.unParseTTInstrs(XGRIDFIT_DICTIONARY['ofunc']) except KeyError: ALL_FUNCTION_CODE = "" # Assign numbers to Xgridfit functions. XGRIDFIT_FUNCTION_NUMS = dict() for fname, finstrs in XGF_FUNCTIONS: XGRIDFIT_FUNCTION_NUMS[fname] = CURRENT_FUNCTION CURRENT_FUNCTION += 1 if XGF_VAR_FUNCTIONS != None: for fvname, fvinstrs in XGF_VAR_FUNCTIONS: XGRIDFIT_FUNCTION_NUMS[fvname] = CURRENT_FUNCTION CURRENT_FUNCTION += 1 # Done with populating XGRIDFIT_FUNCTION_NUMS dictionary. Keep it # in Xgridfit dictionary. XGRIDFIT_DICTIONARY['xgffunc'] = XGRIDFIT_FUNCTION_NUMS # fix up and install the functions that go in the fpgm table. for finame, fiinstrs in XGF_FUNCTIONS: if len(ALL_FUNCTION_CODE) == 0: ALL_FUNCTION_CODE = fix_instructions(fiinstrs) else: ALL_FUNCTION_CODE = ALL_FUNCTION_CODE + INST_NEWLINE + \ fix_instructions(fiinstrs) if len(ALL_FUNCTION_CODE) > 0: CURRENT_FONT.setTableData("fpgm", \ fontforge.parseTTInstrs(ALL_FUNCTION_CODE)) CURRENT_FONT.maxp_FDEFs = CURRENT_FUNCTION # try to get legacy or auto-generated prep code. try: OLD_PREP_CODE = fontforge.unParseTTInstrs(XGRIDFIT_DICTIONARY['oprep']) except KeyError: OLD_PREP_CODE = "" if COMBINE_PREP and (len(OLD_PREP_CODE) > 0): ALL_PREP_CODE = OLD_PREP_CODE + INST_NEWLINE + fix_instructions(XGF_PREP) else: ALL_PREP_CODE = fix_instructions(XGF_PREP) CURRENT_FONT.setTableData("prep", fontforge.parseTTInstrs(ALL_PREP_CODE)) # Install the Xgridfit glyph programs. for ps_name, instrs in GLYPH_DICT.iteritems(): install_glyph_program(ps_name, instrs) # Our maxp entries. if legacy_twi_pts() > : CURRENT_FONT.maxp_twilightPtCnt = legacy_twi_pts() else: CURRENT_FONT.maxp_twilightPtCnt = CURRENT_FONT.maxp_storageCnt = + legacy_storage() if legacy_stack() > : CURRENT_FONT.maxp_maxStackDepth = legacy_stack() else: CURRENT_FONT.maxp_maxStackDepth = ' ( , , ) if XGF_DICT_ALTERED: try: pickle.dump(XGRIDFIT_DICTIONARY, open(' ', 'w')) except IOError: print "Couldn't write the data file!" if XGF_DICT_ALTERED: try: CURRENT_FONT.persistent['xgridfit'] = XGRIDFIT_DICTIONARY except TypeError: print "Warning: font.persistent is not a dictionary, so I can't" print "store any data there. Names of control-values and the" print "font's original fpgm, prep and other data will be lost" print "after this run. To save this data in a separate file," print "use the datafile element or the -F option." CURRENT_FONT.save() CURRENT_FONT.save(" ") CURRENT_FONT.generate(" " ,flags= ) Unrecognized file extension . No file will be saved. XGF_PREP = " " x Compiling glyph ' ': ' ' xgridfit/lib/move-lib.xsl0000644000175000017500000005233411572446750014750 0ustar peterpeter In the MIRP instruction round state cannot be "on" and CVT cut-in "off." Rounding will not be used. In the MIAP instruction round state cannot be "on" and CVT cut-in "off." Rounding will not be used. xgridfit/lib/xgridfit-debug.xsl0000644000175000017500000005553611572446750016151 0ustar peterpeter 25 64 256 10 !!nofile!! !!nofile!! !!nofile!! 0 [ ] You may not push more than 255 numbers at one time. black white gray orthog parallel x y When setting a vector, the "axis" attribute must be either "x" or "y." rnd no-rnd rp0 no-rp0 rp0, min, rnd, rp1 rp2 grid orig =" " < > </ > < > </ > /> < > </ > /> < /> A <pre-program> element must be present, even if empty. <!-- Functions begin here --> <!-- Functions end here --> Saving to file Your XSLT engine does not support -S (outfile_base) <maxp> TwilightPntCnt= StorageCnt= MaxStackDepth= 0 FDEFs= </maxp> x Compiling glyph xgridfit/lib/func-predef.xsl0000644000175000017500000010252111572446747015434 0ustar peterpeter xgridfit/lib/arithmetic.xsl0000644000175000017500000003332511572446747015374 0ustar peterpeter Left-hand parameter missing in call to . Trying to use value from stack. Right-hand parameter missing in call to . Trying to use value from stack. No destination for result of instruction. Leaving value on the stack. Parameter missing in call to . Trying to use value from stack. No destination for result of instruction. Leaving value on the stack. The "result-to" attribute in a <control-value-index> instruction must be the name of a variable. No place to store control value index. It will be left on the stack. Nothing to do with result of formula. The value may be left on the stack. xgridfit/lib/points.xsl0000644000175000017500000013306711572446750014555 0ustar peterpeter rp-a-o-res: rp-a-res: rp-b-o-res: rp-b-res: Can't resolve range with ref " " "Ref" attribute in range points nowhere. Range must contain either two points or a "ref" attribute. All num attributes on points in a set must resolve to numbers at compile time. Can't resolve macro param Cannot resolve ref " " in set Cannot resolve ref " " in set A <set> must either have a ref attribute or contain one or more points. Can't resolve line with ref " Cannot resolve line with ref A line element must contain either two points or a ref attribute. Invalid line ref= name= Can't find a point to move or alter in < > instruction. xgridfit/lib/move-els.xsl0000644000175000017500000012702411572446750014764 0ustar peterpeter Illegal reference-ptr attribute in shift element: Zone must be either "glyph" or "twilight." There must be two "relative-to" points, if any, in an interpolate instruction. yes NaN NaN yes xgridfit/lib/xgfdata.xml0000644000175000017500000003506711276104727014646 0ustar peterpeter SMD SMD SCVTCI SCVTCI SSW SSWCI SSW SSWCI SDB SDB SDS SDS RTG RTHG RTDG RDTG RUTG ROFF 0 64 128 0 16 32 48 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 AND OR EQ GTEQ LTEQ GT LT NEQ ADD SUB MUL DIV MD MD ODD EVEN FLOOR CEILING ABS NEG NOT ROUND ROUND ROUND ROUND RCVT RS GC GC GC GC GC GC no-op no-op no-op xgridfit/lib/numbers.xsl0000644000175000017500000027625711572446750014725 0ustar peterpeter M B W NaN - - - - - - - - - - - - - - - - - - - - - - Recursion level - - - - - - "expression" called from location Evaluating expression " " permitted: crash-on-fail: to-stack: cvt-mode: Can't find value for param " " in macro " " There is no glyph to match " " NaN 0 NaN Cannot resolve value NaN Can't find value for param " " in macro " " custom-round-state can be written to only via <set-round-state> and <with-round-state>. The value this program has attempted to write to it is being discarded. round-state can be written to only via <set-round-state> and <with-round-state>. The value this program has attempted to write to it is being discarded. It is not permitted to write to the default graphics variable except in the <pre-program>. The value this program has attempted to write to it is being discarded. Could not store value . It will be left on the stack. WCVTF WCVTP push-list has nothing to do! Z B W Can't identify type of list-component " " xgridfit/lib/std-vars.xsl0000644000175000017500000000573511312513370014765 0ustar peterpeter Either the xgridfit element is missing or it lacks the required namespace declaration. Run xgfupdate on this file to correct. # Program generated by Xgridfit, version # Don't edit this file unless you are very sure of what you're doing. xgridfit/lib/graphics.xsl0000644000175000017500000014042211572446750015032 0ustar peterpeter Illegal zone specifier S VTCA S VTL No input for vector-setting command. I'm assuming that the needed values are available on the stack. No input for vector-setting command. Doing nothing. Warning: nowhere to store vector. I'm leaving the values on the stack. Attempting to set delta shift: illegal value " " Unknown "period" attribute Unknown "phase" attribute Unknown "threshold" attribute bad parameter for get-vector-letter: pixel font Can't resolve control-value " " pixel font Unknown attribute value name=" " in <restore-default> xgridfit/lib/misc.xsl0000644000175000017500000000557411572446750014175 0ustar peterpeter < > can be used only in the <pre-program>. It is being ignored. No place to store result of GETINFO. It will be left on the stack. xgridfit/lib/measure.xsl0000644000175000017500000000632111572446750014672 0ustar peterpeter xgridfit/lib/function.xsl0000644000175000017500000010723111572446750015060 0ustar peterpeter $$no-value$$ Function " " not found <param> in function " " lacks a name. Cannot find a value for <param> " ". 1xmpfvnc 1xmpvnc Encountered <call-function> element without name. Function returns a value, but I can find no place to put it (no "result-to" attribute). It is being left on the stack. The return value of a function cannot be read unless the attribute return="yes" is present. I am ignoring the "result-to" attribute of this call to function . or A function variant may not have a name attribute and may not contain param or variable elements. Encountered <function< lacking name attribute. Encountered a <call-macro> without name. Can't find macro Cannot find glyph program with psname=" " v g f m No code to execute for param : doing nothing Cannot find param to call xgridfit/lib/prep.xsl0000644000175000017500000003363411572446750014206 0ustar peterpeter xgridfit/lib/xgridfit-python.xsl0000644000175000017500000006605311572446750016400 0ustar peterpeter 25 64 256 !!nofile!! !!nofile!! !!nofile!! !!nofile!! \n \n\ 0 [ ] You may not push more than 255 numbers at one time. 01 10 00 1 0 1 0 When setting a vector, the "axis" attribute must be either "x" or "y." 1 0 1 0 1 0 1 0 0 1 A <pre-program> element must be present, even if empty. import fontforge CURRENT_FONT = fontforge.open(" ") No font file specified. Use an infile element to identify a font to add instructions to. for g in CURRENT_FONT.glyphs(): g.ttinstrs = "" CURRENT_FONT.setTableData('cvt', None) CURRENT_FONT.setTableData('fpgm', None) CURRENT_FONT.setTableData('prep', None) CURRENT_FONT.maxp_FDEFs = 0 CURRENT_FONT.maxp_storageCnt = 0 CURRENT_FONT.maxp_twilightPtCnt = 0 CURRENT_FONT.maxp_maxStackDepth = 0 def install_glyph_program(name, instrs): try: CURRENT_FONT[name].ttinstrs = fontforge.parseTTInstrs(instrs) except TypeError as detail: print "Warning: can't install instructions for glyph ", name print detail except ValueError as detail: print "Warning: can't install instructions for glyph ", name print detail CURRENT_FONT.cvt = ( , ) CURRENT_FONT.setTableData('fpgm', fontforge.parseTTInstrs(' ')) Saving to file Your XSLT engine does not support -S (outfile_base) CURRENT_FONT.maxp_twilightPtCnt = CURRENT_FONT.maxp_storageCnt = CURRENT_FONT.maxp_maxStackDepth = 0 CURRENT_FONT.maxp_FDEFs = Saving to file Your XSLT engine does not support -S (outfile_base) ( , ' ' , ) CURRENT_FONT.save() CURRENT_FONT.save(" ") CURRENT_FONT.generate(" " ,flags= ) Unrecognized file extension . No file will be saved. CURRENT_FONT.setTableData('prep', fontforge.parseTTInstrs(' ')) x Compiling glyph install_glyph_program(" ", " ") xgridfit/lib/primitives.xsl0000644000175000017500000002607211572446750015431 0ustar peterpeter Empty push or to-stack element is not permitted. Unrecognized instruction in <command> element. gray parallel x 1 Nothing to do in <command> with <modifier>. This should not happen! xgridfit/lib/expressions.xsl0000644000175000017500000002324111572446747015621 0ustar peterpeter Closing parenthesis without opening parenthesis. NaN xgridfit/lib/flow.xsl0000644000175000017500000001362011572446747014206 0ustar peterpeter Saving to file Your XSLT engine does not support -S (outfile_base) , \ Cannot resolve attribute test=" " in <compile-if> xgridfit/lib/delta.xsl0000644000175000017500000001351611572446747014334 0ustar peterpeter ; ; point( Cannot find a point for <delta-set>. ) ; xgridfit/lib/messages.xsl0000644000175000017500000000610211572446750015035 0ustar peterpeter Line . Line . Line . Internal error: Error: Please report this error on xgridfit-users@lists.sourceforge.net. Warning: xgridfit/COPYING0000644000175000017500000006363710643720710012770 0ustar peterpeter GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! xgridfit/man/0000755000175000017500000000000011572451641012477 5ustar peterpeterxgridfit/man/ttx2xgf.10000644000175000017500000000276011326436103014165 0ustar peterpeter.TH TTX2XGF 1 "2009-12-18" .SH NAME .B ttx2xgf \- extracts instructions from a TTX file and creates an Xgridfit program. .SH SYNOPSIS .B ttx2xgf [options] .IR infile[.ttx] .IR [outfile] .SH DESCRIPTION .B ttx2xgf is a utility that extracts instructions (hints) and other information relating to instructions from a TTX file (an XML representation of a TrueType font) and creates a new Xgridfit program. .PP If .I infile lacks the .I .ttx extension, it is assumed. If .I outfile is not given, output is written to .I infile.xgf. .PP .SH OPTIONS .IP "\-\-config" Path to a configuration file (relative paths are permitted). If this is not given, ttx2xgf will look first for a file .I config.xml in the current directory, next in the user's Xgridfit configuration directory, and finally in the Xgridfit base directory. .IP "\-e" Display diagnostic messages (for debugging). .IP "\-E, \-\-elapsed-time" Time the running of this program and display the result. .IP "\-\-processor=libxslt|lxml|xsltproc|saxon-6|saxon-9|xalan-j|xalan-c|4xslt" Select a preferred XSLT processsor; ttx2xgf will use this one if possible. .SH FILES .TP .I /usr/share/xml/xgridfit/util/convert-ttx.xsl An XSLT script that performs the initial conversion. .TP .I /usr/share/xml/xgridfit/util/convert-asm.sed A Sed script that completes the conversion. .SH SEE ALSO .BR xgridfit (1), .BR xgfconfig (1), .BR ttx (1) .\" .br .SH AUTHOR .B ttx2xgf was written by Peter Baker .nh . .hy .PP This manual page was written by Peter Baker xgridfit/man/getinstrs.10000644000175000017500000000215211313432207014571 0ustar peterpeter.TH GETINSTRS 1 "2009-12-16" .SH NAME .B getinstrs \- extracts TrueType instructions for one or more glyphs from a font. .SH SYNOPSIS .B getinstrs [options] .IR fontfile .IR glyphs ... .SH DESCRIPTION .B getinstrs calls the FontForge Python extension to extract instructions from a TrueType font (either .ttf or .sfd) and print them to stdout (redirect to capture them in a file). By default the instructions are printed as an Xgridfit glyph program. Use the \-r, \-\-raw command-line option to print them as "raw" instructions instead, or use \-x, \-\-xgridfit to enclose the glyph program(s) in an element, making a complete, valid Xgridfit program. .hy . .SH OPTIONS .IP "\-h, \-\-help" Display a help message and exit. .IP "\-r, \-\-raw" Print "raw" instructions instead of Xgridfit glyph programs. .IP "\-x, \-\-xgridfit" Print XML declaration and element, making a complete, valid Xgridfit program. .SH SEE ALSO .BR xgridfit (1), .BR fontforge (1), .BR python (1) .\" .br .SH AUTHOR .B getinstrs was written by Peter Baker .nh . .hy .PP This manual page was written by Peter Baker xgridfit/man/xgfmerge.10000644000175000017500000000521211313005340014345 0ustar peterpeter.TH XGFMERGE 1 "2009-12-18" .SH NAME .B xgfmerge \- merges two Xgridfit program files .SH SYNOPSIS .B xgfmerge [options] .IR file-a .IR file-b .IR [...] .SH DESCRIPTION .B Xgfmerge merges two or more Xgridfit program files, where file-a is a program generated automatically from an existing font using TTX and ttx2xgf, and file-b and any other files in the list contain other programming for the font. .B Xgfmerge outputs the merged programming to stdout. To capture the output in a file, use this syntax: $xgfmerge -o merged-file.xgf file-a.xgf file-b.xgf .hy . .PP .B "Note:" To merge Xgridfit instructions with those already in a font, the best method is now to run Xgridfit in merge-mode (option \-m). .SH OPTIONS .IP "\-c" Look for a element in each file after the first in the list. If value="no" then ignore all , , , and elements in the file. .IP "\-h" Display a help message. .IP "\-n" Merge elements from all files. elements with duplicate "ps-name" attributes are ignored. .IP "\-o file" The file to write the output to. If this option is not used, output is written to stdout. .IP "\-p" When a element in a file other than file-a is available, use it instead of the one from file-a. If this option is not present, xgfmerge merges the programming in the of file-a with that in the of whichever file is being merged at the moment. The result is unlikely to be good if a single run of xgfmerge merges the contents of more than two elements. .IP "\-s" Sort elements in the output file into alphabetical order. .IP "\-v" Verbose output: xgfmerge tells you what it is doing at each step. .IP "\-x" Resolve XIncludes before merging all files in the list except for file-a. Any XIncludes from file-a.xgf are stripped out of the files before this operation is performed. If XInclude is used to bring global elements (, , etc.) into these files, it is probably a good idea to use the \-c option as well. .SH FILES .TP .I /usr/share/xml/xgridfit/util/merge.xsl An XSLT script that performs the merge. .TP .I /usr/share/xml/xgridfit/util/xinclude.xsl An XSLT script that strips out unwanted XIncludes. .TP .I /usr/share/xml/xgridfit/util/sort-glyphs.xsl An XSLT script that sorts glyph elements in a file. .TP .I /usr/share/xml/xgridfit/utils/add-blanks.sed Does some formatting of the output. .SH SEE ALSO .BR xgridfit (1), .BR ttx (1), .BR ttx2xgf (1). .\" .br .SH AUTHOR .B Xgfmerge was written by Peter Baker .nh . .hy .PP This manual page was written by Peter Baker xgridfit/man/xgfupdate.10000644000175000017500000000231611313005340014532 0ustar peterpeter.TH XGFUPDATE 1 "2009-12-18" .SH NAME .B xgfupdate \- updates an Xgridfit program file to the latest version. .SH SYNOPSIS .B xgfupdate .IR file .SH DESCRIPTION .B Xgfupdate is a utility that updates an Xgridfit program file so that it validates against the current xgridfit.rnc schema. .B Xgfupdate outputs the updated file to stdout. To capture the output in a file, use this syntax: $xgfupdate [options] infile > outfile .hy . .SH OPTIONS .IP "\-h" Display a help message and exit. .IP "\-v 1|2" Choose a mode in which to run Xgfupdate. "1" updates an Xgridfit program so that it will validate against the 2.0 schema. "2" updates an Xgridfit program from version 1.x or 2.0 to version 2.1 by adding the Xgridfit namespace; it also revises XInclude elements to be aware of the Xgridfit namespace. .SH FILES .TP .I /usr/share/xml/xgridfit/util/xgf-update.xsl .I /usr/share/xml/xgridfit/util/xgf-add-namespace.xsl XSLT scripts that do the updating. .TP .I /usr/share/xml/xgridfit/util/add-blanks.sed A Sed script that does some formatting of the output. .SH SEE ALSO .BR xgridfit (1). .\" .br .SH AUTHOR .B Xgfupdate was written by Peter Baker .nh . .hy .PP This manual page was written by Peter Baker xgridfit/man/xgridfit.10000644000175000017500000001667311324521763014414 0ustar peterpeter.TH XGRIDFIT 1 "2009-12-18" .SH NAME .B xgridfit \- a program for gridfitting, or "hinting," TrueType fonts .SH SYNOPSIS .B xgridfit [options] .IR file. \|{ xgf or .IR xml \|}... .SH DESCRIPTION .B Xgridfit is a simple program that implements an XML-based language for gridfitting, or "hinting," TrueType fonts. It compiles an XML source file into tables and instructions that relate to the gridfitting of glyphs. .B Xgridfit does not insert these elements into a font itself, but rather relies on FontForge, the Open Source font editor, to do this. .PP For each input file specified on the command line, the .B xgridfit command generates a script named .I file.py. You may run this script in .I FontForge thus: $ fontforge \-script file.py .PP Alternatively, you can skip generation of a script file and execute the script (the FontForge Python bindings are required for this): $ xgridfit --execute file.xgf .PP For more information about .B Xgridfit, point your browser to .nh .I file:///usr/share/doc/xgridfit/html/index.html .hy or .nh .I http://xgridfit.sourceforge.net .hy . .SH OPTIONS Note that many of these options can also be specified by "default" elements in the program file. However, command-line options always override these defaults. .IP "\-a value, \-\-max\-stack=value" Size of TrueType stack (default is 256) .IP "\-A, \-\-auto\-instr" Auto-instruct all glyphs in the font before installing Xgridfit programming. This option has no effect except in merge-mode (option \-m). .IP "\-b value, \-\-delta\-break=value" Delta Break value: formerly the maximum number of delta pairs that could be placed on the stack with a single push instruction. As of version 1.11 it approximates that behavior by setting \-p option to twice the specified value. This option has no effect in Python mode (option \-l py). .IP "\-c yes|no, \-\-compile\-globals=yes|no" Compile functions, control values, pre-program and maxp entries (default is "yes") .IP "\-C gray|grey|black|white, \-\-color=gray|grey|black|white" Use this color for rounded distances except where specified otherwise (default is "gray"). .IP "\-\-config=file" Read this configuration file instead of the default. .IP "\-d, \-\-debug\-mode" Run in debug mode. Output is .I file.debug rather than .I file.py .IP "\-D, \-\-delete-all" Delete all instruction-related programming and data before installing Xgridfit programming. This option has no effect except in merge-mode (option \-m). Otherwise, when the output language is Python, TrueType data is deleted except when \-\-compile\-globals=no. .IP "\-e" Display diagnostic messages (mainly for debugging Xgridfit). .IP "\-E, \-\-elapsed\-time" Report the time (in seconds) used to run Xgridfit. .IP "\-f, \-\-execute" Execute the generated script, and do not save it in a file. This option overrides \-O, and it is incompatible with \-d, \-S and \-z. .IP "\-F file, \-\-data\-file=file" In merge-mode, Xgridfit stores and reads information about the font's state. By default, this is stored in FontForge's font.persistent object, which can be stored only in an .sfd file. Use this option to store font information in a file instead. .IP "\-g glyph+list, \-\-glyph\-select=glyph+list" Compile only the specified glyphs, ignoring all others. The argument is a list of one or more glyph names, delimited by plus signs ("+"). The list must contain no spaces. .IP "\-G yes|no, \-\-init\-graphics=yes|no" Include or omit at the beginning of each glyph program a function call that initializes variables used to track the graphics state. The default is "yes." This option can be overridden with the init-graphics attribute on any glyph element. .IP "\-h, \-\-help" Display a help message and exit. .IP "\-H yes|no, \-\-auto\-hint=yes|no" Auto-hint all glyphs in the font before auto-instructing. This option has no effect except when auto-instructing is requested (option \-A). .IP "\-i file, \-\-infile=file" File to be input by generated script. Must have extension .I .sfd or .I .ttf .IP "\-l py|ff, \-\-language=py|ff" Whether the output of Xgridfit should be a Python script or one in the native FontForge scripting language. The default is .I py. Alternatively, set the environment variable XGRIDFIT_OUTPUT_LANG to "ff" or "py". .IP "\-m, \-\-merge\-mode" Run in merge-mode. Xgridfit produces a Python script that merges Xgridfit programming with TrueType programming already present in the font. .IP "\-o file, \-\-outfile=file" File to be output by generated script. Must have extension .I .sfd or .I .ttf .IP "\-O file, \-\-output\-script=file" Name of script file to be output by Xgridfit, rather than the default, which replaces .I .xgf in the input file with .I .py .IP "\-p value, \-\-push\-break=value" The number of values that can be pushed with a single PUSHB or PUSHW instruction. The default is 255, except when the output language is ff (\-l ff); then the default is 20. .IP "\-P yes|no, \-\-combine\-prep=yes|no" Combine the Xgridfit pre-program with the prep table already present in the font (merge-mode only; default is yes). .IP "\-\-processor=libxslt|lxml|xsltproc|saxon-6|saxon-9|xalan-j|xalan-c|4xslt" Select a preferred XSLT processsor. Xgridfit will use this one if possible. .IP "\-q, \-\-quiet" Run in quiet mode. Routine messages are suppressed. .IP "\-s value, \-\-max\-storage=value" Maximum places in TrueType storage area. This area is used to store variables, and also Xgridfit's own run-time data. The number must always be 24 or greater .IP "\-S name, \-\-output\-base=name" Save script for each glyph in a separate file named .I name_glyph-name.py - or .I .pe or .I .debug .IP "\-\-skip\-validation" Do not validate the Xgridfit program before compiling. .IP "\-t value, \-\-max\-twilight=value" Maximum number of points in Twilight zone. The default is 25, but few fonts require so many .IP "\-T file, \-\-temp\-file=file" Name of a temporary file in which to store result of XInclude processing: the compiler and/or validator is run against this file. If this option is used, the file is not deleted after processing; if it is not used, the file (named by Xgridfit) is deleted. This option is ignored when a temporary file is not needed. .IP "\-v, \-\-version" Print version number and exit .IP \-V Validate the Xgridfit program against a schema before compiling. Compilation is performed only if validation suceeds. By default xmllint is used for validation; run xgfconfig to choose another validator. .IP "\-\-validator=libxml2|lxml|jing|msv|rnv" Select a preferred Relax NG validator. Xgridfit will use this validator if possible. .IP "\-x, \-\-skip\-compilation" Do not compile. Validation is performed unless suppressed. .IP "\-X, \-\-no\-xinclude" Assume that XInclude processing is unnecessary; do not check. .IP "\-z file, \-\-output\-outfile\-script=file" When the \-S option is present and the \-o option or the element has been used to make the output script save a font or FontForge source file, the output of the script is saved in a separate script file. Xgridfit will supply a default name for this file, but this option lets you supply your own name. .SH FILES .TP .I /usr/share/xml/xgridfit/lib/*.xsl All XSLT scripts of the .B Xgridfit program. .SH SEE ALSO .BR fontforge (1), .BR xgfconfig (1), .BR ttx2xgf (1), .BR xgfupdate (1). .\" .br .SH AUTHOR .B xgridfit was written by Peter Baker .nh . .hy .PP This manual page was written by Kestutis Biliunas .nh , .hy for the Debian project (but may be used by others). Revised and OPTIONS section added by P. Baker. xgridfit/man/xgfconfig.10000644000175000017500000000624311327562462014542 0ustar peterpeter.TH XGFCONFIG 1 "2010-01-16" .SH NAME .B xgfconfig \- configuration program for Xgridfit .SH SYNOPSIS .B xgfconfig options [list] .SH DESCRIPTION .B Xgfconfig selects XSLT processors and RELAX NG validators for Xgridfit to use; it can also be used to specify a new Xgridfit base directory. .PP Xgridfit maintains lists of validators and processors; on starting, it consults these lists and runs the first validator and processor it can find. Xgfconfig reorders these lists so that your preferred programs are looked for first. Xgfconfig may be invoked in one of these forms: $ xgfconfig --processors processor-list $ xgfconfig --validators validator-list $ xgfconfig --xgridfit-dir /xgridfit/directory $ xgfconfig --show .PP The first of these selects processors (one or more of libxslt, lxml, xsltproc, saxon-6, saxon-9, xalan-j, xalan-c, 4xslt); the second selects validators (one or more of libxml2, lxml, jing, msv, rnv); the third specifies a complete path to the Xgridfit base directory (use it if you have installed Xgridfit in your own account rather than system wide); the fourth displays the current configuration. .PP Several of the processors and validators that Xgridfit knows about are Java programs; for these, Xgridfit needs the name and location of a .jar file (by default it assumes certain standard file names, found in /usr/share/java). Specify this with a hash-mark followed by a complete path-name for the file. Here are sample command lines: $ xgfconfig -p saxon-9#/usr/local/share/java/saxon9he.jar lxml $ xgfconfig --config=config.xml -V rnv msv#/home/me/java/msv.jar .PP The second of these commands stores the configuration in the file .I config.xml in the current directory. (When it starts, Xgridfit looks first for a file .I config.xml in the current directory; failing that, it looks for .I ~/.xgridfit/config.xml (Linux/Mac) or .I some-path (Windows); finally it looks in the Xgridfit base directory before giving up and using the default configuration.) .PP An Xgridfit configuration file is a simple XML file, easily editable by users. The entries in it should be all but self-explanatory. .hy . .SH OPTIONS .IP "\-\-config" The configuration file to read or write. If this is not specified, Xgfconfig will search in the standard places (see above) for an existing configuration file for which the user has write privileges. Failing that, it will create a configuration file in the directory ~/.xgridfit (Linux/Mac) or some-dir (Windows). If the user is root or has administrative privileges, Xgfconfig will create the file in the Xgridfit base directory. .IP "\-h, \-\-help" Display a help message and exit. .IP "\-p, \-\-processors" The list following the options is a list of processors. .IP "\-s, \-\-show" Display the current configuration and exit. .IP "\-V, \-\-validators" The list following the options is a list of validators. .IP "\-x, \-\-xgridfit\-dir" Following the options is the full pathname of the Xgridfit base directory. .SH SEE ALSO .BR fontforge (1), .BR xgridfit (1), .BR ttx2xgf (1), .BR xgfupdate (1). .\" .br .SH AUTHOR .B Xgfconfig was written by Peter Baker .nh . .hy .PP This manual page was written by Peter Baker xgridfit/version.mk0000644000175000017500000000004211572446747013751 0ustar peterpeterPACKAGE = xgridfit VERSION = 2.3 xgridfit/schemas/0000755000175000017500000000000011572451644013352 5ustar peterpeterxgridfit/schemas/xgridfit.xml0000644000175000017500000000126211307752323015707 0ustar peterpeter xgridfit/schemas/catalog.xml0000644000175000017500000000074411307752323015505 0ustar peterpeter xgridfit/schemas/xml.xsd0000644000175000017500000000101011313007224014642 0ustar peterpeter xgridfit/schemas/xi.xsd0000644000175000017500000000117211313007224014473 0ustar peterpeter xgridfit/schemas/xgridfit.rnc0000644000175000017500000004724611356474357015721 0ustar peterpeter# xgridfit, an XML-based language for instructing TrueType fonts # # Copyright (c) 2005-2008 by Peter S. Baker # # You can do what you like with this schema, as # long as you keep intact the copyright notice above and add a # notice if you change anything. default namespace = "http://xgridfit.sourceforge.net/Xgridfit2" namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" namespace xi = "http://www.w3.org/2001/XInclude" YESNO = "yes" | "no" various = message | no-warning | getinfo movements = mirp | mdrp | miap | mdap | shift | align | move-point-to-intersection | interpolate | interpolate-untouched-points | shift-absolute | set-coordinate | top.level.move | diagonal-stem | top.level.delta | control-value-delta | untouch | toggle-points | flip-on | flip-off | align-midway graphics = set-vectors | set-projection-vector | set-freedom-vector | store-projection-vector | store-freedom-vector | set-minimum-distance | srp | szp | set-round-state | disable-instructions | enable-instructions | set-dropout-control | set-dropout-type | set-control-value | set-control-value-cut-in | set-single-width-cut-in | set-single-width | set-auto-flip | set-delta-base | set-delta-shift | set-dual-projection-vector | with-vectors | with-projection-vector | with-freedom-vector | with-minimum-distance | with-round-state | with-control-value | with-control-value-cut-in | with-single-width-cut-in | with-single-width | with-delta-base | with-delta-shift | restore-default vars = set-equal | add | subtract | divide | multiply | absolute | negate | floor | ceiling | minimum | maximum | round | no-round | control-value-index | formula form.vars = set-equal | form.add | form.subtract | form.divide | form.multiply | form.absolute | form.negate | form.floor | form.ceiling | form.minimum | form.maximum | form.round | form.no-round | form.control-value-index flow = call-function | call-macro | call-glyph | call-param | if | compile-if measure = measure-distance | get-coordinate primitive = command | push | to-stack programming = various | movements | graphics | vars | flow | measure | primitive token.ps-name = xsd:token {pattern = "\.notdef|[A-Za-z_][A-Za-z0-9_\.]{0,30}" } att.pyflags = attribute pyflags { list { ("afm" | "pfm" | "tfm" | "ofm" | "composites-in-afm" | "glyph-map-file" | "short-post" | "apple" | "opentype" | "old-kern" | "dummy-dsig" | "TeX-table" | "round" | "no-hints" | "omit-instructions" | "PfEd-comments" | "PfEd-colors" | "PfEd-lookups" | "PfEd-guidelines" | "PfEd-background" | "symbol")* } } att.value = attribute value { text } att.num = attribute num { text } att.name = attribute name { xsd:NCName } att.ref = attribute ref { xsd:NCName } att.target = attribute target { xsd:NCName } att.zone = attribute zone { "twilight" | "glyph" } att.color = attribute color { "gray" | "black" | "white" } att.axis = attribute axis { "x" | "y" } att.unit = attribute unit { "pixel" | "font" } att.units.per.pixel = attribute units-per-pixel { "2" | "4" | "8" | "16" | "32" | "64" } att.to-line = attribute to-line { "orthogonal" | "parallel" } att.result-to = attribute result-to { xsd:NCName } att.test = attribute test { text } att.grid-fitted = attribute grid-fitted { YESNO } att.whichpointer = attribute whichpointer { text } att.id = attribute xml:id { xsd:ID } att.round = attribute round { text } att.set-rp0 = attribute set-rp0 { YESNO } att.cut-in = attribute cut-in { YESNO } att.compile-if = attribute compile-if { text } att.distance = attribute distance { text } att.pixel-distance = attribute pixel-distance { text } att.boolean.min-distance = attribute min-distance { YESNO } att.value.min-distance = attribute min-distance { text } att.ps-name = attribute ps-name { token.ps-name } attlist.single.op = att.value, att.result-to? attlist.form.single.op = att.value? attlist.dual.op = attribute value1 { text }, attribute value2 { text }, att.result-to? attlist.form.dual.op = attribute value1 { text }?, attribute value2 { text }? attlist.value.with.name = att.value, att.name attlist.delta-set-basic = attribute size { xsd:nonNegativeInteger {maxInclusive = "47"} }, attribute distance { xsd:int {pattern = "[\-]?[1-8]"} } attlist.vector.components = (attribute x-component { text }, attribute y-component { text }) attlist.vector.store = (attribute x-component { xsd:NCName }, attribute y-component { xsd:NCName })? attlist.measurement = att.grid-fitted?, att.result-to? model.set-vector = att.axis | attlist.vector.components | ( att.to-line?, line ) model.with-vector = (att.axis, programming*) | (attlist.vector.components, programming*) | (att.to-line?, line, programming*) | programming* # # Top level # xgridfit = element xgridfit{ att.id?& glyph-select?& infile?& outfile?& outfile-base?& outfile-script-name?& no-compile?& legacy-functions?& pre-program?& ps-private?& constant*& alias*& variable*& round-state*& \default*& control-value*& function*& macro*& glyph*& xg.xi.include* } # # Value declarations # constant = element constant { attlist.value.with.name, empty } variable = element variable { attlist.variable, empty } attlist.variable &= att.name, att.value? alias = element alias { attlist.alias, empty } attlist.alias &= att.name, att.target # # Controlling compilation of glyph programs # glyph-select = element glyph-select { list { token.ps-name* } } no-compile = element no-compile { (glyph | xg.xi.include)* } # # Script I/O # infile = element infile { xsd:anyURI } outfile = element outfile { attribute fmflags { xsd:int }?, att.pyflags?, xsd:anyURI } outfile-base = element outfile-base { xsd:anyURI } outfile-script-name = element outfile-script-name { xsd:anyURI } # # Top-level declarations # round-state = element round-state { attlist.round-state, empty } attlist.round-state &= att.name, attribute period { "half-pixel" | "one-pixel" | "two-pixel" }, attribute phase { "zero" | "one-quarter" | "one-half" | "three-quarters" }, attribute threshold { "period-minus-one" | "minus-three-eighths" | "minus-one-quarter" | "minus-one-eighth" | "zero" | "one-eighth" | "one-quarter" | "three-eighths" | "one-half" | "five-eighths" | "three-quarters" | "seven-eighths" | "one" | "nine-eighths" | "five-quarters" | "eleven-eighths" } \default = element default { attlist.default, empty } attlist.default &= attribute type { "minimum-distance" | "control-value-cut-in" | "single-width" | "single-width-cut-in" | "delta-base" | "delta-shift" | "delta-break" | "push-break" | "max-twilight-points" | "max-storage" | "legacy-storage" | "max-stack" | "use-truetype-defaults" | "round-state" | "function-base" | "compile-globals" | "init-graphics" | "color" | "delete-all" | "combine-prep" | "auto-instr" | "auto-hint" | "cv-num-in-compile-if" }, att.value ps-private = element ps-private { entry+ } entry = element entry { attlist.entry, empty } attlist.entry &= att.name, att.value control-value = element control-value { attlist.control-value, empty } attlist.control-value &= attribute index { text }?, att.name, attribute value { xsd:int } function = element function { attlist.function, function.param*, (variable|alias)*, programming*, variant* } attlist.function &= att.name, att.id?, attribute num { xsd:nonNegativeInteger }?, attribute return { YESNO }? variant = element variant { att.test, programming* } macro = element macro { attlist.macro, param*, alias*, programming* } attlist.macro &= att.name, att.id? function.param = element param { attlist.param } param = element param { attlist.param, ((set | range | line) | programming+)? } attlist.param &= att.name, att.value? legacy-functions = element legacy-functions { attlist.legacy-functions, programming* } attlist.legacy-functions &= attribute max-function-defs { xsd:nonNegativeInteger } pre-program = element pre-program { att.id?, (variable|alias)*, programming* } glyph = element glyph { attlist.glyph, param*, (constant|alias|variable|range|line|set)*, programming* } attlist.glyph &= att.ps-name, attribute init-graphics { YESNO }?, att.id? # # Miscellaneous / Oddball # message = element message { text } # # Points and point structures # point = element point { attlist.point, empty } attlist.point &= att.num, att.zone? reference = element reference { point } dual.reference = element reference { point, point } line = element line { attlist.line, (att.ref | (point, point)) } attlist.line &= att.name?, att.zone? range = element range { attlist.range, (att.ref | (point, point)) } attlist.range &= att.name?, att.zone? set = element set { attlist.set, (att.ref | point+) } attlist.set &= att.name?, att.zone? contour = element contour { attlist.contour, empty } attlist.contour &= att.num, att.zone? zone = element zone { att.zone, empty } # # Point-moving instructions # mirp = element mirp { attlist.mirp, reference?, point } attlist.mirp &= att.distance, att.round?, att.cut-in?, att.boolean.min-distance?, att.set-rp0?, att.color? mdrp = element mdrp { attlist.mdrp, reference?, point } attlist.mdrp &= att.round?, att.boolean.min-distance?, att.set-rp0?, att.color? miap = element miap { attlist.miap, point } attlist.miap &= att.distance, att.round?, att.cut-in? mdap = element mdap { att.round?, point } shift = element shift { attlist.shift, reference?, (point | range | set | contour | zone)+ } attlist.shift &= attribute reference-ptr { "1" | "2" }?, att.compile-if?, att.round? align = element align { att.compile-if?, reference?, (point | range | set)+ } move-point-to-intersection = element move-point-to-intersection { (point, line, line) | (line, line, point) | (line, point, line) } interpolate = element interpolate { attlist.interpolate, dual.reference?, (point | range | set)+ } attlist.interpolate &= att.compile-if?, att.round? interpolate-untouched-points = element interpolate-untouched-points { att.axis?, empty } set-coordinate = element set-coordinate { attribute coordinate { text }, point } shift-absolute = element shift-absolute { att.pixel-distance, (point | range | set)+ } toggle-points = element toggle-points { (point | range | set)+ } align-midway = element align-midway { point, point } flip-on = element flip-on { range } flip-off = element flip-off { range } untouch = element untouch { point } top.level.move = element move { attlist.move, ((reference, point, nested.delta*, (align*& interpolate*& shift*), nested.move*, nested.delta*) | (point, nested.delta*, (align*& shift*), nested.move*, nested.delta*)) } nested.move = element move { attlist.move, point, nested.delta*, (align*& interpolate*& shift*), nested.move*, nested.delta* } attlist.move &= (att.distance? | att.pixel-distance?), att.round?, attribute cut-in { text }?, att.value.min-distance?, att.color?, att.compile-if? diagonal-stem = element diagonal-stem { attlist.diagonal-stem, line, line, align?, align? } attlist.diagonal-stem &= att.distance, att.round?, att.cut-in?, att.value.min-distance?, att.color?, attribute freedom-vector { YESNO }?, attribute save-vectors { YESNO }? top.level.delta = element delta { att.compile-if?, ((point, (point.delta-set | empty.delta-set)+) | point.delta-set+) } nested.delta = element delta { att.compile-if?, point?, (point.delta-set | empty.delta-set)+ } control-value-delta = element control-value-delta { cv.delta-set+ } cv.delta-set = element delta-set { attlist.cv.delta-set, empty } attlist.cv.delta-set &= attribute cv { xsd:NCName }, attlist.delta-set-basic point.delta-set = element delta-set { attlist.delta-set-basic, point } empty.delta-set = element delta-set { attlist.delta-set-basic, empty } # # Enable/disable instructions # disable-instructions = element disable-instructions { empty } enable-instructions = element enable-instructions { empty } # # Graphics state # set-vectors = element set-vectors { model.set-vector } with-vectors = element with-vectors { model.with-vector } set-projection-vector = element set-projection-vector { model.set-vector } with-projection-vector = element with-projection-vector { model.with-vector } set-freedom-vector = element set-freedom-vector { model.set-vector } with-freedom-vector = element with-freedom-vector { model.with-vector } set-dual-projection-vector = element set-dual-projection-vector { att.to-line?, line } store-projection-vector = element store-projection-vector { attlist.vector.store, empty } store-freedom-vector = element store-freedom-vector { attlist.vector.store, empty } srp = element srp { att.whichpointer, point } szp = element szp { attlist.szp, empty } attlist.szp &= att.whichpointer, att.zone set-dropout-control = element set-dropout-control { attlist.set-dropout-control, empty } attlist.set-dropout-control &= attribute threshold { xsd:nonNegativeInteger {maxInclusive = "255"} }, attribute flags { xsd:nonNegativeInteger {maxInclusive = "63"} } set-dropout-type = element set-dropout-type { att.dropout.value, empty } att.dropout.value = attribute value { xsd:nonNegativeInteger {maxInclusive = "7"} } set-control-value = element set-control-value { attlist.set-control-value, empty } with-control-value = element with-control-value { attlist.set-control-value, programming* } attlist.set-control-value &= attlist.value.with.name, att.unit? set-control-value-cut-in = element set-control-value-cut-in { att.value, empty } with-control-value-cut-in = element with-control-value-cut-in { att.value, programming* } set-minimum-distance = element set-minimum-distance { att.value, empty } with-minimum-distance = element with-minimum-distance { att.value, programming* } set-round-state = element set-round-state { att.round, empty } with-round-state = element with-round-state { att.round, programming* } set-single-width-cut-in = element set-single-width-cut-in { att.value, empty } with-single-width-cut-in = element with-single-width-cut-in { att.value, programming* } set-single-width = element set-single-width { att.value, empty } with-single-width = element with-single-width { att.value, programming* } set-auto-flip = element set-auto-flip { attribute value { "on" | "off" }, empty } set-delta-base = element set-delta-base { att.value, empty } with-delta-base = element with-delta-base { att.value, programming* } set-delta-shift = element set-delta-shift { att.units.per.pixel, empty } with-delta-shift = element with-delta-shift { att.units.per.pixel, programming* } restore-default = element restore-default { attlist.restore-default, empty } attlist.restore-default &= attribute name { "minimum-distance" | "control-value-cut-in" | "single-width" | "single-width-cut-in" | "delta-base" | "delta-shift" | "round-state" | "all" } # # Arithmetic elements # set-equal = element set-equal { attlist.set-equal, empty } attlist.set-equal &= att.target, attribute source { text } control-value-index = element control-value-index { attlist.control-value-index, empty } form.control-value-index = element control-value-index { att.value, empty } attlist.control-value-index &= att.value, att.result-to add = element add { attlist.dual.op, empty } form.add = element add { attlist.form.dual.op, empty } subtract = element subtract { attlist.subtract, empty } attlist.subtract &= attribute minuend { text }, attribute subtrahend { text }, att.result-to? form.subtract = element subtract { attlist.form.subtract, empty } attlist.form.subtract &= attribute minuend { text }?, attribute subtrahend { text }? divide = element divide { attlist.divide, empty } attlist.divide &= attribute dividend { text }, attribute divisor { text }, att.result-to? form.divide = element divide { attlist.form.divide, empty } attlist.form.divide &= attribute dividend { text }?, attribute divisor { text }? multiply = element multiply { attlist.dual.op, empty } form.multiply = element multiply { attlist.form.dual.op, empty } absolute = element absolute { attlist.single.op, empty } form.absolute = element absolute { attlist.form.single.op, empty } negate = element negate { attlist.single.op, empty } form.negate = element negate { attlist.form.single.op, empty } floor = element floor { attlist.single.op, empty } form.floor = element floor { attlist.form.single.op, empty } ceiling = element ceiling { attlist.single.op, empty } form.ceiling = element ceiling { attlist.form.single.op, empty } minimum = element minimum { attlist.dual.op, empty } form.minimum = element minimum { attlist.form.dual.op, empty } maximum = element maximum { attlist.dual.op, empty } form.maximum = element maximum { attlist.form.dual.op, empty } round = element round { attlist.round, empty } no-round = element no-round { attlist.round, empty } attlist.round &= att.value, att.color?, att.result-to? form.round = element round { attlist.form.round, empty } form.no-round = element no-round { attlist.form.round, empty } attlist.form.round &= att.value?, att.color? formula = element formula { att.result-to?, (form.vars)+ } # # Function and macro calls # call-function = element call-function { attlist.call-function, (function.param-set* | function.with-param*) } attlist.call-function &= att.name, att.result-to? call-macro = element call-macro { att.name, (param-set* | with-param*) } call-param = element call-param { att.name, empty } call-glyph = element call-glyph { att.ps-name, with-param* } function.param-set = element param-set { attribute opt { YESNO }?, function.with-param+ } param-set = element param-set { with-param+ } function.with-param = element with-param { att.name, att.value, empty } with-param = element with-param { att.name, (att.value | (att.value?, ((set | range | line) | programming+))) } # # Conditionals # if = element if { att.test, programming*, else? } else = element else { programming* } compile-if = element compile-if { att.test, programming*, else? } no-warning = element no-warning { programming* } # # Getting info # measure-distance = element measure-distance { attlist.measurement, point, point } get-coordinate = element get-coordinate { attlist.measurement, point } getinfo = element getinfo { attlist.getinfo, empty } attlist.getinfo &= attribute selector { text }, att.result-to? # # Primitives # command = element command { attribute name { xsd:token { pattern = "[A-Z0-5]{2,9}" } }, ( attribute modifier { text }? | modifier* ) } modifier = element modifier { attlist.modifier, empty } attlist.modifier &= att.value, attribute type { "set-rp0" | "round" | "minimum-distance" | "color" | "grid-fitted" | "to-line" | "axis" | "ref-ptr" } push = element push { text } to-stack = element to-stack { text } # # XInclude # xg.xi.include.attlist = attribute href { xsd:anyURI }?, [ a:defaultValue = "xml" ] attribute parse { "xml" | "text" }?, attribute xpointer { text }?, attribute encoding { text }?, attribute accept { text }?, attribute accept-language { text }? xg.xi.include = element xi:include { xg.xi.include.attlist } start = xgridfit xgridfit/schemas/xgridfit.xsd0000644000175000017500000021101511356474357015720 0ustar peterpeter xgridfit/schemas/xgridfit.rng0000644000175000017500000015022711356474357015717 0ustar peterpeter yes no \.notdef|[A-Za-z_][A-Za-z0-9_\.]{0,30} afm pfm tfm ofm composites-in-afm glyph-map-file short-post apple opentype old-kern dummy-dsig TeX-table round no-hints omit-instructions PfEd-comments PfEd-colors PfEd-lookups PfEd-guidelines PfEd-background symbol twilight glyph gray black white x y pixel font 2 4 8 16 32 64 orthogonal parallel 47 [\-]?[1-8] half-pixel one-pixel two-pixel zero one-quarter one-half three-quarters period-minus-one minus-three-eighths minus-one-quarter minus-one-eighth zero one-eighth one-quarter three-eighths one-half five-eighths three-quarters seven-eighths one nine-eighths five-quarters eleven-eighths minimum-distance control-value-cut-in single-width single-width-cut-in delta-base delta-shift delta-break push-break max-twilight-points max-storage legacy-storage max-stack use-truetype-defaults round-state function-base compile-globals init-graphics color delete-all combine-prep auto-instr auto-hint cv-num-in-compile-if 1 2 255 63 7 on off minimum-distance control-value-cut-in single-width single-width-cut-in delta-base delta-shift round-state all [A-Z0-5]{2,9} set-rp0 round minimum-distance color grid-fitted to-line axis ref-ptr xml text xgridfit/utils/0000755000175000017500000000000011572451646013071 5ustar peterpeterxgridfit/utils/defaults.xml0000644000175000017500000001027711137064734015424 0ustar peterpeter Command-line tool for Daniel Veillard's libxslt (default). --stringparam @pname@ @arg@ --output @outfile@ xsltproc Michael Kay's Saxon processor for XSLT 1.0, written in Java. saxon.jar @pname@=@arg@ -o @outfile@ Michael Kay's Saxon processor for XSLT 2.0, written in Java. saxon9.jar @pname@=@arg@ -o:@outfile@ The XSLT processor for 4Suite, written in Python. --define=@pname@=@arg@ --outfile=@outfile@ 4xslt An XSLT processor from the Apache XML Project, written in Java. xalan2.jar -param @pname@ @arg@ -out @outfile@ An XSLT processor from the Apache XML Project, written in C++. -param @pname@ '@arg@' -out @outfile@ xalan The command-line validator for Daniel Veillard's libxml2. rng xmllint James Clark's RELAX NG validator, written in Java. rng jing.jar The Multi-Schema validator from Sun, written in Java. rng msv.jar David Tolpin's RELAX NG validator, written in ANSI C. rnc rnv Swiss Army Knife for XML: validator is a frontend for libxml2. rng xmlstarlet xgridfit/utils/ff-functions.xgf0000644000175000017500000002614611311132360016165 0ustar peterpeter pt cv-of-blue 0 pt 1 width cv ppem 2 val 3 pt cv chg-rp0 ppem 4 5 6 7 pt ref-pt-a ref-pt-b 8 min-dist inner-pt outer-pt 9 pt2 pt1 10 pt 11 pt 12 other-edge-ref-pt pt ref-pt-a ref-pt-b 13 ppem ref-pt base-pt 14 master-counter-start-pt master-counter-end-pt current-counter-start-pt current-counter-end-pt ppem 15 ref-pt pt 16 ref-pt pt 17 ref-pt pt 18 pt diag-start-pt diag-end-pt 19 20 x y 21 xgridfit/utils/add-blanks.sed0000644000175000017500000000031110717622174015555 0ustar peterpeters/^\([ ]*$/ d /^[ ]*<\/asm>$/ d s/// s/<\/asm>// s/^[ ]*$/<*>/ /PUSH[BW]/ d s/^[ ]*\([ 0-9\-]*\)$/\1<\/push>/ /[ ]*<\/push>/ d s/^<\*>$// s/^[^A-Z]*\(GC\)\[\(.*\)\].*$// s/^[^A-Z]*\(IUP\)\[\(.*\)\].*$// s/^[^A-Z]*\(MD\)\[\(.*\)\].*$// s/^[^A-Z]*\(MDAP\)\[\(.*\)\].*$// s/^[^A-Z]*\(MDRP\)\[\(.*\)\].*$// s/^[^A-Z]*\(MIAP\)\[\(.*\)\].*$// s/^[^A-Z]*\(MIRP\)\[\(.*\)\].*$// s/^[^A-Z]*\(MSIRP\)\[\(.*\)\].*$// s/^[^A-Z]*\(NROUND\)\[\(.*\)\].*$// s/^[^A-Z]*\(ROUND\)\[\(.*\)\].*$// s/^[^A-Z]*\(SDPVTL\)\[\(.*\)\].*$// s/^[^A-Z]*\(SFVTCA\)\[\(.*\)\].*$// s/^[^A-Z]*\(SFVTL\)\[\(.*\)\].*$// s/^[^A-Z]*\(SHC\)\[\(.*\)\].*$// s/^[^A-Z]*\(SHP\)\[\(.*\)\].*$// s/^[^A-Z]*\(SHZ\)\[\(.*\)\].*$// s/^[^A-Z]*\(SPVTCA\)\[\(.*\)\].*$// s/^[^A-Z]*\(SPVTL\)\[\(.*\)\].*$// s/^[^A-Z]*\(SVTCA\)\[\(.*\)\].*$// s/^[^A-Z012]*\([A-Z0123]*\)\[ *\].*$// s/^ The <asm> element is no longer permitted in Xgridfit programs. Please convert your program using the the sed script convert-asm.sed (in the utils directory) and then run this converter again. xgridfit/utils/sort-glyphs.xsl0000644000175000017500000000207111306605442016102 0ustar peterpeter http://xgridfit.sourceforge.net/Xgridfit2 xgridfit/utils/configure.xsl0000644000175000017500000000702311130616446015573 0ustar peterpeter Processors: Validators: : : xgridfit/utils/add-xgridfit-element.xsl0000644000175000017500000000072711307766734017627 0ustar peterpeter xgridfit/utils/xgf-add-namespace.xsl0000644000175000017500000001131111307504500017042 0ustar peterpeter Can't find an xpointer for this xi:include xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)xpointer( ) xgridfit/utils/merge.xsl0000644000175000017500000003516011354420534014713 0ustar peterpeter no yes yes Warning: control values above this point should not be added, deleted or reordered. They may be renamed and their values changed. max-stack xgridfit/utils/convert-ttx.xsl0000644000175000017500000001534111326320556016112 0ustar peterpeter max-twilight-points legacy-storage max-stack left-sidebearing last + 1 right-sidebearing last + 2 vertical 0 horizontal 1 false 0 true 1 Do not add, subtract or reorder above this point. You may change the id but not the value of any of these control-value elements. notdef-glyph xgridfit/utils/xinclude.xsl0000644000175000017500000000155711125223076015430 0ustar peterpeter xgridfit/python/0000755000175000017500000000000011572451643013247 5ustar peterpeterxgridfit/python/xgflib.py0000644000175000017500000017667511354414077015120 0ustar peterpeterfrom subprocess import Popen, PIPE from re import search, compile from sys import exit, stdout, stderr from os.path import join, isfile, isdir, splitext, abspath, dirname from os import access, R_OK, W_OK, pathsep, environ, remove, mkdir from tempfile import mkstemp, TemporaryFile from optparse import OptionParser from time import time try: import libxml2 except ImportError: print """ Xgridfit depends on libxml2 and its Python bindings. Install these and try again. """ exit(1) VERSION = '2.2' JAVA_EXECUTABLE = 'java' DISPLAY_DIAGNOSTIC_MESSAGES = False XGRIDFIT_DIR = abspath('/usr/local/share/xml/xgridfit/') XSLT_DIR = abspath(join(XGRIDFIT_DIR, 'lib')) UTIL_DIR = abspath(join(XGRIDFIT_DIR, 'utils')) SCHEMA_DIR = abspath(join(XGRIDFIT_DIR, 'schemas')) HOME_DIR = environ['HOME'] CONFIG_DIR_REL = '.xgridfit' CONFIG_DIR = abspath(join(HOME_DIR, CONFIG_DIR_REL)) # CONFIG_DIR = HOME_DIR + '/' + CONFIG_DIR_REL NO_PROCESSOR_ERROR = """ Could not find an XSLT processor to use. Install one of these: libxslt (preferably with Python bindings) lxml (Python bindings for libxslt) Saxon (preferably version 9, but 6 will do) Xalan (C++ or Java version) 4Suite If you choose one of the Java-based processors, you must run xgfconfig to help Xgridfit find its .jar file. """ def diagnostic_message(msg): """ Displays diagnostic messages it is turned on. """ if DISPLAY_DIAGNOSTIC_MESSAGES: stderr.write(msg + "\n") def adjust_directories(new_xgridfit_dir): """ Change all directories if the Xgridfit root dir is changed. """ global XGRIDFIT_DIR global XSLT_DIR global SCHEMA_DIR global UTIL_DIR XGRIDFIT_DIR = abspath(new_xgridfit_dir) XSLT_DIR = abspath(join(XGRIDFIT_DIR, 'lib')) UTIL_DIR = abspath(join(XGRIDFIT_DIR, 'utils')) SCHEMA_DIR = abspath(join(XGRIDFIT_DIR, 'schemas')) def has_xinclude_namespace(f): """ Test a file for the XInclude namespace. """ result = False fh = open(f, 'r') for line in fh.readlines(): if line.find('http://www.w3.org/2001/XInclude') >= 0: result = True break fh.close() return result def xinclude_temp_file(fname, tfile=None): """ Get a temporary file for Xinclude output. """ xgfdoc = libxml2.parseFile(fname) xgfdoc.xincludeProcess() if tfile is None: tfile = mkstemp(prefix='xgf_')[1] xgfdoc.saveFile(tfile) return tfile def have_program(filename): """ Search the path for a file; return true if found. """ file_found = False sys_path = environ['PATH'] paths = sys_path.split(pathsep) for path in paths: if isfile(abspath(join(path, filename))): diagnostic_message("found program " + filename) file_found = True break if not file_found: diagnostic_message("did not find program " + filename) return file_found def findProcessor(config): """ Read through the processor priority list and return the first one we think we can actually run. """ proc = None for k in config.processor_priority: if Configuration.processor_classes[k].isEnabled(config): proc = Configuration.processor_classes[k] break return proc def findValidator(config): """ Read through the validator priority list and return the first one we think we can actually run. """ val = None for k in config.validator_priority: if Configuration.validator_classes[k].isEnabled(config): val = Configuration.validator_classes[k] break return val class XGFCompilationError(Exception): """ Error when compiling an Xgridfit program. """ def __init__(self, value): self.value = value def __str__(self): return str(self.value) class XGFValidationError(Exception): """ Error when validating an Xgridfit program file. """ def __init__(self, value): self.value = value def __str__(self): return str(self.value) class Validator(): """ Base class for all validators. """ def __init__(self, config, xgf, need_xinclude=False): self.xgffile = xgf self.need_xinclude = need_xinclude self.config = config @staticmethod def isEnabled(config): return False def execute_external(self, params): """ Run a validator. """ process = Popen(params, stderr=PIPE) err = process.communicate()[1] if process.returncode != 0: raise XGFValidationError(err) def validate(self): pass class LibxmlValidator(Validator): """ The default validator: libxml2 with Python bindings. """ def __init__(self, config, xgf, need_xinclude=False): Validator.__init__(self, config, xgf, need_xinclude) @staticmethod def isEnabled(config): return True def libxmlError(self, ctxt, error): try: last_error = libxml2.lastError() err_str = "line " + str(last_error.line()) + \ ": " + last_error.message() stderr.write(err_str) except Exception as d: stderr.write(str(d)) def validate(self): diagnostic_message("Validating with libxml2 ...") xgfctxt = libxml2.createFileParserCtxt(self.xgffile) xgfctxt.parseDocument() xgfdoc = xgfctxt.doc() libxml2.registerErrorHandler(self.libxmlError, xgfctxt) if self.need_xinclude: xgfdoc.xincludeProcess() sc_file = abspath(join(SCHEMA_DIR, 'xgridfit.rng')) rngParser = libxml2.relaxNGNewParserCtxt(libxml2.pathToURI(sc_file)) rngs = rngParser.relaxNGParse() ctxt = rngs.relaxNGNewValidCtxt() result = xgfdoc.relaxNGValidateDoc(ctxt) xgfdoc.freeDoc() if result != 0: raise XGFValidationError("Error validating document") class LxmlValidator(Validator): """ Validator using libxml2 and an alternate set of python bindings. """ def __init__(self, config, xgf, need_xinclude=False): Validator.__init__(self, config, xgf, need_xinclude) @staticmethod def isEnabled(config): try: from lxml import etree except ImportError: diagnostic_message("No lxml validator ...") return False else: diagnostic_message("Have lxml validator ...") return True def validate(self): from lxml import etree diagnostic_message("Validating with lxml ...") xgfdoc = etree.parse(self.xgffile) if self.need_xinclude: xgfdoc.xinclude() relaxng_doc = etree.parse(abspath(join(SCHEMA_DIR, 'xgridfit.rng'))) relaxng = etree.RelaxNG(relaxng_doc) try: relaxng.assertValid(xgfdoc) except etree.DocumentInvalid as d: err_msg = str(d) + "\n" raise XGFValidationError(err_msg) class RnvValidator(Validator): """ The RNV validator: very fast and friendly. """ def __init__(self, config, xgf, need_xinclude=False): Validator.__init__(self, config, xgf, need_xinclude) @staticmethod def isEnabled(config): return have_program('rnv') def validate(self): diagnostic_message("Validating with rnv ...") args = ['rnv', abspath(join(SCHEMA_DIR, 'xgridfit.rnc')), self.xgffile] try: self.execute_external(args) except XGFValidationError: raise class JingValidator(Validator): """ Jing validator: Java-based, so a bit slow, but does not stop on error. """ def __init__(self, config, xgf, need_xinclude=False): Validator.__init__(self, config, xgf, need_xinclude) @staticmethod def isEnabled(config): return have_program(JAVA_EXECUTABLE) \ and isfile(config.jar_files['jing']) def validate(self): diagnostic_message("Validating with jing ...") args = ['java', '-jar', self.config.jar_files['jing'], abspath(join(SCHEMA_DIR, 'xgridfit.rng')), self.xgffile] try: self.execute_external(args) except XGFValidationError: raise class MsvValidator(Validator): """ MSV validator: good, Java-based, a bit verbose. """ def __init__(self, config, xgf, need_xinclude=False): Validator.__init__(self, config, xgf, need_xinclude) @staticmethod def isEnabled(config): return have_program(JAVA_EXECUTABLE) \ and isfile(config.jar_files['msv']) def validate(self): diagnostic_message("Validating with msv ...") args = ['java', '-jar', self.config.jar_files['msv'], abspath(join(SCHEMA_DIR, 'xgridfit.rng')), self.xgffile] try: self.execute_external(args) except XGFValidationError: raise class XSLTProcessor(): """ Base class for all XSLT processors. """ def __init__(self, config, f, x, p, need_xinclude=False): self.xgffile = f self.params = p self.xslfile = x self.need_xinclude = need_xinclude self.config = config @staticmethod def isEnabled(config): return False def execute_external(self, params): """ Run an XSLT processor. """ process = Popen(params, stdout=PIPE) output = process.communicate()[0] if process.returncode != 0: raise XGFCompilationError('Error from ' + params[0]) return output def run(self): pass class SaxonProcessor(XSLTProcessor): """ Base class for the two Saxon processors we know about (6 and 9). """ def __init__(self, config, f, x, p, need_xinclude=False): XSLTProcessor.__init__(self, config, f, x, p, need_xinclude) def make_params(self, params): param_list = [] for k in params.keys(): param_list.append(k + '=' + params[k]) return param_list class SaxonNineProcessor(SaxonProcessor): """ The current Saxon processor: well optimized! """ def __init__(self, config, f, x, p, need_xinclude=False): SaxonProcessor.__init__(self, config, f, x, p, need_xinclude) @staticmethod def isEnabled(config): return have_program(JAVA_EXECUTABLE) \ and isfile(config.jar_files['saxon-9']) def run(self): diagnostic_message('Running saxon-9 processor ...') start_args = [JAVA_EXECUTABLE, '-classpath', self.config.jar_files['saxon-9'], 'net.sf.saxon.Transform', '-l:on', '-versionmsg:off', '-s:' + self.xgffile, '-xsl:' + self.xslfile] try: return self.execute_external(start_args + self.make_params(self.params)) except XGFCompilationError: raise class SaxonSixProcessor(SaxonProcessor): """ The Saxon 6 processor, still widely used. """ def __init__(self, config, f, x, p, need_xinclude=False): SaxonProcessor.__init__(self, config, f, x, p, need_xinclude) @staticmethod def isEnabled(config): return have_program(JAVA_EXECUTABLE) \ and isfile(config.jar_files['saxon-6']) def run(self): diagnostic_message('Running saxon-6 processor ...') start_args = [JAVA_EXECUTABLE, '-classpath', self.config.jar_files['saxon-6'], 'com.icl.saxon.StyleSheet', '-l', self.xgffile, self.xslfile] try: return self.execute_external(start_args + self.make_params(self.params)) except XGFCompilationError: raise class XalanJProcessor(XSLTProcessor): """ The Xalan-Java processor: current Ubuntu version (Jan. 2010) has a bug that prevents it from stopping on error, so this appears pretty far down the priority list. """ def __init__(self, config, f, x, p, need_xinclude=False): XSLTProcessor.__init__(self, config, f, x, p, need_xinclude) @staticmethod def isEnabled(config): return have_program(JAVA_EXECUTABLE) \ and isfile(config.jar_files['xalan-j']) def run(self): diagnostic_message('Running xalan-j processor ...') param_list = [] for k in self.params.keys(): param_list += ['-param', k, self.params[k]] start_args = [JAVA_EXECUTABLE, '-classpath', self.config.jar_files['xalan-j'], 'org.apache.xalan.xslt.Process', '-l', '-in', self.xgffile, '-xsl', self.xslfile] try: return self.execute_external(start_args + param_list) except XGFCompilationError: raise class XsltprocProcessor(XSLTProcessor): """ Runs the external xsltproc program. Use this if the python binding for libxslt is not installed. """ def __init__(self, config, f, x, p, need_xinclude=False): XSLTProcessor.__init__(self, config, f, x, p, need_xinclude) @staticmethod def isEnabled(config): return have_program('xsltproc') def run(self): diagnostic_message('Running xsltproc processor ...') param_list = [] for k in self.params.keys(): this_param = ['--stringparam', k, self.params[k]] param_list += this_param start_args = ['xsltproc'] if self.need_xinclude: start_args += ['--xinclude'] end_args = [self.xslfile, self.xgffile] all_args = start_args + param_list + end_args if DISPLAY_DIAGNOSTIC_MESSAGES: stderr.write(str(all_args)) try: return self.execute_external(all_args) except XGFCompilationError: raise class XalanCProcessor(XSLTProcessor): """ The Xalan C++ processor: good, fast, but unnecessarily verbose. """ def __init__(self, config, f, x, p, need_xinclude=False): XSLTProcessor.__init__(self, config, f, x, p, need_xinclude) @staticmethod def isEnabled(config): return have_program('xalan') def run(self): diagnostic_message('Running xalan-c processor ...') param_list = [] for k in self.params.keys(): param_list += ['-param', k, "'" + self.params[k] + "'"] start_args = ['xalan', '-in', self.xgffile, '-xsl', self.xslfile] try: return self.execute_external(start_args + param_list) except XGFCompilationError: raise class LibxsltProcessor(XSLTProcessor): """ The default processor: libxslt with its Python bindings. """ def __init__(self, config, f, x, p, need_xinclude=False): XSLTProcessor.__init__(self, config, f, x, p, need_xinclude) self.xslt_error = False @staticmethod def isEnabled(config): try: import libxslt except ImportError: diagnostic_message("No libxslt ...") return False else: diagnostic_message("Have libxslt ...") return True def libxsltError(self, ctxt, error): stderr.write(error) if error.find("Error") >= 0: self.xslt_error = True def run(self): diagnostic_message('Running libxslt processor ...') import libxslt xgfdoc = libxml2.parseFile(self.xgffile) if self.need_xinclude: xgfdoc.xincludeProcess() styledoc = libxml2.parseFile(self.xslfile) style = libxslt.parseStylesheetDoc(styledoc) newparams = dict() for k in self.params.keys(): newparams[k] = "'" + str(self.params[k]) + "'" libxslt.registerErrorHandler(self.libxsltError, style.newTransformContext(xgfdoc)) result = style.applyStylesheet(xgfdoc, newparams) if self.xslt_error: raise XGFCompilationError('Error from libxslt') s = style.saveResultToString(result) xgfdoc.freeDoc() result.freeDoc() styledoc.freeDoc() return s class LxmlProcessor(XSLTProcessor): """ The lxml Python bindings for libxslt. Very good, but does not display messages while running. """ def __init__(self, config, f, x, p, need_xinclude=False): XSLTProcessor.__init__(self, config, f, x, p, need_xinclude) @staticmethod def isEnabled(config): try: from lxml import etree except ImportError: diagnostic_message("No lxml ...") return False else: diagnostic_message("Using lxml ...") return True def run(self): diagnostic_message('Running lxml processor ...') from lxml import etree xgfdoc = etree.parse(self.xgffile) if self.need_xinclude: xgfdoc.xinclude() styledoc = etree.parse(self.xslfile) transform = etree.XSLT(styledoc) newparams = {'silent_mode': "'yes'"} for k in self.params.keys(): newparams[k] = "'" + self.params[k] + "'" # Since lxml won't display messages while running, suppress the # routine ones. try: result = transform(xgfdoc, **newparams) # print any warnings after the run. if len(transform.error_log) > 0: for e in transform.error_log: stderr.write(str(e) + "\n") except etree.XSLTApplyError as msg: raise XGFCompilationError(msg) return(str(result)) class FourSuiteProcessor(XSLTProcessor): """ An XSLT processor written in Python. Good, but slow and verbose. """ def __init__(self, config, f, x, p, need_xinclude=False): XSLTProcessor.__init__(self, config, f, x, p, need_xinclude) @staticmethod def isEnabled(config): try: from Ft.Xml import InputSource from Ft.Lib.Uri import OsPathToUri from Ft.Xml.Xslt import Processor, XsltRuntimeException except ImportError: diagnostic_message("No 4Suite ...") return False else: diagnostic_message("Have 4Suite ...") return True def run(self): diagnostic_message('Running 4Suite processor ...') from Ft.Xml import InputSource from Ft.Lib.Uri import OsPathToUri from Ft.Xml.Xslt import Processor, XsltRuntimeException processor = Processor.Processor() srcAsUri = OsPathToUri(self.xgffile) source = InputSource.DefaultFactory.fromUri(srcAsUri) ssAsUri = OsPathToUri(self.xslfile) transform = InputSource.DefaultFactory.fromUri(ssAsUri) processor.appendStylesheet(transform) try: result = processor.run(source, topLevelParams=self.params) except XsltRuntimeException as msg: raise XGFCompilationError(msg) return result class InstructionSet: """ A set of instructions (for a glyph, function or prep table), read in as a newline-delimited string, parsed, output as a series of Xgridfit and elements, and stored in a libxml2 xmlNode object. """ push_test = compile(r"PUSH[BW]") alpha_test = compile(r"[A-Z]+") num_test = compile(r"[0-9]+") instcomp = compile(r"[A-Z0-5]+") mod1comp = compile(r"\[[01]+\]") mod2comp = compile(r"[01]+") def __init__(self, s): self.raw_instruction_string = s self.instruction_list = self.raw_instruction_string.split("\n") def line_type(self, ln): if search(InstructionSet.push_test, ln): return "push" if search(InstructionSet.num_test, ln) and not search(InstructionSet.alpha_test, ln): return "num" if len(ln.strip()) < 1: return "empty" return "inst" def get_instruction(self, ln): instr = search(InstructionSet.instcomp, ln).group(0) res2 = search(InstructionSet.mod1comp, ln) if res2: modif = search(InstructionSet.mod2comp, res2.group(0)).group(0) else: modif = None return (instr, modif) def parse_and_install(self, parent_element): num_string = "" last_type = "first" for i in self.instruction_list: current_type = self.line_type(i) # diagnostic_message("\ntype of \"" + i + "\": " + current_type + "\n") if current_type != "num" and last_type == "num": parent_element.newChild(None, "push", num_string) num_string = "" if current_type == "inst": inst, mod = self.get_instruction(i) inst_elem = parent_element.newChild(None, "command", None) inst_elem.setProp("name", inst) if mod is not None: inst_elem.setProp("modifier", mod) if current_type == "num": if len(num_string) > 0: num_string += " " num_string += i.strip() last_type = current_type if current_type == "num": parent_element.newChild(None, "push", num_string) class TTXOptions: """ Options for the utility ttx2xgf. """ def __init__(self): global DISPLAY_DIAGNOSTIC_MESSAGES usage_message = "\nttx2xgf infile[.ttx] [outfile]" self.opt_pars = OptionParser(usage_message) self.opt_pars.add_option("--config", dest="config_file", metavar="file", help="full pathname of an Xgridfit configuration file") self.opt_pars.add_option("-e", action="store_true", default=False, dest="display_diagnostic", help="display diagnostic messages (for debugging)") self.opt_pars.add_option("-E", "--elapsed-time", action="store_true", dest="elapsed_time", default=False, help="report the time (in seconds) used for this run \ of ttx2xgf") self.opt_pars.add_option("--processor", dest="preferred_processor", metavar="libxslt|lxml|xsltproc|saxon-6|saxon-9|xalan-j|\ xalan-c|4xslt", help="preferred XSLT processor") (opts, self.args) = self.opt_pars.parse_args() DISPLAY_DIAGNOSTIC_MESSAGES = opts.display_diagnostic self.config_file = opts.config_file self.elapsed_time = opts.elapsed_time self.preferred_processor = opts.preferred_processor self.preferred_validator = None class MergeOptions: def __init__(self): global DISPLAY_DIAGNOSTIC_MESSAGES usage_message = "\nxgfmerge [options] file-a file-b [...]" self.opt_pars = OptionParser(usage_message) self.opt_pars.add_option("--config", dest="config_file", metavar="file", help="full pathname of an Xgridfit configuration file") self.opt_pars.add_option("-e", "-v", action="store_true", default=False, dest="display_diagnostic", help="display diagnostic messages (for debugging)") self.opt_pars.add_option("-E", "--elapsed-time", action="store_true", dest="elapsed_time", default=False, help="report the time (in seconds) used for this run \ of ttx2xgf") self.opt_pars.add_option("--processor", dest="preferred_processor", metavar="libxslt|lxml|xsltproc|saxon-6|saxon-9|xalan-j|\ xalan-c|4xslt", help="preferred XSLT processor") self.opt_pars.add_option("-c", "--use-compile-globals", dest="use_compile_globals", action="store_true", default=False, help="ignore globals in files other than file-a when \ value of \"compile-globals\" default is \"no\"") self.opt_pars.add_option("-n", "--include-no-compile", dest="skip_b_no_compile", action="store_false", default=True, help="Include element") self.opt_pars.add_option("-o", "--out", dest="output_file", metavar="file", help="Write result to file (otherwise to stdout)") self.opt_pars.add_option("-p", "--replace-pre-program", dest="prep_mode", action="store_true", default=False, help="Prefer from file other than file-a") self.opt_pars.add_option("-s", "--sort", dest="sort_glyphs", action="store_true", default=False, help="Sort glyph elements in output") self.opt_pars.add_option("-x", "--xinclude", dest="resolve_xincludes", action="store_true", default=False, help="Resolve XIncludes (except from file-a)") (opts, self.args) = self.opt_pars.parse_args() self.params = {} if opts.use_compile_globals: params["use_compile_globals"] = "yes" if not opts.skip_b_no_compile: params["skip_b_no_compile"] = "no" if opts.prep_mode: params["prep_mode"] = "priority" DISPLAY_DIAGNOSTIC_MESSAGES = opts.display_diagnostic self.elapsed_time = opts.elapsed_time self.config_file = opts.config_file self.preferred_processor = opts.preferred_processor self.output_file = opts.output_file self.sort_glyphs = opts.sort_glyphs self.resolve_xincludes = opts.resolve_xincludes class ConfigOptions: def __init__(self): """ After this runs, precisely one of processors, validators or xgridfit_dir must be true, and we must have a list of arguments in args. These must be in the format saxon-9 or saxon-9=/path/to/saxon9.jar, quoted if it contains spaces. We exit with an error message if more than one of processors, validators, or xgridfit_dir is True or if the args list is empty. """ usage_message = "\nxgfconfig options list" self.opt_pars = OptionParser(usage_message) self.opt_pars.add_option("--config", dest="config_file", metavar="file", help="Xgridfit configuration file to read and write") self.opt_pars.add_option("-p", "--processors", dest="processors", action="store_true", default=False, help="processor list follows") self.opt_pars.add_option("-s", "--show", action="store_true", default=False, dest="show_config", help="display the current configuration") self.opt_pars.add_option("-V", "--validators", dest="validators", action="store_true", default=False, help="validator list follows") self.opt_pars.add_option("-x", "--xgridfit-dir", dest="xgridfit_dir", action="store_true", default=False, help="Xgridfit base directory follows") (opts, self.args) = self.opt_pars.parse_args() self.processors = opts.processors self.validators = opts.validators self.xgridfit_dir = opts.xgridfit_dir self.config_file = opts.config_file self.show_config = opts.show_config if (self.processors and (self.validators or self.xgridfit_dir)) or \ (self.validators and self.xgridfit_dir): stderr.write("You may specify only one of --processors, \ --validators or --xgridfit-dir\n") exit(1) if not self.processors and not self.validators and \ not self.show_config and not self.xgridfit_dir: stderr.write("\nError: Nothing to do!\n\n") self.opt_pars.print_help() exit(1) if len(self.args) < 1 and not self.show_config: err_msg = "You must " if self.processors or self.validators: err_msg += "list the name of at least one " if self.processors: err_msg += "processor\n" if self.validators: err_msg += "validator\n" if self.xgridfit_dir: err_msg += "supply the location of the Xgridfit base directory\n" stderr.write(err_msg) exit(1) class OptionsAndArgs: """ Options for the utility xgfconfig. """ def __init__(self): global DISPLAY_DIAGNOSTIC_MESSAGES usage_message = "\nxgridfit [options] file.{xgf or xml} ..." self.opt_pars = OptionParser(usage_message) self.opt_pars.add_option("-a", "--max-stack", type="int", dest="max_stack", metavar="num", help="size of TrueType stack") self.opt_pars.add_option("-A", "--auto-instr", action="store_true", dest="auto_instr", help="auto-instruct the font before installing \ Xgridfit programming (merge-mode only)") self.opt_pars.add_option("-b", "--delta-break", type="int", dest="delta_break", metavar="num", help="delta break value") self.opt_pars.add_option("-c", "--compile-globals", choices=['yes', 'no'], dest="compile_globals", metavar="yes|no", help="compile functions, control values, \ pre-program and maxp entries (default is \"yes\")") self.opt_pars.add_option("-C", "--color", choices=['black', 'white', 'gray', 'grey'], dest="color", metavar="black|white|gray|grey", help="default color of rounded distances (default \ is \"gray\")") self.opt_pars.add_option("--config", dest="config_file", metavar="file", help="full pathname of an Xgridfit configuration file") self.opt_pars.add_option("-d", "--debug-mode", action="store_true", dest="debug_mode", default=False, help="run in debug mode (output file has extension \ .debug)") self.opt_pars.add_option("-D", "--delete-all", action="store_true", dest="delete_all", help="delete all instruction-related info before \ installing Xgridfit programming (merge-mode only)") self.opt_pars.add_option("-e", action="store_true", default=False, dest="display_diagnostic", help="display diagnostic messages (for debugging)") self.opt_pars.add_option("-E", "--elapsed-time", action="store_true", dest="elapsed_time", default=False, help="report the time (in seconds) used for this \ run of Xgridfit") self.opt_pars.add_option("-f", "--execute", action="store_true", dest="execute", default=False, help="execute the generated script; do not save") self.opt_pars.add_option("-F", "--data-file", dest="data_file", metavar="filename", help="Store font information in a file instead \ of in FontForge's font.persistent object (merge-mode only)") self.opt_pars.add_option("-g", "--glyph-select", dest="glyph_select", metavar="glyph+list", help="compile only glyphs in this list (delimit \ with +)") self.opt_pars.add_option("-G", "--init-graphics", choices=['yes', 'no'], dest="init_graphics", metavar="yes|no", help="initialize graphics state tracking in glyph \ programs (default is \"yes\")") self.opt_pars.add_option("-H", "--auto-hint", choices=['yes', 'no'], dest="auto_hint", metavar="yes|no", help="auto-hint the font before auto-instructing \ (default is \"yes\"; has no effect except with --auto-instr; merge-mode only)") self.opt_pars.add_option("-i", "--infile", dest="infile", metavar="filename", help="file to be input by generated script") self.opt_pars.add_option("-l", "--language", choices=['ff', 'py'], dest="language", default="py", metavar="py|ff", help="language of script to be output: Python \ or native FontForge (default is \"py\")") self.opt_pars.add_option("-m", "--merge-mode", action="store_true", dest="merge_mode", default=False, help="run in merge-mode") self.opt_pars.add_option("-o", "--outfile", dest="outfile", metavar="filename", help="file to be output by generated script") self.opt_pars.add_option("-O", "--output-script", dest="output_script", metavar="filename", help="script file to be output by Xgridfit") self.opt_pars.add_option("-p", "--push-break", type="int", dest="push_break", metavar="num", help="push break value") self.opt_pars.add_option("-P", "--combine-prep", choices=['yes', 'no'], dest="combine_prep", metavar="yes|no", help="combine Xgridfit pre-program with the \ font's prep table (merge-mode only; default is \"yes\")") self.opt_pars.add_option("--processor", dest="preferred_processor", metavar="libxslt|lxml|xsltproc|saxon-6|saxon-9|\ xalan-j|xalan-c|4xslt", help="preferred XSLT processor") self.opt_pars.add_option("-q", "--quiet", action="store_true", dest="silent_mode", help="run in quiet mode") self.opt_pars.add_option("-s", "--max-storage", type="int", dest="max_storage", metavar="num", help="max places in storage area (variables)") self.opt_pars.add_option("-S", "--output-base", dest="outfile_base", metavar="name", help="save script for each glyph in file \ name_glyphname.pe (works only with option --language ff)") self.opt_pars.add_option("--skip-validation", action="store_false", dest="validate", default=True, help="skip Relax NG validation") self.opt_pars.add_option("-t", "--max-twilight", type="int", dest="max_twilight", metavar="num", help="max points in twilight zone") self.opt_pars.add_option("-T", "--temp-file", dest="temp_file", metavar="filename", help="temporary file for XInclude results") self.opt_pars.add_option("-v", "--version", action="store_true", dest="version", default=False, help="show version number and exit") self.opt_pars.add_option("-V", action="store_true", dest="dummy_validate", default=False, help="Validate Xgridfit program before compiling \ (has no effect since the default is now yes)") self.opt_pars.add_option("--validator", dest="preferred_validator", metavar="libxml2|lxml|jing|msv|rnv", help="preferred Relax NG validator") self.opt_pars.add_option("-x", "--skip-compilation", action="store_true", dest="skip_compilation", default=False, help="Do not compile. Validation is performed if \ --skip-validation does not block it") self.opt_pars.add_option("-X", "--no-xinclude", action="store_false", dest="perform_xinclude_check", default=True, help="Assume that XInclude is unnecessary; \ do not check") self.opt_pars.add_option("-z", "--output-outfile-script", dest="outfile_script_name", metavar="name", help="name of separate script file for output of \ (works only with options --language ff --output-glyph-script)") (opts, self.args) = self.opt_pars.parse_args() self.params = {'max_stack': None, 'auto_instr': None, 'delta_break': None, 'compile_globals': None, 'color': None, 'delete_all': None, 'data_file': None, 'glyph_select': None, 'init_graphics': None, 'auto_hint': None, 'infile': None, 'outfile': None, 'push_break': None, 'push_break': None, 'combine_prep': None, 'silent_mode': None, 'max_storage': None, 'outfile_base': None, 'outfile_script_name': None, 'max_twilight': None} # Extract all the params that have got to be passed to the # XSLT processor and put them in self.params (but we pass # 'yes' not True). for k in opts.__dict__.keys(): if k in self.params: int_val = opts.__dict__[k] if int_val is not None: if int_val == True: int_val = 'yes' if int_val == False: int_val = 'no' if type(int_val) is int: int_val = str(int_val) self.params[k] = int_val # Discard any undefined params. for k in self.params.keys(): if self.params[k] is None: del self.params[k] if DISPLAY_DIAGNOSTIC_MESSAGES: stderr.write("Parameters:\n") stderr.write(str(self.params)) # These are the params we deal with in this script; they are # not passed to the XSLT processor. DISPLAY_DIAGNOSTIC_MESSAGES = opts.display_diagnostic self.config_file = opts.config_file self.debug_mode = opts.debug_mode self.elapsed_time = opts.elapsed_time self.execute = opts.execute self.language = opts.language self.merge_mode = opts.merge_mode self.output_script = opts.output_script self.temp_file = opts.temp_file self.version = opts.version self.validate = opts.validate self.perform_xinclude_check = opts.perform_xinclude_check self.skip_compilation = opts.skip_compilation self.preferred_processor = opts.preferred_processor self.preferred_validator = opts.preferred_validator # fixups: certain options are incompatible. if self.merge_mode: self.language = 'py' if 'outfile_base' in self.params: del self.params['outfile_base'] if 'outfile_script_name' in self.params: del self.params['outfile_script_name'] if self.debug_mode or 'outfile_base' in self.params: self.execute = False class Configuration(): """ Reads and manages a configuration file, which stores a user's preferred processor and validator, and also an Xgridfit base directory, if different from the default. To do: permit default Xgridfit options. """ default_validator_priority = ['libxml2', 'lxml', 'rnv', 'jing', 'msv'] default_processor_priority = ['libxslt', 'saxon-9', 'xsltproc', 'xalan-c', 'lxml', 'saxon-6', '4xslt', 'xalan-j'] processor_jar_files = ['saxon-9', 'saxon-6', 'xalan-j'] validator_jar_files = ['jing', 'msv'] java_progs = processor_jar_files + validator_jar_files default_jar_files = {'saxon-9': '/usr/share/java/saxon9.jar', 'saxon-6': '/usr/share/java/saxon.jar', 'xalan-j': '/usr/share/java/xalan2.jar', 'jing': '/usr/share/java/jing.jar', 'msv': '/usr/share/java/msv/msv.jar'} validator_classes = {'lxml': LxmlValidator, 'libxml2': LibxmlValidator, 'rnv': RnvValidator, 'jing': JingValidator, 'msv': MsvValidator} processor_classes = {'libxslt': LibxsltProcessor, 'lxml': LxmlProcessor, 'xsltproc': XsltprocProcessor, 'xalan-c': XalanCProcessor, 'saxon-9': SaxonNineProcessor, 'saxon-6': SaxonSixProcessor, '4xslt': FourSuiteProcessor, 'xalan-j': XalanJProcessor} default_xgridfit_dir = XGRIDFIT_DIR def __init__(self, config_file=None, write_access_needed=False): """ Reads a config file and stores the content in a usable form. """ self.validator_priority = list(Configuration.default_validator_priority) self.processor_priority = list(Configuration.default_processor_priority) self.jar_files = Configuration.default_jar_files.copy() if config_file is not None: self.config_file = config_file else: self.config_file = self.__find_config_file(write_access_needed) diagnostic_message("Using config file " + self.config_file) try: self.processor_priority = self.__read_config_list(self.processor_priority, "processor") self.validator_priority = self.__read_config_list(self.validator_priority, "validator") new_xgridfit_dir = self.__get_config_item('xgridfit-dir', None) if new_xgridfit_dir is not None: if isdir(new_xgridfit_dir): adjust_directories(new_xgridfit_dir) else: stderr.write(new_xgridfit_dir + " is not a directory\n") except libxml2.parserError: stderr.write("Could not read configuration file " + self.config_file + "\n") if DISPLAY_DIAGNOSTIC_MESSAGES: stderr.write("New processor priority:\n") stderr.write(str(self.processor_priority)) stderr.write("New validator priority:\n") stderr.write(str(self.validator_priority)) stderr.write("New jar file dict:\n") stderr.write(str(self.jar_files)) def show_current_config(self): """ Print the current configuration on the console. """ stdout.write("Current configuration file: ") if isfile(self.config_file): stdout.write(self.config_file) else: stdout.write("None (this is the default configuration)") stdout.write("\n") print "Processors in order of preference:" for p in self.processor_priority: stdout.write(" " + p) if p in self.jar_files: stdout.write(" (" + self.jar_files[p] + ")") stdout.write("\n") print "Validators in order of preference:" for v in self.validator_priority: stdout.write(" " + v) if v in self.jar_files: stdout.write(" (" + self.jar_files[v] + ")") stdout.write("\n") print "Xgridfit base directory: " print " ", XGRIDFIT_DIR def __processor_jar_files_changed(self): """ True if the current list of processor jar files differs from the default """ changed = False for p in Configuration.processor_jar_files: if self.jar_files[p] != Configuration.default_jar_files[p]: changed = True break return changed def __validator_jar_files_changed(self): """ True if the current list of validator jar files differs from the default """ changed = False for v in Configuration.validator_jar_files: if self.jar_files[v] != Configuration.default_jar_files[v]: changed = True break return changed def save_file(self): """ Saves the file, with whatever needs saving. """ cfgdoc = libxml2.newDoc("1.0") cfgdoc.newChild(None, "xgfconfig", None) ctxt = cfgdoc.xpathNewContext() root_node = ctxt.xpathEval("/xgfconfig")[0] if self.processor_priority != Configuration.default_processor_priority or \ self.__processor_jar_files_changed(): for pv in self.processor_priority: new_node = root_node.newChild(None, "processor", pv) if pv in self.jar_files: new_node.setProp("jar", self.jar_files[pv]) if self.validator_priority != Configuration.default_validator_priority or \ self.__validator_jar_files_changed(): for pv in self.validator_priority: new_node = root_node.newChild(None, "validator", pv) if pv in self.jar_files: new_node.setProp("jar", self.jar_files[pv]) if Configuration.default_xgridfit_dir != XGRIDFIT_DIR: dir_node = ctxt.xpathEval("/xgfconfig/xgridfit-dir") if len(dir_node) > 0: dir_node[0].content = XGRIDFIT_DIR else: root_node.newChild(None, "xgridfit-dir", XGRIDFIT_DIR) if CONFIG_DIR == dirname(self.config_file) and not isdir(CONFIG_DIR): mkdir(CONFIG_DIR) cfgdoc.saveFormatFile(self.config_file, 1) def __read_config_list(self, prog_list, tag): """ Read a configuration file and use the data found there to reorder a priority list and revise a dictionary containing the locations of jar files. """ if isfile(self.config_file): diagnostic_message("Reading config file " + self.config_file) if DISPLAY_DIAGNOSTIC_MESSAGES: stderr.write("Old priority list:\n") stderr.write(str(prog_list)) doc = libxml2.parseFile(self.config_file) ctxt = doc.xpathNewContext() node_name = "/xgfconfig/" + tag node_list = ctxt.xpathEval(node_name) if len(node_list) > 0: new_priority = [] for n in node_list: p_name = n.content.strip() if p_name in prog_list: diagnostic_message("have ref to program " + p_name) new_priority.append(p_name) if p_name in Configuration.java_progs: ctxt.setContextNode(n) jar = ctxt.xpathEval("@jar") if len(jar) > 0: diagnostic_message("have ref to jar " + jar[0].content) j_file = jar[0].content if isfile(j_file): self.jar_files[p_name] = j_file else: diagnostic_message("have no ref to jar " + j_file + "\n") for p in prog_list: if not p in new_priority: new_priority.append(p) else: new_priority = prog_list doc.freeDoc() ctxt.xpathFreeContext() else: new_priority = prog_list return new_priority def adjust_configuration(self, opts): """ Adjust the configuration using stuff from the command line. """ if opts.preferred_processor is not None: try: self.processor_priority.remove(opts.preferred_processor) except ValueError: stderr.write("There id no processor " + opts.preferred_processor + "\n") else: self.processor_priority.insert(0, opts.preferred_processor) if opts.preferred_validator is not None: try: self.validator_priority.remove(opts.preferred_validator) except ValueError: stderr.write("There id no validator " + opts.preferred_validator + "\n") else: self.validator_priority.insert(0, opts.preferred_validator) def __get_config_item(self, tag, default_value=None): """ Retrieve an item from the configuration file. """ result = default_value if isfile(self.config_file): diagnostic_message("Retrieving item " + tag + " from " + self.config_file) doc = libxml2.parseFile(self.config_file) ctxt = doc.xpathNewContext() node_name = "/xgfconfig/" + tag node_list = ctxt.xpathEval(node_name) if len(node_list) > 0: result = node_list[0].content doc.freeDoc() ctxt.xpathFreeContext() diagnostic_message("Result is " + str(result)) return result def __find_config_file(self, write_access_needed): """ Find the configuration file, or a location for the file, where we have the appropriate permission. If we don't need write access, we first look for a local file config.xml, then in the user's config directory, then in the Xgridfit base directory. If write access *is* needed, we try first for the local file, then in the Xgridfit base directory, finally in the user's config directory. So running xgfconfig as root should normally change the default configuration system-wide. """ access_mode = R_OK if write_access_needed: access_mode |= W_OK fname = "config.xml" sys_fname = join(XGRIDFIT_DIR, fname) default_fname = join(CONFIG_DIR, fname) if not write_access_needed: if isfile(fname) and access(fname, access_mode): return(fname) if isfile(default_fname) and access(default_fname, access_mode): return(default_fname) if isfile(sys_fname) and access(sys_fname, access_mode): return(sys_fname) return(default_fname) else: if isfile(fname) and access(fname, access_mode): return(fname) if access(XGRIDFIT_DIR, access_mode): return(sys_fname) return(default_fname) def parse_priority_list(self, priority_list, target_list): """ priority_list is a list of processor or validator names, optionally followed by a hash sign and the pathname of a jar file. target_list is edited so that the items in priority_list are deleted from their original positions in the list and prepended to it. If a jar file is specified and we know that the app in question needs one, then we associate the jar file with the app in self.jar_files. Note that this method changes priority_list in place, assuming that we have no further use for it. """ priority_list.reverse() for p in priority_list: jar_item = None if p.find('#') >= 0: priority_item, jar_item = p.split('#', 1) else: priority_item = p if priority_item in target_list: del target_list[target_list.index(priority_item)] target_list.insert(0, priority_item) if jar_item is not None: if priority_item in self.jar_files: if isfile(jar_item): self.jar_files[priority_item] = jar_item else: stderr.write("File " + jar_item + " does not exist\n") else: stderr.write("Program " + priority_item + " does not require a jar file\n") else: stderr.write("I don't know a processor or validator " + priority_item + "\n") exit(1) def run_xgridfit(xgfdir="/usr/local/share/xml/xgridfit/"): XGRIDFIT_DIR = abspath(xgfdir) """ Validates and compiles an Xgridfit program. """ start_time = time() # Parse the command line. options_and_args = OptionsAndArgs() if options_and_args.version: print VERSION return True # Choose the XSLT script we want. xsl_file = 'xgridfit-python.xsl' if options_and_args.debug_mode: xsl_file = 'xgridfit-debug.xsl' if options_and_args.merge_mode: xsl_file = 'xgridfit-merge.xsl' if options_and_args.language == 'ff': xsl_file = 'xgridfit.xsl' # Anything to do? if len(options_and_args.args) < 1: stderr.write("\n\nError: No Xgridfit file specified!\n\n") options_and_args.opt_pars.print_help() return False # Read configuration file and consult command line for validator and # processor priorities. config = Configuration(config_file=options_and_args.config_file, write_access_needed=False) config.adjust_configuration(options_and_args) # Find an XSLT processor. if not options_and_args.skip_compilation: processor = findProcessor(config) if processor is None: stderr.write(NO_PROCESSOR_ERROR) return False # Find a Relax NG validator. if options_and_args.validate: validator = findValidator(config) if validator is None: options_and_args.validate = False system.stderr.write("Can't find a validator: skipping validation\n") error_free = True # Process each file on the command line. for xgf_file in options_and_args.args: original_xgf_file = xgf_file # Do we have the file? if not isfile(xgf_file): stderr.write("Can't find file " + xgf_file + "\n") return False # Check if we need XInclude. if options_and_args.perform_xinclude_check: need_xinclude = has_xinclude_namespace(xgf_file) else: need_xinclude = False ffscript = None delete_temp_file = False # Name the output file. if options_and_args.language == 'py': out_ext = ".py" else: out_ext = ".pe" output_script = splitext(xgf_file)[0] + out_ext # Merge in XIncludes, if we have to, and save the result in a temp file. if need_xinclude and \ (options_and_args.validate or (not processor in [LxmlProcessor, LibxsltProcessor, XsltprocProcessor])): xgf_file = xinclude_temp_file(xgf_file, tfile=options_and_args.temp_file) delete_temp_file = (options_and_args.temp_file == None) diagnostic_message("xgf_file is " + xgf_file) diagnostic_message("delete_temp_file is " + str(delete_temp_file)) need_xinclude = False diagnostic_message("Using temp file " + xgf_file) # Validate if we haven't been told not to. if options_and_args.validate: try: validator(config, xgf_file, need_xinclude).validate() except XGFValidationError as d: stderr.write(str(d) + "\n") error_free = False except Exception as d: stderr.write(str(d) + "\n") error_free = False else: diagnostic_message("valid") # If no errors so far, go on and compile. if error_free and not options_and_args.skip_compilation: # Use the script file name supplied by user. if options_and_args.output_script is not None: output_script = options_and_args.output_script try: ffscript = processor(config, xgf_file, abspath(join(XSLT_DIR, xsl_file)), options_and_args.params, need_xinclude).run() except XGFCompilationError as d: stderr.write(str(d) + "\n") error_free = False except Exception as d: stderr.write(str(d) + "\n") else: if options_and_args.execute: xgf_prog = Popen(['python', '-'], stdin=PIPE) xgf_prog.communicate(ffscript) if xgf_prog.returncode != 0: stderr.write("Error executing Xgridfit-generated script\n") else: f = open(output_script, 'w') f.write(ffscript) f.close() # A little fussy, but it calms my nerves. if delete_temp_file and original_xgf_file != xgf_file: diagnostic_message("removing " + xgf_file) remove(xgf_file) # If error, don't go on to next file. if not error_free: break if options_and_args.elapsed_time: print "Elapsed time:", time() - start_time return error_free def run_config(xgfdir="/usr/local/share/xml/xgridfit/"): XGRIDFIT_DIR = abspath(xgfdir) """ Creates/reads/updates a configuration file. """ # Parse the command line options_and_args = ConfigOptions() # Read the configuration file config = Configuration(config_file=options_and_args.config_file, write_access_needed=not options_and_args.show_config) # Show the current configuration and exit if options_and_args.show_config: config.show_current_config() exit(0) # We will revise only one of these: processors, validators, # xgridfit_dir current_list = None if options_and_args.processors: current_list = config.processor_priority if options_and_args.validators: current_list = config.validator_priority # If we have a list, edit it in place if current_list is not None: config.parse_priority_list(options_and_args.args, current_list) if options_and_args.xgridfit_dir: XGRIDFIT_DIR = options_and_args.args[0] # Save the new configuration file try: config.save_file() except Exception as d: stderr.write(str(d)) return False return True def run_ttx2xgf(xgfdir="/usr/local/share/xml/xgridfit/"): XGRIDFIT_DIR = abspath(xgfdir) """ Extract TT instructions from a TTX file. """ start_time = time() libxml2.keepBlanksDefault(0) # Parse the command line options_and_args = TTXOptions() # Read the configuration file config = Configuration(config_file=options_and_args.config_file, write_access_needed=False) config.adjust_configuration(options_and_args) # Anything to do? if len(options_and_args.args) < 1: stderr.write("\n\nError: No TTX file specified!\n\n") options_and_args.opt_pars.print_help() exit(1) else: # Do some automatic naming if necessary ttx_file = options_and_args.args[0] if not ttx_file.endswith((".TTX", ".ttx"), 1): ttx_file += ".ttx" if len(options_and_args.args) > 1: xgf_file = options_and_args.args[1] else: xgf_file = splitext(ttx_file)[0] + ".xgf" diagnostic_message("TTX file is " + ttx_file) diagnostic_message("XGF file is " + xgf_file) # Find a processor to use. processor = findProcessor(config) if processor is None: stderr.write(NO_PROCESSOR_ERROR) exit(1) error_free = True # Do the transformation. try: xgf_output = processor(config, ttx_file, abspath(join(UTIL_DIR, "convert-ttx.xsl")), {}, False).run() except XGFCompilationError as d: stderr.write(str(d) + "\n") error_free = False except Exception as d: stderr.write(str(d) + "\n") error_free = False if error_free: # The instructions are still raw. We need to convert them to XGF # command and push elements. If we've gotten this far there's not # whole lot that can go wrong, so cover it with one big try block. try: # Get the output as a libxml2 doc. xgf_intermediate_doc = libxml2.parseDoc(xgf_output) # Free up some memory. del xgf_output xgf_root = xgf_intermediate_doc.getRootElement() # Get a list of all the glyph programs. glyph_list = xgf_root.xpathEval("*[local-name() = 'glyph']") # Convert raw instructions to Xgridfit command and push elements. for g in glyph_list: iset = InstructionSet(g.content) for c in g.get_children(): c.unlinkNode() c.freeNode() iset.parse_and_install(g) # Do the same for legacy-functions and pre-program elements. tmp_elem_list = xgf_root.xpathEval("*[local-name() = 'legacy-functions']") if len(tmp_elem_list) > 0: tmp_elem = tmp_elem_list[0] iset = InstructionSet(tmp_elem.content) for c in tmp_elem.get_children(): c.unlinkNode() c.freeNode() iset.parse_and_install(tmp_elem) tmp_elem_list = xgf_root.xpathEval("*[local-name() = 'pre-program']") if len(tmp_elem_list) > 0: tmp_elem = tmp_elem_list[0] iset = InstructionSet(tmp_elem.content) for c in tmp_elem.get_children(): c.unlinkNode() c.freeNode() iset.parse_and_install(tmp_elem) # Save the file and free the memory. xgf_intermediate_doc.saveFormatFile(xgf_file, 1) xgf_intermediate_doc.freeDoc() except Exception as d: stderr.write(str(d) + "\n") error_free = False if options_and_args.elapsed_time: print "Elapsed time:", time() - start_time return error_free def run_xgfmerge(xgfdir="/usr/local/share/xml/xgridfit/"): XGRIDFIT_DIR = abspath(xgfdir) start_time = time() # Parse the command line options_and_args = MergeOptions() # Read the configuration file config = Configuration(config_file=options_and_args.config_file, write_access_needed=False) config.adjust_configuration(options_and_args) xgridfit/python/setup.py0000644000175000017500000000016111353456350014754 0ustar peterpeterfrom distutils.core import setup setup(name='xgflib', version='1.0', py_modules=['xgflib'], ) xgridfit/docs/0000755000175000017500000000000011572451632012654 5ustar peterpeterxgridfit/docs/parch-dark.jpg0000644000175000017500000000621610736450467015405 0ustar peterpeterJFIFHHCreated with The GIMPC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222"&!1AQaq"R ?m|Ef!:猯j~d6vPY˓%DU :FR& o3YPMt6UFXzq[6o%A`'P9P.؝u 4lW!UQs"xѻxn|Q\q|t5Y%.Vne"$4(~rAH`PX4ڜ'GYa!m'`eECZ,j-FR--%?U[ګwndԈ3DDŽҤRE0򏖘IXu3{6+ 9B>fa._B#+GBdo$aCCǬ6rERR{"YM<;@uv`{´ dB5D"X*A!g41ەW(?ZMoӀIOZTM?&T.rPW~3.Ax`Wu_NMГn9>*+\,xkW,|z!G"\ū' x 523Qw*m_ҡq)S6A<{M"ҩrh|#BMp5<ù:ѫ_?NQ;ؓfSCMlXW(CnDA="j\R=_kKT1 Cf"tuݟ.+yrsmFѠQQw G8"v y.(ٱe8][Ɯ-4D|*loyzȍշq0#xT!*r~y0kxU,[>CyFQ ۬nY2VgɾrQRPt|bIl5,3dO.Q [o+ P w4\ѻ̠lPPRqQCs}ITRN t^X=e ;g8M^[a-bMBdFRn뿼 x~]qxJNCԣ9smӢPŠ3=dup)&1;bpjwF4Ŝx]x̊҂][9=&mzDp<'M ZJ`* uOmV30k-(!w^LEP9zBuGN2ئxN*) -%FM4n 5Uy;Os&1 *6)D9ˆv`~uH{(D7 I?{χ|VuMmv_xƜpz$MQۭϼ *?~0qTHPa˴:DQ@Ķ{\R`mt8ɈXPy^p*cnt$NPN)IfKog 5ECyY;>*sXsa8 w[]; Tq_nEUy7gɊP}NDXs>@vuG0E7D1|4ʀ (:fwyV Y+iͺ߶s(R_߼I{T@ɬiTŲn:eh%Q%N/O|Wls`J*=k0%:]PZ@ۯG S}qЮD٭fK䈈K~2ECOL0J4z2 # 1K?A?˼9S[t$٭)L^w9ֿ$AjDSFlhQC|s"_Ÿ$|.(+d)eʃ8r| hu1l-2DDWTPV*x5DeOF85Б(7WfſtQ䀪E`!ʊ:&05 fg7_oAR:U?"R1lhɅUx kx08Nfk81ZuX5U[S[,hGEժ3U\E /J$ޔ p򇖊:ۃO6Y;[߬ϒk٘rSxgridfit/docs/low-level.html0000644000175000017500000001712411100636163015444 0ustar peterpeter Xgridfit

Low-level elements

Though Xgridfit tries to provide as much functionality as possible in its high-level programming constructs, there may well be times when you feel you need to write low-level, "raw" instructions, either because Xgridfit does not meet some particular need or because a job can be done most efficiently with low-level instructions. Xgridfit provides three elements to help you write low-level code.

<command>

The <command> element will insert any TrueType instruction into your Xgridfit program. If the command reads values from the stack or writes to it, it is up to you to manage the stack yourself. Here is a simple example:

      <command name="ALIGNRP"/>
    

A number of instructions take one or more bits as modifiers. For example, the MIAP instruction, which positions a point at a grid coordinate read from the control-value table, takes a single modifier bit that indicates whether the control-value should be rounded before the point is positioned. The modifier can be noted in more than one way, even when entered in FontForge:

      MIAP[1]
      MIAP[rnd]
    

There are two ways to insert modifiers in Xgridfit: one is compact, easy and possibly non-portable, and the other is verbose but portable. The compact method is to include a modifier attribute containing a string which is to be copied verbatim into Xgridfit's output code:

      <command name="MIAP" modifier="1"/>
      <command name="MIRP" modifier="01100"/>
    

The verbose method is to include one or more <modifier> elements as children of <command>. Each element defines a bit:

      <command name="MIAP">
        <modifier type="round" value="yes"/>
      </command>

      <command name="MIRP">
        <modifier type="set-rp0" value="no"/>
        <modifier type="round" value="yes"/>
        <modifier type="minimum-distance" value="yes"/>
        <modifier type="color" value="gray"/>
      </command>
    

At present there is no advantage, aside from legibility (and who cares about that?), to using <modifier>. But if Xgridfit at some future time acquires the ability to produce input for some font production program other than FontForge, the verbose method is guaranteed to work while the compact method is not.

It is not necessary to provide a <modifier> for every bit that can accompany an instruction: all modifier types have defaults. Here are the modifier types, with all possible values, and with defaults in bold:

  • set-rp0: yes, no.
  • round: yes, no.
  • minimum-distance: yes, no.
  • color: gray, black, white.
  • grid-fitted: yes, no.
  • to-line: parallel, orthogonal.
  • axis: x, y.
  • ref-ptr: 1, 0.

If you are planning to write low-level code, you presumably know already which instructions have modifier bits and what those bits do. If you do not, consult the TrueType Reference Manual.

<push>

Many TrueType instructions operate upon values they pop from the stack; thus you must have have a way to move values onto the stack. TrueType provides a variety of PUSH instructions, depending on how the values are stored in the program code (as bytes or words) and how many values need to be pushed. Xgridfit reduces this variety to a single element: <push>, which takes a list of values. These are valid Xgridfit <push> instructions:

        <push>2 5 89 67</push>

        <push>
          left
          right
          lc-vertical-stem
          -1
        </push>

        <push> 0.58p 2.0 to-grid </push>

        <push>1 (top + 3) 512</push>

	<push>minimum-distance</push>
    

Notice that all expressions containing whitespace must be enclosed in parentheses.

The Xgridfit <push> element may invoke the TrueType PUSHB and PUSHW instructions, which push number literals onto the stack; but it can also handle variables and other values that can be resolved only at run-time. In other words, it is a general-purpose element for moving numbers of all kinds onto the stack. The list of values in a single <push> element can be heterogeneous: some bytes, some words, some variables.

Here is an example of the use of <push> in a fragment of code from a function, in which the point line-2-a and the control-value cvt have been passed in as parameters:

      <push>line-2-a cvt</push>
      <command name="MIRP">
        <modifier type="color" value="black"/>
      </command>
    

This code fragment also shows, incidentally, how a <command> element can be abbreviated by accepting defaults. It is functionally the same as this:

      <command name="MIRP">
        <modifier type="set-rp0" value="yes"/>
        <modifier type="minimum-distance" value="yes"/>
        <modifier type="round" value="yes"/>
        <modifier type="color" value="black"/>
      </command>
    

<to-stack>

<to-stack>, an element for moving a single value onto the stack, is deprecated as of Xgridfit version 1.11, as <push> can perform the same function.

xgridfit/docs/bbar-revised.png0000644000175000017500000002767411130460714015736 0ustar peterpeterPNG  IHDR"sRGBbKGD pHYs  tIME5q IDATxwtMm{d7lSCKBB(!|$!Ԑ :Ĵ7qWYՒee@Xuvvus|}g̽WZL4s.8EGǺZŜĵC@^(p^[w9kNzTQ9Qu˵@#A 9tw 5Njݩyo=': 5' 'k`r ֜h # # # # K91odC;lVIv qsҞSrި~[S١ж~f4SDNqMOdr-Y~ ~ٲ.TYiR04 ֵo0#`~*ICkC]p$O')C4'>AE&OZ8tSV7HN><9ubI&RMlYֿvaVU6GE&**71y. 5g '9BrsqS9P94}!tHJ5Fe'_5co&ᗱ2.p<CqTL.ET8@U8JqLFHa7}MrAܛp?A 8Ygޞ)() xe _ x)Ub1K;-]ު V86|Y/V"I*ʗȐGhlmvbTG)j;֪lH J! yw6h ނ^)zjRi$%-%4{Ӹw QdRdAdѻ|255VŸ?&΢NT^;kwz8B8}VI/Ïc[Ppb04`>t}kOclޒSadsk*Uu_6ʔzF6sZ{+ٿ=XB@cxs.95u1 oOdS]_R16bǍۺ<.lx7&z<>2lE=r_kzC|rs Eg#9|=^gdsqpzfqFp%M&qFp7cp.3kx/a= %l8VnKl.krxE^W . -j ˆ\9<ڋ!l]sVQEi @kӒސE2S!-LdSAoHӬn&$ ĺW,$-zB8Y2 d |1łDŽ s7USWTp$zQ6rR8z+i0 G뫱GFFE,Z:бNԔ u*Td綷01P!K2|x WQXE^gŊ[:9J1)ꄑytvzU M)Ԣ ;}nǀَiД[gϭxImB@9,"nKf ůEdSA0DD",kbMI0 ĨSE",SEEX% `lF2 7eF6oŊ٣ F6Рc~Td[s`N1n~*DE67qˑqpppE8dR\kl\kl\kl\kيl\kl\ktB8B8B8ˌlJӒblJC}pK S#۲e7+ȦF67q[5# # # # 3ad~ad@adad@adad0y?0yCټCLG 8!!!B|8A~酑ad8B8B8B8M8zad~ad0y?0 00 00yCټC )l]ʇxaDWfigK4iisn+8$$rnv~+T1Rlď* #8B.䷆k1OHw1:I8.qEys~ET"mNoWxU?I-גeۧJ^i<[x)+9zcqdkPl/&Nr [>An=6aL{Gz?o`yG9}8B't&5N {hhJ 1\oref~eu9|/I0ܬ~&lnp3KoazL\ZEp|/0ZQ0o,/_vgb ^z}F68]Uk,s+i0 ى/p^4.x1-EY8@:{9=T Rc- d(7!2r# @TaJ1 'QM:dU^mKy{ _Iv+РWuܴ&KIL7ZҰopiLJ#=$!DGM6IՅ`07j5f3djc6r L y /`r͞>/1i# Js)'!ͰV6}gUPŽ=T8fNn'XB{Orΐ774s<5l卲8f8Jnt$\ Mzs:2-RV%@gaw{dd$*ELG#THH#'x7'k _T-O#K2W$\K T**OCZ0V⢒j22˪?ҽppʋ#^ff,+5zIO&/׸Kv,O6E,ɐČS3X1 6j?Eagƅg\x x)+{3缈\.) _0V.+lnٴ^On4aa9߁:nrإ&* g HlWTUuꊐgFm'y$<39KI0oTuLO<&}5hx23.rgSȺ\3n~=Fkk9}2tFgNgN<ޛ4Ȏ]wү:x}EE_;;kޫᏣ3ǞSN?LY˝nê#94Ghdmx2be26}sU(-XjJZ^"/8<`LTds 72+rvi~ GF,"Y\z) ~M\,-BF/H}7E"yaK]Eea"b6[3o=w`[p܀|FGTԲ勨P!EtS̈́x%!_@>.M'/aOnJGBcݒ9tTQe+&?'ۦj+5hhw@oلp܀z[%Qhm_\[TÚ$Ͽ߶("y7 #qmUoĔ( WBx,5R#vh/JX|.0Y1;y7=WqD&tP/8_”=ULuɹ),yj&K|mL%9jnYnGm:1`~GZglmgu:'T'8*8X8&Nf7= ,YY)#|ܚp;뾤cgQ2R*P64a4mGlmXnNȍDS\'l?.01#|c;|W3mk]rn\uC O%7)_ # !;l(kvykq9|su~±wyNMHf1ڕ tL7;" %")>6ذ3U:fEs1~T@Ǹ<' '59=C+#?e²e7sqsx-l5N̨Ie%5zmN":x҇#"蘆PQso\Mey[r"ln "Sɇ'?8"gr~M{'?~@M]3fh0:-9F670IDATs?iZHԜ#X]%sb bu1ra0DLG̍Kmz cy4op)mB8_ qCϷuu*Ɔ#/c14TUcfD"a}`uQ)=ӊ"JưEsrc ,N^.xgۘגG܈\"pPsIInMݜ'FO]>)uI7p[: E.¦'[,2l/e?t{<'$GZru5HrכL#[,uw%;׹5-kC8^^?3&2W<>4~XqS\u҇wo{,N1i@u)>:LټiHW!|=Fhp#IJĥuQ_^J r͹e_F/Or[}~T;RqUUl JH]D3<˰-\x~Sܪy.+8wI6>["Ehdg&,<_yetD81qT wԇSqi ёӝeذO+>_ tmsW_#>^R-!~:'>tL7'%=c乺jVa~W#pw%;$? 鷀jU,taLC@ts\E^:\ַ~a,gȧhwl;\l&sX=9)#ۏQQs}g?P~BH8nAy駘gkE7wTF4SNfR]oopb;xںM(\չŊ[8i1ڌ}.~q/)Eu?v}Ջl=7늵R*UBLk^I7!\aKJ Rlgv8+^Oy6g 5FF@)N\rO+k7?\x o^%Kڣ-f4e2^ xYLsM#͏q'}'^To~SőѾ3&kj nX]%m#M=VVLLXNi{姗/=?#{jވT}·\[v;wFqKvqsj=v9aCYh)oqEGr\bBsܪFTC77mϢ(bnIxxrMN<16/Œ+5s@lcd+-԰~E;hWw+&K#A<3:( l G$S3*HKcb(+с FXG:g? dߵoH3s;s}Ԕ##c> t`+dg;EwкB\OW31|N]θ4FRtcs#9 }xj,SޮHɴie yu-Ҳgg}v{;-0M8g<:BC*دu"$j FuW/Iŭ)1*x4n"NOmr}ufWZ穫N]vrvD;o̍'S8¢HNyW5}!tHdmGGo&ϿXX~v-!5]y;=~M ܍q:5.Ua%Ujfn+;;jo;87Z҄ 1,K垯+z+f~_ ȳD+w-aQ_bn&QѮo-Jw?KJh7C?YplXuzϷ}5g};}0 o,̺D#FU#٩݉JV12/v{Ogţ_qq 8j:l'Wq_x>Ϩ% m?`a4 5irXsU#,#XҶd[ _jL:kN\ˆOY5Dc^6[uu#l'ZbڤBń kM1u4eBlwEoT5R>A|q4hȲf3ߴTkFg!Ag1b>_CB[<l~) .ʲK Tdm̫Ԇ&vͤ7nȖ$EʎAc>:7\ʱ d[*4fgng0C 2d֒ݼoW?0˙%'`U=y5 jpNù鏱6j4c*Dc` $1MX1kرcX0̴h[huiյҢm]ӎެ'-ȶHfȡG}VvdwnRͩ7ge6x-7@{TpBw֜ƨ2ҪjE#kРAgסB*~~C u j Eo C_$#MJV}]>(xu;r';l18|1't" ܤ rJ %r ֜xTp(c J %r (*81sE 9kN*81Xs"boIENDB`xgridfit/docs/index.html0000644000175000017500000001777711572451542014674 0ustar peterpeter Xgridfit
Xgridfit logo

Xgridfit is a high-level, XML-based language for gridfitting, or "hinting," TrueType fonts. It aims to provide these advantages over the manual instructing of glyphs:

  • replace the cryptic "mnemonics" of the TrueType language with descriptive instruction names;
  • provide for the naming of points, control values, variables, functions and function parameters;
  • provide macro capability for the easy and efficient handling of similar visual features of glyphs;
  • provide high-level instructions (e.g. "diagonal-stem") to supplement the primitive instructions of TrueType;
  • provide high-level programming constructs;
  • manage the stack behind the scenes;
  • manage reference points and zone pointers behind the scenes;
  • provide methods and tools for managing instructions in large font projects;
  • edit and augment existing instructions in fonts;
  • support the FontForge auto-instructor and TrueType debugger.
  • provide a simple method for adding new instructions to fonts that already contain them.

In short, it conceals the assembly language-like character of the TrueType instruction set behind a friendly façade and provides many of the conveniences of a high-level programming language.

There is much to be said for XML as the base for a programming language. True, it is ugly and verbose, but its verbosity contributes to its legibility. Lots of people are comfortable with XML, or at least understand the basics of it. And a decent XML editor (I suggest Emacs with nxml-mode) will do most of your typing for you, giving you all the advantages of verbosity and few of the disadvantages.

The Xgridfit program compiles an XML source file into tables and instructions that relate to the gridfitting of glyphs. Its output is a Python script that can be run in FontForge to perform one or more the following tasks:

  • open a FontForge source file or TrueType font;
  • Set Blue values;
  • Run the FontForge auto-hinter and auto-instructor;
  • add the CVT (Control Value), fpgm (font program) and prep (pre-program) tables produced by the Xgridfit compiler (if desired, without disturbing any programming already present in the font);
  • add the glyph programs produced by the compiler (again, without disturbing any glyph programs already present in the font);
  • set entries relevant to TrueType instructions in the maxp table;
  • save a FontForge source file or generate a TrueType font.

Xgridfit does have its limits. First of all, it cannot think for you: you still must understand the basics of TrueType gridfitting. Some limitations are those of the TrueType engine itself, which is not capable of run-time type-checking or type conversion. Other limitations, such as the absence of for- and while-loops, are due to the limitations of the XSLT language in which it is implemented.

But Xgridfit does a few things very well, in my experience at least: it speeds up TrueType development considerably, it makes TrueType programming much more legible than before, it makes it easy to revise and reuse existing TrueType code, and it does these things while offering a level of control over the glyph outline that you can't get from the graphical tools that I've seen.

System Requirements

Xgridfit will run under Linux, Mac OS X and Windows (with Cygwin). These programs/libraries are required or suggested:

  • GNU Make to run the install script.
  • FontForge. Required to install instructions in fonts. Python extensions should be enabled. (The pre-built executable for Cygwin does not include Python capabilities, so you must either build from source or set the compiler to produce FontForge scripts-- see documentation for the -l command-line option). If you want to be able to view the results of your programming in FontForge, you must build it against FreeType libraries with the bytecode interpreter enabled. (Note that there are patent issues here.)
  • Python. Version 2.4 or higher. The Xgridfit executable and several utilities are Python programs; and the default output of the Xgridfit compiler is a Python script.
  • libxml2 and libxslt. Your system probably has libxml2 installed, but you might have to install libxslt. It is possible to use other XSLT processors with the Xgridfit compiler, but libxslt is still required for various utilities.
  • Python bindings for libxml2. In Debian and Debian-based Linux distributions, look for the package python-libxml2. In Fedora, look for libxml2-python.
  • A few standard tools, which are almost certainly present on your system: Bash, sed, grep, mktemp.
xgridfit/docs/cvt.html0000644000175000017500000002710511313431130014323 0ustar peterpeter Xgridfit

Control Values

A control value is a specialized variable consulted by TrueType instructions that position points precise distances from the grid origin or from other points. The TrueType instructions that use control values are MIRP and MIAP; the Xgridfit instructions that use them are <mirp>, <miap>, <move> and <diagonal-stem>.

All control values are global--visible to all functions and glyph programs, and also the pre-program. (But see below.) Control values are defined by <control-value> elements; these are top-level elements (children of <xgridfit>).

A <control-value> element looks like this:

    <control-value name="lc-vert-stem" value="230"/>

The name attribute names the control value, and value is a distance in "font units," the units of the grid on which the font was designed (for TrueType fonts, usually 2048 units per em, but frequently 1000, as in PostScript Type 1 fonts). Before any of your programming runs, the TrueType engine converts all control values to the units of the current raster grid. The numbers you supply must be integers; but by the time your <pre-program> runs, they are "f26dot6" fixed-point numbers. Your <pre-program> may make any necessary adjustments by rounding these numbers, applying deltas to them, or setting new values.

Put a control value to use by passing its name to a TrueType instruction--in Xgridfit, usually via the distance attribute of the <move> element:

    <move distance="lc-horz-thin-curve">
      <reference>
        <point num="top"/>
      </reference>
      <point num="top-below"/>
    </move>

This element moves the point "top-below" along the freedom vector until it is positioned the distance "lc-horz-thin-curve" (as measured along the projection vector) from the reference point "top." Notice how the name "lc-horz-thin-curve" suggests a standard measurement that is likely to occur repeatedly in a font. In fact, the thin curves at the tops or bottoms of certain characters (e.g. 0 and o) may differ slightly in width; but at low resolutions such slight differences can get magnified, causing the font to look blobby. One important function of control values is to standardize such approximately equal distances.

Simulating Local Control Values

Though all control values are global, you can simulate local variables by reserving certain control values for local use and assigning them names within the glyph program. For example, if you want to reserve two control values for local use, define these somewhere in your list of global control values:

    <control-value name="cvt-local-1" value="0"/>
    <control-value name="cvt-local-2" value="0"/>

These same two control values can be assigned different values by various glyph programs. Simply rename them with <alias> elements among the declarations at the top of the glyph program:

    <alias name="thin-diagonal" target="cvt-local-1"/>
    <alias name="thick-diagonal" target="cvt-local-2"/>

Now use <set-control-value> to assign values to these control values. By default this element uses font units (the units of the grid on which you designed your font--usually 1000 or 2048 units per em).

    <set-control-value name="thin-diagonal" value="64"/>
    <set-control-value name="thick-diagonal" value="114"/>

Now you can use the names you have assigned these control values as you would the name of any control value.

The Control Value Cut-in

The normalizing function of the control value is desirable only at low resolutions. Slight irregularities (assuming they are part of the font's design) should be allowed to emerge at higher resolutions. The mechanism for permitting this to take place is the control value cut-in. The cut-in is an F26dot6 fixed-point number, set via the <set-control-value-cut-in> and <with-control-value-cut-in> elements; the cut-in attribute of the <mirp>, <miap>, <move> and <diagonal-stem> elements determines whether the cut-in is consulted when executing those instructions. The cut-in is used by default, so you only need to specify the cut-in attribute when its value is "no."

When executing the MIRP or MIAP instruction, the TrueType engine compares the cut-in to the difference between the distance in the control value table and the distance in the original outline. If this difference is greater than the value of the cut-in, the original distance is used; otherwise the distance is that of the control value.

For an illustration, let's return to the example of the <move> element above. If executed with the default cut-in value of 17/16 (1.0625) at 500 pixels per em, the original distance is used in preference to the control value, and the result is as in the leftmost figure (where the original outline is in black and the gridfitted outline in green). If the cut-in is set at 5.0p and the same instruction is executed, the control value is used rather than the original distance, with the result that the gridfitted outline differs significantly from the original.

at 500 ppem with default cut-in at 500 ppem with cut-in of 5p

By contrast, if we were to make the same experiment at 50 pixels per em, the outlines would look the same, since the control value would be used in both cases.

Elements Relating to Control Values

The name of a control value can be used in many contexts. In an arithmetic element, the name always resolves to the actual value of the control value. In an expression, on the other hand, it always resolves to the index of the control value (its position in the table of control values; the number that must be passed to the MIRP or MIAP instruction). You must use the control-value() operator if you wish to reference the actual value in an expression.

Probably the arithmetic element used most often to operate on a control value is <round>. In the <pre-program> it is common to round frequently used control values; this instruction will do it:

     <round value="lc-vert-stem"/>

That element does the same as this, which uses an expression in the source attribute:

     <set-equal target="lc-vert-stem"
                source="round(control-value(lc-vert-stem))"/>

or this, which does essentially the same job:

    <set-control-value name="lc-vert-stem" unit="pixel"
                value="round(control-value(lc-vert-stem))"/>

<control-value>

The font's Control Value Table is built from the <control-value> elements. Each <control-value> has a name (which must be unique) and a numerical value. The index of the <control-value> is generated by Xgridfit, and no attempt should be made to predict it: Xgridfit instructions should use only the names of <control-value>s, though the index may be derived and used at run time.

<set-control-value>
<with-control-value>

You can assign a value to a control value anywhere: in the <pre-program>, a <function>, or a <glyph> program. The value you assign can be either in font units (the units of the grid on which you designed the font) or in pixel units (the grid on which the glyph is now being rasterized). To specify which, include the attribute unit="font" or unit="pixel" ("font" is the default). You must specify the name of the control value with the name attribute and the value (an integer in font units or an "F26Dot6" number in pixel units) with the value attribute.

Use <with-control-value>, which takes attributes exactly like those of <set-control-value>, to assign a control value to be used only within the <with-control-value> element. After this element, the value will be the same as it was before.

<set-control-value-cut-in>
<with-control-value-cut-int>

A distance in 64ths of a pixel. If the difference between a distance from a <control-value> element and the original distance is greater than this, the original distance is used. The effect is generally to use the <control-value> distance at low resolutions and the original distance at high resolutions. This can be used to promote evenness at small sizes, where a 1-pixel difference between the width of (say) p and b can look bad. The default value is 17/16: that is, 1.0625p or 68.

<control-value-index>

Assigns the index of a control value to a variable. Use this if you need to get such an index for any reason, since the <set-equal> instruction yields the value, not the index, of a control value.

xgridfit/docs/if.html0000644000175000017500000001737510740430064014145 0ustar peterpeter xgridfit

Conditional Execution and Looping

The <if> element

Xgridfit's mechanism for executing code conditionally is simple: the <if> element contains code that is executed if the expression in the test attribute evaluates as true (non-zero):

    <if test="pixels-per-em &lt; 20">
      <!-- execute code -->
    </if>
  

The <if> element may also contain an <else> element at the end; this is executed only if test evaluates as false (zero):

    <if test="pixels-per-em &lt; 20">
      <!-- do this if test is true -->
      <else>
        <!-- do this if test is false -->
      </else>
    </if>
  

Xgridfit's <if> element resembles the XSLT's <if> (though <else> is an addition). Remember, when writing the test attribute, that Xgridfit requires operators in expressions to be surrounded by whitespace.

You should also be aware that the TrueType engine frequently executes code conditionally even without the explicit use of <if>. The control value cut-in is consulted to determine whether to use a measurement from the original outline or one from the Control Value Table in moving points, and the (apparently) little-used single-width cut-in is similar. Every <delta-set> represents code that is executed conditionally--a point is moved only at a particular resolution.

The <compile-if> element

The <compile-if> element provides for conditional compilation: the code inside the element is compiled only if the expression in the test attribute evaluates to "true" (non-zero) at compile time. The test attribute may contain only expressions that can be evaluated at compile time: constants, number literals, control values (indexes only). Only a few operators are permitted: + - = != &gt; &lt; &gt;= &lt;= or and not.

<compile-if> is allowed anywhere that other programming is allowed (except within a <move> element), and can contain any other programming (including other <compile-if> elements). Here's a simple example:

    <macro name="anchor-to-baseline">
      <param name="pt"/>
      <param name="pt2" value="-1"/>
      <param name="pt3" value="-1"/>
      <move distance="baseline" round="no" cut-in="no">
        <point num="pt"/>
      </move>
      <compile-if test="pt2 &gt;= 0">
        <align>
          <point num="pt2"/>
        </align>
      </compile-if>
      <compile-if test="pt3 &gt;= 0">
        <align>
          <point num="pt3"/>
        </align>
      </compile-if>
    </macro>
  

This macro anchors one, two or three points to the baseline so that they won't be moved later. The param "pt" is required: it is a point that is always moved by the first "move" element. Params "pt2" and "pt3" are optional; they have impossible default values. But if reasonable point numbers are passed to the macro for "pt2" and "pt3" then the two "align" elements are compiled. Here are a couple of calls to the macro:

      <call-macro name="anchor-to-baseline">
        <with-param name="pt" value="bottom-left"/>
      </call-macro>

      <call-macro name="anchor-to-baseline">
        <with-param name="pt" value="bottom-left"/>
        <with-param name="pt2" value="bottom-mid"/>
        <with-param name="pt3" value="bottom-right"/>
      </call-macro>
  

Another way to compile code conditionally is to include the compile-if attribute on a <move>, <align>, <interpolate>, <shift> or <delta> element. These are the elements that can be nested inside a <move>, where the <compile-if> element is not allowed. Using this attribute, we can rewrite the "anchor-to-baseline" macro as follows:

    <macro id="anchor-to-baseline">
      <param name="pt"/>
      <param name="pt2" value="-1"/>
      <param name="pt3" value="-1"/>
      <move distance="baseline" round="no" cut-in="no">
        <point num="pt"/>
	<align compile-if="pt2 &gt;= 0 and pt3 &lt; 0">
	  <point num="pt2"/>
	</align>
	<align compile-if="pt2 &gt;= 0 and pt3 &gt;= 0">
	  <point num="pt2"/>
	  <point num="pt3"/>
	</align>
      </move>
    </macro>
  

The advantage of this method is that it enables the Good Programming Practice of building blocks of code around the visible features of a glyph while still permitting conditional compilation. It also produces slightly more compact and efficient code than the earlier example. The disadvantage is that it is somewhat more awkward to write three different <align> elements. However, it may well be worth doing so in a macro.

You may include, as the last child of a <compile-if> element, an <else> element containing code to compile if test evaluates as false. This works the same way as the <else> clause in an <if> element.

Looping

Xgridfit does not have an explicit looping mechanism such as the for-loop of C and other languages. Certain TrueType instructions can loop through a collection of points; Xgridfit exploits this capability and extends it by allowing more than one <point> or <range> element to be included in an <align>, <shift>, <interpolate>, or <toggle-points> element (the <range> element is itself a looping mechanism). Xgridfit exploits other looping mechanisms of TrueType when it allows more than one <delta-set> in a <delta> or <control-value-delta> element and more than one <param-set> in a <call-function> element.

xgridfit/docs/x-vec-a.gif0000644000175000017500000000555510643720040014603 0ustar peterpeterGIF89aE ###&&&'''((()))***---222:::AAAMMMpUUUXXXbbbcccppqqquuu! ,2"2Ü˽̧ѥȜڥ۵ޟכ-×.0}X 8 FTaCseH1Evm㹏Bn)eKPS9ΞW7C)3i<綟тJNސ>k k趧PIԪ6Ym]F5TY06p^];0nA=-__LUo+ŕQc:][~/Fh3ΞO)3PɈ#42V{6޾}?u%Vܕ('ڜNj'9&#j"[ $x_\ݲxcYhzYeo/&w+{I 0 &a/ jR< 8C '/F4͌4M-3Lu`-'7g)L'M [v=\(q;70k7)@{ls n]Jߠ< .^,][n w^xᣫ o懿sXm~{q#~W.N_<ѓ^y_cL0<Ͻ*#dJm}d86;ȤHBI}t(I1D?+c0= @+6Yno"/a OHڐrP!B`P] S 16t ̈Cb &>ȉb>!ETU~MOUtӰ7 \ hCƀc랡dώ1 !+#i^Qm4HwS,6רXgI oJQIzV=^N/g./i>J8ecH ZF.+%($EH@nqf&g̓^C#B,37 hg v6n_4R{R:]uXJFeDNWeT&Wm߀Fjwz@l-8"C$hl=;*~p{M52 >V;"Fc>x*.ڦ3++RVDdkkKmllXіfSٳVH?};9q 1&-F0}KAئzƿFMOQhs^lKBQRY Nk($s,2k/cM^)'rw~7sI!qr,V&NN 4ؘNC.'D% b;)'&A 6RQڋc-b#!5HڦfB:'l={ 5HS; 6 N5j"~?fCs)t$#Y9?f*LW3CS} TT*R߆ؐXyIoF `DeYkЂ Hj`әHj6-BzCjcbKм7i-'GEFdH &6M6툊T>|-:ŦFn[ڄ槼_Y*Jק=Ǩg+IZ`ˉf[DFR -[|1SWܯ*DcjM lwEӞ*fm`iRk6ŚhnS[64UhW<49K^[~hZ\bv?M-kS[>}AV"KEi\P铈Ʌ M?澟QK==9pPަ=; U\y0wykZ3t?.gtQO7YQTjlHi[b[ݫ>9CRBD&wAEjm R  dz-kӒI-B笋Q|3iA"g I A 0 H PyI\,ww&K:,}cb;*Vqd8tv{:l=!s5a_x.))-(WUGhC/-9$5ğ%0?zV:'xΎJݵI]x GK.GAHb ԬLlH FO0 ra3 5Ih$[sA@d8KCl bKNxC g# QןtD///+sdyYّHqMU.]ZOdάcC%h֖ذ-ͦ_~w⿩^dIdҿ7&5ܹWV3`8~=ϼ b¦(4J)Ć5mґ9CD|D,|o~H]V3LXN验8""qNW52kR"4RQ -& ,/Iۧ[ԯpuX,Z&H  5H  5HjUS]H R>TIENDB`xgridfit/docs/A3.gif0000644000175000017500000000524510643720037013610 0ustar peterpeterGIF89aF ###&&&'''((()))***---222:::AAAMMMpUUUXXXbbbcccppqqquuu! ,44¡ȢΜϿ޿n/`Lk, E[^ 5$)o;ʄidɟ?gy(\nvsi[GR3%:ic'>d6Bm,!a mʮn!p滳#ZDr7=ݹZg7yK_fr_=g{|4!z xIY8)5(P1y'!n|2I We";L <4& -Nvc'p> %,&"-p28u_9$Ԥ\ `HB>I |ki0Id,c,BaWvhIvfT#ꤊt>`DG^:ʉ#妜j79΢i" j&k%(KDZ* h-xPAZ?9nrA6Xjw"E 5神j*^Y[05իJ.p+ϒ Wb^$*1?v,o$rI3O2*Do3ȕ&4 <79Я<}0W}0 FW5꽫F:Q㴶4Fcw7(+=wKu㛊vv5۞VS;qQRφruZ;旫J[!us S^6Xmy7-:ϊ(3v4ϫ}ǰ|)¸oJxCx۰,>^.ߓtDy^a6}sr-}3ESR~LFqc0@@c qNB~ ?ZJc3ˇLp p@1h~|@>NQbF>u(Q01`@0u$@.PЈ*wD%V,TT RHU$J!(!]56ɐ>`l{cd)>|@m-^90 {+I0x)_w gYWȦ6nz 8ǹMfsy]u4+98(4yUВ=9a -E1ʍ9.zDʓ/K,"EGseQ~uS*8҆hiiL4Z?,ѱ/1dҏr(MKsSc4!(*D)( U˩A$<V;~3dX-)ɜ4Z'=խHg A⵩p_O_;]b__nb%;#25ldyB: XȾ dSǕVmml+Zږ.a/X; _Wheqy\ #ŕr\=$X}ta:ջzuV~x_]Wn[ֶ}ٛ^5|aJ~d:-y@Xʗ x!wtpE-P%D:[s|#qhiݪ(m csEsHN&;L":TXβeH#Ǫ5<ǐ 7 e^ӬfӲ9 %(5bXpu්8>)=`C"렫xʜ~-CӖ+Eԥ4'GeQ5gv!a"kҮ5z-a66p]M7T:=tv`Ysپv2z>ja,|gպkZ֖ m7]:p n;w 7үfpknZ=q};ju)NlK19m'9Wo9Il󼡵Fmq_{[:;>ai#7^zm<mr}әuӜ>yÞlw캔zʡm&n9ξ @;xgridfit/docs/bbar-points.png0000644000175000017500000002771611130460714015606 0ustar peterpeterPNG  IHDRsRGBbKGDgK pHYs  tIME@S IDATxwXW  H/" UE(MJXbLb=R(UF ]]dY`?6;;s9w~{;RF $)=UTBXi!*!*!  BH$)QAAUBT.U AT%AT%waխXD$%7gꌼvloN<(Ɖ@½]6&HcXS&|(+c3&@lT4(OtΘ ؃zp5- 2 xvtCCCJRR$1HJN\\jkUf1YZRUh^~^2T\uƌOo`/)ii#_88NP(?K)/;Ę+ItDZx!; !zCy[،w'SN؏$x#^蟰BI3:8U !VKzfnX\&ysUk|oa2L&ky_Jl( S(gCWR\byI3:8D i PzF>{fW\&6 p '1TQ^ F&ϓG~ ʊ:ϟ9m_3ft|"xc$ %&!$.ɣ.\cWb"wX@_3hÍ~$P}=?ё>O:ɾ#ܧOv:oF'`R1rPR2Kv& C f+.+/,(,,()m5@# IB *R B ('+'7P^^YEYSKKYEYHbc%>EiIg)/Rs/).Q&%--..N͜#($̴>4ʪ+*+WT+}_^YEYCKKSKSCSCh0JJIO#$=Mzafjb:z2!,οԙz ssr3_|hpc#C&|0,<"ALTPvFY*(w`{[wlvqS^|/?K;j16cUT@PJE޺assed^>}$>.Иq6&.UĪp{뎦3\]ttuH, b"D>2iC}AU"a/}ۇ.#3kgiji @hjj$48$4~uUWSf͛3r('Ux<}T=9kg j[uښYΚ;{pCT%}3._;nիl쿜!=5熷 Լ__pU AU*߿0"91];cc3K sK sK]QW&+ujĄ'9:;:q#AUBP\U|0iP}d]aL&!\]h4T%U Ro/wǷed1l'UVZv?4? &*fysOt$WAP̹W,Y4o|um_7dzтWkc[GPܼsv銡pK'O7g=skۮZzlo~ ,Xt`ҝɼ~ɣtwO4=DJ VX[YYRù{? 8pv3plw;TѦR3^ˏd$P(fNOzcU˦LrHKG_#J$(\did&$$? ( ]uJkɮ&lۼݙUtpYР+(* Ꙋ\㙜r᭛>}@q=a=uz;{$i|ZZϜ`!F0V"iSͬ2'\EIXp=2BMu8+wacXpP0_3Z ٻw^.عuރf= o O/5Ä}acT;;_`J(JV6gnxwBnU7` @Ƶ CH}} =MkRTX4qF&ᆔשB{wt Exxyy$N\yDLA4MM7/m<ܸ =D hobA?|}w777l0~{}3s  G*[0o&_|5>#&gh4q 3ddCQKK|] i ]F7OVNޱsR3jS̟9:=w /feDDD.]ǏzEpk'M ߺSܖ{6f\ݻw|K' {gp^?sNg @w׼v}NBƦg}5ESclDyrmRrW.M `w9׷7$u9<~yrJ3"bErӷkZTU6~GuuЃ+ښsCפHBXwrYl`clՊeV1V"^7]LFI&8zqǏH@4{ڮ苠*|$Ll..\4w,"@K[̥sK-().Fb(lAjo1V׮ !a؃0RL4>p!JRO:?L\TXDNٹeUT~DIY =ݫӷ4;7O qs!b/8akBߡ*){6[tނ'v-Ei헬7YoQ^UӽphGUyNFܸzSӊt~+*ЉJ}JyyzNM 4))[6l%Դ&#^`щJ}JmM4]={alڰzYgIяJ}G]m4R/?5-mqjڭLRLM;`gvF]UTNJJ =݋4z]ݱKYtӜMk Roc;iv'F~u{FpsLv7m'_cidz9zUTTMN}. >M }LLG`xCP}؃]Y,QQQt#Mywy5sl u}Ի.YJ"<ӂB ,8{ ~ضAtY%I9W8*mKHhߑ;@ ,'L?w !y%$ `5٢76ںs;)-+-26CUI  S;:%@yyR|Ĥ7Pz h1J Gac6]?@\|ϟZe2t-F&;T^~ HxJ.=x;._K6-Y?J,Y$}JKuU}'ڃIa͋.܏Ca&2+V<ǟd1xƜY+*F0VXI%!H] 8GQ; /8 Y vV[[ c%Ғ3^eוk~wAa&fΙuqqVi9oIaGS_>u c%D0QPeuY ^#$~Iq1U X֬_w1XKі,c8T%D`%2=WܼvJ۵%JʣG߻틎CUBif$|CUB/HkCǡ*!ˬ=% ơ*! MJaC=<~g)+*wJ2sdJNvBu7Q;8:M|Lcּ97"Ȉ}5D1օ;T%D`1{[dBL9:U Xlҫ*+b_T%DvtDF; },.F&Lr CUBΓ#Y,Y vru Fǡ*! F3 ;q&N%*!Hqvs Okt&cqJb?!Tg;:M  Cǡ*!P}=&QTXDƐgqT%"Z#*t8b9BBnjCǡ*!x$2x8Lx*! %%itV%T%D9zT“xXkdb_S]CUBc?"MFXX<1):U XF|@",̟%%PEAiI)f5afY :U X(%Df)qJ C\CSɬUOPAx/PFQU`U pk_Y[SC PB OCUB#W/^Z!okJ 3Do(ކh228T%D`!]Hw7oqJJzYdRzCd**!Jmm4ިJKCd"yy5T%D;qdJx+z^CUBu |XJYP{^_@kkqJ!P(JJqJB"ġ*!+L-*!4B! 8T%DQTT(+#}.#+{*! t4H4L5.W6rVOXIEUB>VTVZJX^=8T%D(?}JJBN!)in.IU !(4 zeW֏41erzZI &ޮjQ ;n=N $+e_>dT:dܙk`0֭\6PIZD3LU*W}QWg-]DARF]^y;8 :D{p7][德Jh9.c"xx߁c>}BIDAT3ӂ~b5Ԟ:d0i'4äWκ@eӮO%!!U YHr\.uSK[ޝF棤cSm/Q;YWFjЕE)--na. SV5iX.\7s Ǽ-w mBd!Z˥sWt*jjnv }~Nl1 lm!0}*6@zՆ8aΟY+\,)f?KJްz]W بN AU"DApI}YY9DM rD8}qEmܲiRvVhQICO gܤZۃD>tIn{1?۹c"`0i4Ij^ץj]-JAQ1,&EBBBJZzEY!Se(]v -ͬ7q'>?p8әgIɉR 776ڙ1qֵiOs,mQw{W/^^ iEYEmXK4{0V"=XNrbeɺxϩ?VU7qӦm%v Ū~c}:>S%)pLX:i|۟ee#M,JKJu~`H c2朻};l6:v_UwrsyeXdMF3R_157x>k}fJs z2u4U**..n`8l脸ϯÇqdqɔ|'H颢unc%A+=نDD m2ޒ=z+!A{cJ $Ggp'/ /UcRͦ^ <5til+!DA|IIIuX H^ JKJ!OfaA!.-%bԯ7VF.HkFZa2z׼&((ȊьtwlV[S&t8Єĸy)V?ַ2u+W T6y=sTE]~7uu˨[pwpu:i1)*,RUS%ii Q0VM8E>^75#T-_/ l6%܏W.\(/owϥ {\)^&iX㍃'G|M-m-{w˫GNOM n/~Zb%:: qU,FtB\FZzJ/gVZ_3V'OYR9HBV+I% -E ohmk9f561i;Dś4h Wyq?٩G|8ð)\$%x i R,cTubb;ŕc-, n'Q,,%J&sȅ?hWZ 2*BRTVٜVRά_pR,F\\m}}LBj>nVZ8Bva}ӎb"PG)lYA~ !AR[B>&Imo}f{ʶYGP edė$HNL⏩T ,]v`g$ @'4!ۢ qy[lAgO DU"0ɏY{iS\+,(ljjbXYo.=`=cGq'|!pvsk%%gIVj!=hO߃nDG((+wrKHy~؉e<:_۾yRݸeY6y:ݥ=hOߓa9ҊvV_]]3Xg0J]FIY73?z(ATTUT+>vȾ#ܧO a1N.R ,w ti?zpx5q(Q +um9o`x_YEmnj;x^ &>VH-{p&aDX#t "ݧ?~bjkjغ;p>Kh%$2$X;&*z\ +FGWm[c/9`-UF ? t`t?"LTTKhϟ03%CcckF`31f+Q#Ia$I._fsLNL9w팎uG \9/1f)ć,#0DPUjeE<Ѵh!G^K}6=v,,&R]HOQ^VC-,(d2 U 5In?ܼ;c )^+QZ SJ"""9A]HIx`aEU pj20$=2x}S==&g6T"*@MR{cEBRr}S lg)Nfko+&&.=z&4hiiJ7c}]Hy,e!38 eRW[eaeqƵ^ 179<$%tdi:J]߻T5Cj]HERlTpc#UH3viWw4QOݳu!h*|=P^vX6f%e+}_=%%k\~!7|ԗcu7DՅQ#x+M qv㤤_J}9=6]zYii}97I"D9ț׼̟'m8uD{riٙ?s۾vÇJȂTDyYhSˌ8Ζ4RCCCWǕuPE(AMōtLtD% n:c:JbG9zCG=oyY~JdYFPY+"IENDB`xgridfit/docs/reference.html0000644000175000017500000045677411355415205015522 0ustar peterpeter Xgridfit
SourceForge.net Logo Home Page Project Page Download CVS repository
<absolute> <add> <alias> <align> <align-midway> <call-function> <call-glyph> <call-macro> <call-param> <ceiling> <command> <compile-if> <constant> <contour> <control-value> <control-value-delta> <control-value-index> <default> <delta> <delta-set> <diagonal-stem> <disable-instructions> <divide> <else> <enable-instructions> <entry> <flip-off> <flip-on> <floor> <formula> <function> <get-coordinate> <getinfo> <glyph> <glyph-select> <if> <infile> <interpolate> <interpolate-untouched-points> <legacy-functions> <line> <macro> <maximum> <mdap> <mdrp> <measure-distance> <message> <miap> <minimum> <mirp> <modifier> <move> <move-point-to-intersection> <multiply> <negate> <no-compile> <no-round> <no-warning> <outfile> <outfile-base> <outfile-script-name> <param> <param-set> <point> <pre-program> <ps-private> <push> <range> <restore-default> <reference> <round> <round-state> <set> <set-auto-flip> <set-control-value> <set-control-value-cut-in> <set-coordinate> <set-delta-base> <set-delta-shift> <set-dropout-control> <set-dropout-type> <set-dual-projection-vector> <set-equal> <set-freedom-vector> <set-minimum-distance> <set-projection-vector> <set-round-state> <set-single-width> <set-single-width-cut-in> <set-vectors> <shift> <shift-absolute> <srp> <store-freedom-vector> <store-projection-vector> <subtract> <szp> <toggle-points> <to-stack> <untouch> <variable> <variant> <with-control-value> <with-control-value-cut-in> <with-delta-base> <with-delta-shift> <with-freedom-vector> <with-minimum-distance> <with-param> <with-projection-vector> <with-round-state> <with-single-width> <with-single-width-cut-in> <with-vectors> <xgridfit> <zone>

Element Reference

<absolute>

Converts negative to positive numbers; positive numbers stay positive.

        <absolute value="line-width" result-to="lw"/>

Content

None.

Attributes

value
Required, except when <absolute> is the child of a <formula>. Any value or expression. The value to operate on.
result-to
Optional; not allowed when <absolute> is the child of a <formula>. The name of a variable or control value in which to store the result. If result-to is omitted where allowed and value is a variable or control value, the result is written to value. If value cannot be written to, the compiler issues a warning and the result is left on the stack.

<add>

Adds two numbers together.

        <add value1="line-width" value2="1p"/>

Content

None.

Attributes

value1, value2
Required, except when <add> is the child of a <formula>. Any value or expression. These are the values to add together.
result-to
Optional; not allowed when <add> is the child of a <formula>. If result-to is omitted where allowed, Xgridfit attempts to write the result to value1. If value1 cannot be written to, the compiler issues a warning and the result is left on the stack.

<alias>

Provides access to a value under some other name. The value can be a control-value, constant, variable, or any value that can be resolved to a number either at compile time or run time. The <alias> element can appear at the top level of a program (as a child of <xgridfit>), or along with other declarations at the beginning of <glyph>, <function>, <macro> or <pre-program> elements. An alias takes precedence over all other elements, so in the case of name collisions the alias is always used. Here is a simple example:

	<control-value name="lc-vert-stroke" value="0"/>
	<alias name="lc-vert-stem" target="lc-vert-stroke"/>

Now a <move> element with attribute distance="lc-vert-stem" will use the control-value named lc-vert-stroke. If another control-value is named lc-vert-stem it will be invisible. If you want the alias to be used in just one glyph program, declare it as a child of <glyph> rather than as a child of <xgridfit>.

Content

None.

Attributes

name
Required. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. This is the name under which the program may now access the value.
target
Required. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. The name of the value which is being renamed.

<align>

Moves one or more points along the freedom vector until aligned with a reference point. Points are "aligned" when their distance from each other, measured along the projection vector, is zero. When the projection vector is "x," aligned points end up stacked vertically; when it is "y" they end up in a horizontal line. When the projection vector is set to a line, the aligned points end up arrayed along an imaginary line orthogonal to the projection vector.

The <align> element must contain at least one object to align. It may contain any number of <point>s, <range>s and <set>s. An optional <reference> element contains the point to align with. If the reference point is omitted, the current setting of RP0 is used.

<align> can and frequently should be nested inside a <move> element, in which case points are aligned relative to the point that is the target of the <move>. In both of the following cases point "m" is aligned with point "r":

        <align>
          <reference>
            <point num="r"/>
          </reference>
          <point num="m"/>
        </align>

        <move>
          <point num="r"/>
          <align>
            <point num="m"/>
          </align>
        </move>

Content

One or more <point>, <range> and <set> elements.

Attribute

compile-if
Optional. Any value or expression that can be resolved to a number at compile time. If true (non-zero), the <align> element is compiled; otherwise the compiler passes it over.

<align-midway>

Must contain two <point> elements. Moves these along the freedom vector until they are aligned midway between their original positions. Measurement is along the projection vector.

        <align-midway>
          <point num="a"/>
          <point num="b"/>
        </align-midway>

Content

Two <point> elements, both required.

Attributes

None.

<call-function>

Calls a function (defined via the <function> element) by name. Parameters may be passed to the function by including several <with-param> elements; or, if the function is to be called repeatedly, several <param-set> elements, each containing the <with-param> elements for one call to the function.

If the function returns a value, it can be assigned to a variable via the result-to attribute. Note, however, that if a <call-function> element contains more than one <param-set>, only the value returned by the last iteration of the function is returned.

    <call-function name="cap-serif-width">
      <param-set>
        <with-param name="ref-pt" value="left-left"/>
        <with-param name="move-pt" value="top-serif-end"/>
      </param-set>
      <param-set>
        <with-param name="ref-pt" value="left-left"/>
        <with-param name="move-pt" value="bottom-serif-end"/>
      </param-set>
    </call-function>

Contents

Either several <with-param> elements (if the function is to be called just once) or several <param-set> elements.

Attribute

name
Required. The name of the function to call.
result-to
Optional. The name of a variable or control value in which to store the value returned by the function.

<call-glyph>

The <call-glyph> element causes code for the whole of a glyph program to be compiled and inserted, in the manner of a macro. Like <call-macro>, <call-glyph> can contain <with-param> elements, passing values to the glyph program. For a detailed account of its use, see the chapter on functions, macros and glyph programs.

Content

If the glyph being called has one or more <param> elements, one or more <with-param> elements. <param-set> elements are not permitted here.

Attribute

ps-name
Required. Must match the ps-name attribute of the <glyph> element being called.

<call-macro>

Causes a macro to be compiled and its code inserted at the present location.

    <call-macro name="lc-vert-stem-with-serif">
      <with-param name="anchor" value="left-left"/>
      <with-param name="distance-from-anchor" value="hn-width"/>
      <with-param name="stem-a" value="right-right"/>
      <with-param name="serif-a" value="right-serif-right"/>
      <with-param name="stem-b" value="right-left"/>
      <with-param name="serif-b" value="right-serif-left"/>
    </call-macro>

Content

Either one or more <with-param> elements, one for each parameter defined in the <macro> element, or several <param-set> elements if the macro is to be compiled and inserted at this place more than once. <with-param> may be omitted for each <param> element with a value attribute.

Attribute

name
Required. The name of the macro to call.

<call-param>

This element may be used within a <glyph> or <macro> element containing <param> elements. It will cause to be executed a snippet of code passed into a called <glyph> or <macro> via a <with-param> element. For details, see the "Callable Parameters" section of Functions, Macros and Glyph Programs.

Content

None.

Attribute

name
Required. The name of the <param> to call.

<ceiling>

Yields the smallest integer greater than or equal to value.

Content

None.

Attributes

value
Required, except when <ceiling> is the child of a <formula>. Any value or expression. The value to operate on.
result-to
Optional; not allowed when <ceiling> is the child of a <formula>. If result-to is omitted where allowed, Xgridfit attempts to write the result to value. If value cannot be written to, the compiler issues a warning and the result is left on the stack.

<command>

Causes any TrueType instruction (except the PUSHB and PUSHW instructions) to be inserted at this place in the output. name is the name of the command; modifier, is simply copied into brackets after the instruction that is generated. This element

        <command name="MIRP" modifier="10110"/>

is compiled to "MIRP[10110]". The modifier attribute lacks portability, since it is copied in literally. A better solution is to use <modifier> elements within the <command> element, thus:

        <command name="MIRP">
          <modifier type="rp0" value="yes"/>
          <modifier type="minimum-distance" value="no"/>
          <modifier type="round" value="no"/>
          <modifier type="color" value="black"/>
        </command>

Though verbose, this style allows Xgridfit to check the input code and has the potential to allow Xgridfit to vary the syntax of its output. (Since Xgridfit now produces scripts only for FontForge, the latter capability is not exploited.)

Content

One or more <modifier> elements, if required by the instruction and if the modifier attribute is not used.

Attributes

name
Required. The name of the TrueType instruction to be output. The compiler checks this against a list of instructions.
modifier
A modifier string to be inserted literatim in the TrueType instruction. For example, if command is "MIRP" and modifier is "rnd", then MIRP[rnd] is output.

<compile-if>

Code within <compile-if> is compiled only if the test attribute evaluates to true (non-zero). The compiler must be able to evaluate test at compile time: thus it may contain only constants, number literals, control value indexes and a few operators (+ - = != &gt; &lt; &gt;= &lt;= or and not).

Here is a simple example of <compile-if>:

        <compile-if test="bold-italic">
          <delta>
            <delta-set size="3" distance="-2">
              <point num="pt"/>
            </delta-set>
          </delta>
        </compile-if>

The delta is compiled and inserted in the output code only if bold-italic (a global constant) is non-zero.

The <compile-if> element may also contain an <else> element, which must come last. If test evaluates to false (zero), the code contained in <else> is compiled.

Content

Programming to be conditionally compiled.

Attribute

test
Required. Any value or expression that can be resolved to a number at compile time. If it evaluates as true (non-zero), the content of this element is compiled.

<constant>

A constant is a named number. The value can be an integer, either of the two kinds of fixed-point number (e.g. "2.3" for a distance on the grid or "1.0v" for a component of a vector), or the name of another constant, in which case it creates an alias for that constant. It can also be a simple expression (usually addition or subtraction) based on another constant:

        <constant name="bottom-left" value="3"/>
        <constant name="bottom" value="bottom-left"/>
        <constant name="bottom-right" value="bottom + 4"/>

Constants can be referenced just about anywhere that numbers are called for. To refer to a constant belonging to another glyph program, use the glyph's ps-name followed by a slash and the name of the constant, e.g.

        <point num="macron/bottom"/>

This is useful when instructing composite glyphs.

Constants can be declared at the beginning of a <glyph> program, or as a child of the <xgridfit> element.

Content

None.

Attributes

name
Required. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. Other elements can refer to the constant by this name.
value
Required. A number or simple expression. It should be possible to resolve this attribute to a number at compile time.

<contour>

Specifies a contour to be shifted by a <shift> instruction.

Content

None.

Attributes

num
Required. A number or simple expression, the number of the contour. It should be possible to resolve this attribute to a number at compile time.
zone
Optional. Possible values are "glyph" and "twilight." Include the attribute zone="twilight" if this contour is in the twilight zone; otherwise the compiler will assume that it is in the glyph zone.

<control-value>

The font's Control Value Table is built from the <control-value> elements. Each <control-value> has an name (which must be unique) and a numerical value. The index of the <control-value> is generated by Xgridfit, and no attempt should be made to predict it: Xgridfit instructions should use only the names of <control-value>s, though the index may be derived and used at run time.

    <control-value name="curved-char-bottom" value="-25"/>
    <control-value name="lc-x-height" value="850"/>
    <control-value name="lc-descender-depth" value="-555"/>
    <control-value name="lc-ascender-height" value="1485"/>

Content

None.

Attributes

name
Required. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted.
value
Required. A number in font units (the units of the grid on which the font was designed, normally 100 units per em or 2048 units per em).
index
Optional, and consulted only in merge-mode. Specifies how to determine a control-value's index. "Auto" (the default) means that if a control-value with this one's value is found in the font, it should be re-used; otherwise this control value should be appended to the end of the control-value table. "Append" means that the control-value should always be appended to the end of the control-value table. A number specifies the index at which the control-value should be placed. If the value of this control-value is different from the value of that of the control-value at that index in the existing font, the control-value is updated.

<control-value-delta>

The <control-value-delta> element works like the <delta> element, but operates on the Control Value Table rather than on a point. It should normally be invoked in the <pre-program>. Each <delta-set> inside a control-value-delta element must have cv, size and distance attributes, but it may not contain a point.

The setting of the vectors has no effect on the <control-value-delta>. Rather, the <delta-set> specifies an amount to add to or subtract from the value stored there.

    <control-value-delta>
      <delta-set cv="pq-char-width" size="6" distance="-8"/>
      <delta-set cv="pq-char-width" size="9" distance="-8"/>
    </control-value-delta>

Content

One or more <delta-set> elements.

Attributes

None.

<control-value-index>

Assigns the index of a control value to a variable. Use this if you need to get such an index for any reason, since the <set-equal> instruction yields the value, not the index, of a control value.

Content

None.

Attributes

value
Required. The name of the control value whose index you want to retrieve. No other kind of value is recognized here.
result-to
Required. The name of a <variable> in which to store the index of the control value.. Only a variable is permitted here--not, for example, the name of another control value.

<default>

This element, which may appear as a child of <xgridfit>, declares a default value. If the type is "minimum-distance," "control-value-cut-in," "single-width," "single-width-cut-in," "delta-base," "delta-shift" or "round-state," Xgridfit also inserts code in the prep program to set a font-wide default in the TrueType engine. Another way of setting these defaults is simply to include elements that set these values in the <pre-program>, and the effect is the same. If you want the TrueType engine to reject all attempts to set defaults (that is, if you want to use only the defaults that are standard for TrueType), include this:

        <default type="use-truetype-defaults" value="yes"/>

In addition to TrueType defaults, stored in the font file, this element controls several defaults that govern how Xgridfit operates.

Content

None.

Attributes

type
Required. Must be one of the following: "minimum-distance", "control-value-cut-in", "single-width", "single-width-cut-in", "delta-base", "delta-shift", "delta-break", "max-twilight-points", "max-storage", "legacy-storage", "max-stack", "use-truetype-defaults", "round-state", "function-base", "init-graphics", "color", "delete-all", "combine-prep", "auto-instr", "auto-hint", "cv-num-in-compile". For details about the meanings of these types, see The Graphics State and Xgridfit Defaults and Merge-mode.
value
Required. For permissible values, see The Graphics State and Xgridfit Defaults.

<delta>

A delta instruction moves points at particular sizes. The <delta> element may contain any number of <delta-set> elements, each one specifying a point to move, a size at which to move it, and a distance to move it.

The direction of the move is determined by the current setting of the freedom vector. The available specifications are fuzzy as to the details. You will experience no surprises when the vectors are set to x or y; you may experiment with the vectors set at other angles.

When the first element of a <delta> is a <point>, that point is the default, which every <delta-set> element will move unless it contains its own <point>. These two <delta> elements are equivalent:

      <delta>
        <delta-set size="3" distance="8">
          <point num="p1"/>
        </delta-set>
        <delta-set size="4" distance="8">
          <point num="p1"/>
        </delta-set>
      </delta>

      <delta>
        <point num="p1"/>
        <delta-set size="3" distance="8"/>
        <delta-set size="4" distance="8"/>
      </delta>

Note that a <move> element may contain <delta> elements. When a <delta-set> element inside one of these <delta> elements lacks a <point>, it operates on the point moved by the parent <move>.

Content

An optional <point> element, followed by one or more <delta-set> elements.

Attributes

compile-if
Optional. Any value or expression that can be resolved to a number at compile time. If true (non-zero), the <delta> element is compiled; otherwise the compiler passes it over.

<delta-set>

The <delta-set> element encapsulates the essential information about a single delta move or adjustment: the resolution at which to apply the delta, the magnitude of the adjustment, and the point or control value that will be affected.

The resolution is determined by the size attribute, which can be a number from 0 to 47. It is added to the value set by the <set-delta-base> or <with-delta-base> instruction to obtain the resolution (in pixels per em or "ppem") at which the move should take place. The default delta base is 9; if you don't change it, a size of "0" means 9 ppem, "9" means 18 ppem, and so forth up to "47," which means 56 ppem.

The distance attribute is the distance to shift the point along the freedom vector, or the amount to add to or subtract from the control value. Legal values are from -8 to 8 (excluding 0). When moving points, negative numbers shift against the direction of the freedom vector (generally down or left) and positive numbers shift in the direction of the freedom vector.

The default unit by which pixels are moved and control values adjusted is 1/8 pixel. The unit is controlled by means of the <set-delta-shift> or the <with-delta-shift> instruction.

A <delta-set> that is the child of a <delta> will normally contain a single <point>. However, the <point> may be omitted in either of two circumstances: First, when the <delta> is the child of a <move> element, the <point>, when not specified, is implicitly the <point> that is the child of the parent <move>. Second, when the first child element of the <delta> is <point>, that point will be moved by any <delta-set> that lacks a child <point>. A <delta-set> that is the child of a <control-value-delta> element may not contain a <point>, but it must have a cv attribute.

All attribute values in a <delta-set> and a child <point> must be capable of being resolved to numerical values at compile time. Variables and function parameters are not permitted.

Content

When the <delta-set> is the child of a <delta> element, it may contain a <point>; this is the point to move. It must contain a <point> when it the parent <delta> is not the child of a <move> and the first child of the <delta> is not a <point>. When the <delta-set> is the child of <control-value-delta> it has no content.

Attributes

cv
Required when the <delta-set> is the child of <control-value-delta>. The name of the control value to adjust.
size
Required. An integer from 0 to 47. The resolution at which to move the point or adjust the control value, as explained above.
distance
Required. An integer from -8 to 8, excluding 0. The distance to move the point or the amount to adjust the control value, as explained above.

<diagonal-stem>

Given two lines (making up a diagonal stem), makes the second line parallel to the first, subject to the operation of the Control Value cut-in. If one <align> element is present, the points it contains are aligned with the second line; if there are two, the first set of points is aligned with the first line and the second set with the second line. You may, and often should, set a new minimum distance value with the min-distance attribute. At the end of this instruction the minimum distance is reset to its former value.

Usually it doesn't make a lot of sense to round the distance when calling this instruction; and yet the default value of round is yes for compatibility with other, similar instructions. You'll probably want to set the round attribute to no; but if you have several <diagonal-stem> instructions together, enclose them in a <with-round-state round="no"> element to turn off rounding beforehand and on again afterwards. In this case, do not include the round attribute with the <diagonal-stem> elements.

By default this instruction does not set the Freedom Vector, since the best setting of that vector varies with circumstances. If you want the Freedom Vector to be the same as the Projection Vector, set freedom-vector="yes".

This instruction is not suitable for use inside a function (though you may do so if the <line> elements contain points rather than ref attributes). Also, I'm not sure whether it will work if the various points are in different zones. It may, but I don't guarantee it.

    <with-minimum-distance value="diag-min-dist">
      <with-round-state round="no">
        <diagonal-stem distance="cap-thick-diag" save-vectors="yes">
          <line ref="left-diag-left-line"/>
          <line ref="left-diag-right-line"/>
        </diagonal-stem>
        <diagonal-stem distance="cap-thin-diag" save-vectors="yes">
          <line ref="right-diag-right-line"/>
          <line ref="right-diag-left-line"/>
        </diagonal-stem>
      </with-round-state>
    </with-minimum-distance>

Content

Two <line> elements, the second to be made parallel to the first. Optionally, one or two <align> elements, the first containing points to be aligned with the first line and the second with the second line.

Attributes

distance
Required. The name of a control value which determines the distance to place the second line from the first.
round
Optional. The value may be "yes" or "no", the name of a standard or custom round state, or any number or expression to use as an input for SROUND. If the value is anything but "no", rounding is used.
cut-in
Optional. The value may be "yes" or "no"; the default is "yes". Determines whether to use the control value cut-in.
min-distance
Optional. The value may be "yes" or "no" or any value or expression to be used to set the minimum distance for this operation.
color
Optional. Permitted values are "black", "white" and "gray". The default is "black." The kind of distance between the points of the two <line> elements.
freedom-vector
Optional. The value may be "yes" or "no"; the default is "no". Determines whether to set the freedom vector to the same angle as the projection vector.
save-vectors
Optional. The value may be "yes" or "no"; the default is "no". If "yes", both the projection vector and the freedom vector are guaranteed to be the same after this intruction as they were before.

<disable-instructions>

Disables the instructions associated with glyphs. The TrueType specification does not say that instructions in the <pre-program> are disabled: presumably they are not. This instruction is available only in the <pre-program>.

Content

None.

Attributes

None.

<divide>

Divides dividend by divisor. If result-to is not specified, Xgridfit attempts to write the result to dividend.

Content

None.

Attributes

dividend
Required, except when <divide> is a child of the <formula> element. Any value or expression. The number to be divided.
divisor
Required, except when <divide> is a child of the <formula> element. Any value or expression. The number by which the dividend is to be divided.
result-to
Optional; not allowed when <divide> is the child of a <formula>. The name of a variable or control value in which to store the result. In a <formula> element the result can be passed automatically to the next arithmetic element; otherwise, if this attribute is missing, the compiler tries to store the result in dividend. Failing that, it issues a warning and leaves the result on the stack.

<else>

Provides the "else" clause for an <if> or <compile-if> element. The <else> must be the last child of the parent element.

Content

Programming to be conditionally compiled.

Attributes

None.

<enable-instructions>

Enables the instructions associated with glyphs. This instruction is available only in the <pre-program>.

Content

None.

Attributes

None.

<entry>

An entry in the PostScript private dictionary.

Content

None.

Attributes

name
Required. The name of the entry.
value
Required. The value of the entry. Usually this is a space-delimited list of numbers; for BlueFuzz it must be an integer.

<flip-off>
<flip-on>

"Flips" a range of points so that they all become either on-line points or off-line points. The <flip-off> and <flip-on> elements must contain a single <range> element. The range operated upon always runs from the lowest point to the highest.

Content

One <range> element.

Attributes

None.

<floor>

Yields the greatest integer less than or equal to value, which is either an integer representing 64ths of a pixel or a fixed-point number. The returned value, if looked at as an integer, is either zero or a multiple of 64.

Content

None.

Attributes

value
Required, except when <floor> is the child of a <formula>. Any value or expression. The value to operate on.
result-to
Optional; not allowed when <floor> is the child of a <formula>. The name of a variable or control value in which to store the result. If result-to is omitted where allowed, Xgridfit attempts to write the result to value. If value cannot be written to, the compiler issues a warning and the result is left on the stack.

<formula>

A formula is a block containing arithmetical instruction elements. Within the <formula> the behavior of these elements is modified slightly: when a result-to attribute is missing, they do not attempt to write their result back to one of the values passed to them, but rather leave it on the stack, thus making it available to the following instruction element. Further, while Xgridfit normally issues a warning when an arithmetic element takes a value from the stack or leaves a result on the stack, within a formula this is the expected behavior and so the warning is suppressed. The instructions within the formula should be chained, the result of one operation being used as an argument for the following one; this results in tight code being generated. Example:

        <formula result-to="minimum-distance">
          <round value="lc-vert-stem"/>
          <multiply value2="0.8"/>
        </formula>

This rounds the control-value "lc-vert-stem," multiplies it by 0.8, and sets the minimum distance in the graphics state to the result. The original entry in the control-value table is unchanged. By contrast, if this <round> element were not the child of a <formula>, the result would be written back to the control-value table.

Content

A sequence of elements that perform arithmetic: set-equal, add, subtract, divide, multiply, absolute, negate, floor, ceiling, minimum, maximum, round, no-round, control-value-index.

Attributes

result-to
Optional. The name of a variable or control value in which to store the result. If there is no result-to attribute, the compiler issues a warning and the result is left on the stack.

<function>

The <function> element is used to define functions. Functions are called by name using the <call-function> element. Normally Xgridfit takes care of indexing functions and making sure the right number is used to call them.

A function may also have a num attribute: this is used to define the function in the fpgm table and ensures that any legacy programming can continue to call older functions by number. Xgridfit assigns a number automatically to any function that lacks a num attribute.

A function that returns a value must have the attribute return="yes"; within such a function an instruction may assign a value to the special variable "return". The return value must be a single number; lines, vectors, and other structures consisting of two or more numbers cannot be returned.

A <function> may contain any number of <param> elements and any number of <variable> elements, followed by programming.

    <function name="lc-standard-serif">
      <!-- Regulates vertical distances within a serif -->
      <param name="base"/>
      <param name="bottom-left"/>
      <param name="bottom-right"/>
      <param name="top-left"/>
      <param name="top-right"/>
      <with-vectors axis="y">
        <mdap>
          <point num="base"/>
        </mdap>
        <mirp distance="lc-serif-height" set-rp0="yes">
          <point num="top-left"/>
        </mirp>
        <align>
          <point num="top-right"/>
        </align>
        <mirp distance="lc-serif-height" set-rp0="yes">
          <point num="bottom-left"/>
        </mirp>
        <align>
          <point num="bottom-right"/>
        </align>
      </with-vectors>
    </function>

You may define function variants, that is, alternative versions of a function to be used at certain sizes or resolutions. To do so, simply include one or more <variant> elements as the last children of the <function> element.

Content

First optional <param> elements; next optional <variable> and <alias> elements (in any order); then elements containing programming to be executed by default; finally optional <variant> elements defining versions of the function to be used if the test attribute of the <variant> element evaluates as true (non-zero) when the <pre-program> is run.

Attributes

name
Required. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. The name of this function.
xml:id
Optional. A valid XML ID, i.e. any sequence of letters, numbers, hyphens, periods; no spaces permitted; and unique within the program. This ID may be used if a function is imported into a file using XInclude.
num
Optional. A non-negative integer (zero or greater). See above for its use. If your program contains functions with num attributes, it should not contain a <legacy-functions> element.
return
Optional. Permitted values are "yes" and "no"; "no" is the default. If "yes", the function may return a value by assigning a value to the special "return" variable.

<get-coordinate>

Gets the coordinate of a point, measured along the current projection vector. If the projection vector is set to x, for example, the result will be the horizontal distance of the point from the grid origin (0,0). The result-to attribute may be the name of a variable, a control value, or a graphics state variable.

        <get-coordinate result-to="v">
          <point num="p"/>
        </get-coordinate>

Most of the time it will be more convenient to use one of the "coord" operators in an expression.

Content

The <point> to get the coordinate of.

Attributes

grid-fitted
Optional. Permitted values are "yes" and "no"; the default is "yes". Whether to use the point's current (grid-fitted) position or its original position (before grid-fitting).
result-to
Optional. The name of a variable or control value in which to store the result. If there is no result-to attribute, the compiler issues a warning and the result is left on the stack.

<getinfo>

The <getinfo> element provides access to the TrueType GETINFO instruction, which queries the TrueType engine about the state of the current glyph, about the engine version, or about whether ClearType is enabled. In general it is more convenient to use Xgridfit's built-in graphics variables to obtain such information, but the <getinfo> element may be useful to combine selectors in ways that Xgridfit does not anticipate; and future versions of the TrueType may introduce selectors that Xgridfit does not know about.

<getinfo> takes two attributes: selector indicates which query or queries to submit to GETINFO. Its value can be any number or expression; and note that the relevant graphics variables can be used here, and the value of these variables in this context is the selector rather than the result of a GETINFO query, as is the case elsewhere. Selectors for GETINFO can be combined by ANDing them; this can be simulated in Xgridfit by adding selectors together (since TrueType programming does not have arithmetical AND). This query

	<getinfo result-to="v" selector="is-glyph-rotated + is-glyph-stretched"/>

will return a non-zero (true) value if either condition is true.

The second attribute, result-to, works like the same attribute elsewhere: that is, it is a variable in which to store the result of the query, and if it is omitted the compiler issues a warning and the value is left on the top of the stack.

Content

None.

Attributes

selector
One or more of the following, added together: is-glyph-rotated, is-glyph-stretched, is-glyph-grayscale, is-cleartype-enabled, is-compatible-width-enabled, is-symmetrical-smoothing-enabled, is-BGR-order. Or, by itself, is-glyph-transformed.
result-to
Optional. The name of a variable in which to store the result. If there is no result-to attribute, the compiler issues a warning and the result is left on the stack.

<glyph>

The <glyph> element contains instructions relating to an individual glyph. Example:

        <glyph ps-name="sample-glyph">
          <constant name="last" value="50"/>
            . . .
          <variable id="v"/>
          <with-vectors axis="y">
            <!-- programming here -->
          </with-vectors>
          <with-vectors axis="x">
            <!-- more programming here -->
          </with-vectors>
          <interpolate-untouched-points/>
        </glyph>

To make a glyph program callable in the manner of a macro (see <call-glyph>), include one or more <param> elements for key values. These should have value attributes, since the glyph program will have to be compiled and run even when it is not called.

Content

<param> elements (if any) must come first, followed by <constant>, <range>, <set>, <line>, <alias> and <variable> elements in any order. Finally programming for the glyph.

Attributes

ps-name
Required. The PostScript name of the glyph. It must match the PostScript name of the glyph in the font.
xml:id
Optional. A valid XML ID, i.e. any sequence of letters, numbers, hyphens, periods; no spaces permitted; and unique within the program. This ID may be used if a <glyph> is imported into a file using XInclude.
init-graphics
Optional. Permitted values are "yes" and "no". This attribute determines whether variables used by Xgridfit to track the graphics state are initialized at the beginning of the glyph program. Such initialization is not needed when instructions are imported from another font. The default value is normally "yes," but the default may be set with the init-graphics <default> or with the -G option for the xgridfit executable.

<glyph-select>

Specifies a whitespace-delimited list of glyphs to compile, ignoring all others. It is all right to keep this element in the file when you don't need it: just empty it out. These are valid:

	<glyph-select>a macron amacron</glyph-select>
	<glyph-select></glyph-select>

This element corresponds to the glyph-select parameter and the -g command line option, either of which will, if present, override the element.

Content

A whitespace-delimited list of ps-names of glyph elements.

Attributes

None.

<if>

Contains instructions that are executed only if the expression in the test attribute is true. If the test is false, and an <else> element is the last child of this <if>, the instructions in the <else> element are executed. <if> elements may be nested.

The test attribute contains an expression, e.g.

        <if test="minimum-distance = 1p">

For more on expressions, see the Expressions section of this documentation. In the TrueType language, where all data is numeric, a non-zero value is considered true and zero false. So the test attribute can be used to tell whether a value is zero. This

        test="round(lc-vert-stem) != 0"

is equivalent to this:

        test="round(lc-vert-stem)"

The <if> element may contain an <else> clause, which must come last.

        <if test="boolean-expression">
          <!-- programming -->
          <else>
            <!-- alternative programming -->
          </else>
        </if>

Content

Programming, followed optionally by an <else> element.

Attributes

test
Required. Any value or expression. The condition to test for.

<infile>

Contains the name of a file to which TrueType instructions are to be added. This may be either a FontForge source file (.sfd) or a TrueType font (.ttf).

          <infile>MyFont.sfd</infile>
          <outfile>MyFont.ttf</outfile>

Content

The name of a file with extension .sfd or .ttf.

Attributes

None.

<interpolate>

To "interpolate" a point is to move it so that its position relative to two reference points is what it was in the original outline. If the distance between the two reference points is not what it was in the original outline, the point is positioned so that its relationship to the reference points is proportionally correct.

The <interpolate> element must contain at least one point to interpolate. It may contain any number of <point>s, <range>s and <set>s. Like most other elements that move points, it may contain a <reference> element; but this element must contain two <point>s, not just one.

This instruction may be nested inside a <move> element containing a reference point, in which case no reference points are needed in the <interpolate> element: the points it contains are automatically interpolated between the <move> element's reference point and its moved point. These two <interpolate> elements do the same thing:

        <interpolate>
          <reference>
            <point num="top"/>
            <point num="bottom"/>
          </reference>
          <point num="bar-top-left"/>
        </interpolate>

        <move>
          <reference>
            <point num="bottom"/>
          </reference>
          <point num="top"/>
          <interpolate>
            <point num="bar-top-left"/>
          </interpolate>
        </move>

If you want to round points after interpolating them, simply include the attribute round="yes" on the <interpolate> element. The points will be moved along the freedom vector to the nearest rounded position. Note that this has no effect on <range> or <set> elements. If you want to use a round state other than the current one, use the appropriate value for round:

	<interpolate round="to-half-grid">
	  <reference>
	    <point num="a"/>
	    <point num="b"/>
	  </reference>
	  <point num="c"/>
        </interpolate>

Content

An optional <reference> element (containing two <point> elements), followed by one or more <point>, <range> and <set> elements.

Attributes

compile-if
Optional. Any value or expression that can be resolved to a number at compile time. This <interpolate> element is compiled only if the compile-if attribute evaluates as true (non-zero). If this attribute is not present, the <interpolate> is compiled.
round
Optional. The value may be "yes" or "no", the name of a standard or custom round state, or any number or expression to use as an input for SROUND. If the value is anything but "no", any points referred to by <point> elements (but not <range> or <set> elements) are moved to the nearest rounded position. Points are not rounded when this attribute is not present.

<interpolate-untouched-points>

Interpolates all points that have not been moved or "touched" by instructions so that they are positioned correctly relative to points that have been moved. Most of the time you will want to place this instruction at the end of the program for each glyph.

Content

None.

Attribute

axis
Optional. Permitted values are "x" and "y". Determines the axis along which interpolation is performed. If this attribute is omitted, interpolation is performed along both x and y axes.

<legacy-functions>

Stores functions from a font that has been converted for use with Xgridfit. Normally this should not be created or edited by hand: see Conversion for further details.

Content

Programming imported from an existing font: normally just <command> and <push> elements.

Attributes

max-function-defs
Required. A positive integer (one or higher). One more than the highest index of a functon defined in the <legacy-functions> element. Normally this will be set correctly by ttx2xgf, but the user should check it before proceeding.

<line>

A <line> is defined by its two end-points. These points need not be adjacent.

When a <line> has a name attribute, another <line> may refer to it by name. You may name the <line> the first time you use it or declare it in a <line> element among the declarations at the beginning of a <glyph>. For example, if you declare the line thus:

        <line name="line-2b">
          <point num="b"/>
          <point num="a"/>
        </line>

then you can use an abbreviated form whenever you need it:

        <set-freedom-vector>
          <line ref="line-2b"/>
        </set-freedom-vector>

If both points that define a <line> are in the same zone, you may use the optional zone attribute on the <line> to indicate this. Most instructions that take a <line> as an argument allow one point to be in one zone and the other point in the other: in such cases place the zone attributes on the <point>s. The exception is the <move-point-to-intersection> instruction, which requires that each of the two lines it takes as arguments be entirely in a zone. For this instruction, place the zone attributes on the <line>s, never on the <point>s.

Content

Two <point> elements, one at each end of the line. These are required if no ref attribute is present.

Attributes

name
Optional, but necessary if this <line> is referred to elsewhere. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. Names this <line>.
ref
Required if no <point> elements are present. A reference to a named <line>.
zone
Optional. Permitted values are "twilight" and "glyph". Include the attribute zone="twilight" if both end-points of the line are in the twilight zone.

<macro>

A macro is a stretch of code that is compiled and inserted into the program stream wherever a <call-macro> element is encountered. Macros resemble functions in syntax: they begin with <param> definitions followed by program code, which can access all global variables and values (e.g. control values, graphics variables, constants and variables declared as children of <xgridfit>). Macros can be called from a <function>, <pre-program> or <glyph>, and variables and values local to these structures can be accessed by passing them as parameters.

Macro parameters are fundamentally different from function parameters. A function parameter is passed to the function on the stack at run time; the macro parameter, on the other hand, is swapped at compile time for the value parameter, which is then evaluated as any value is evaluated at run time. When passing variables or control values, there is no rule governing whether they are passed to the macro by value or by reference; rather, they are evaluated according to the rule that governs evaluation of variables for the particular instruction where they occur.

Content

Optional <param> elements, followed by optional <alias> elements, and then by programming.

Attributes

name
Required. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. Names this <macro>.
xml:id
Optional. A valid XML ID, i.e. any sequence of letters, numbers, hyphens, periods; no spaces permitted; and unique within the program. This ID may be used if a <macro> is imported into a file using XInclude.

<maximum>

Yields the greater of the two values value1 and value2.

        <maximum value1="lc-vert-stem" value2="1p" result-to="lc-vert-stem"/>

Content

None.

Attributes

value1
Required except when <maximum> is the child of a <formula> element. Any value or expression.
value2
Required except when <maximum> is the child of a <formula> element. Any value or expression.
result-to
Optional; not allowed when <maximum> is the child of a <formula>. The name of a variable in which to store the result. If result-to is omitted where allowed, the compiler issues a warning and the result is left on the stack.

<mdap>

Corresponds to the TrueType MDAP instruction. Normally <move> is a better choice for moving points, but this element is provided to facilitate low-level programming.

This element rounds a point to the grid if the round attribute is not no; otherwise it "touches" the point (marks it as moved).

        <mdap>
          <point num="p"/>
        </mdap>

Content

A single <point>.

Attributes

round
Optional. The value may be "yes" or "no", the name of a standard or custom round state, or any number or expression to use as an input for SROUND. The default value is "yes." This attribute determines whether and how to round the point.

<mdrp>

Corresponds to the TrueType MDRP instruction. Normally <move> is a better choice for moving points, but this element is provided to facilitate low-level programming.

This element will also take care of setting RP0 beforehand if a reference point is supplied. If no reference point is supplied, the current value of RP0 is used.

        <mdrp>
          <reference>
            <point num="r"/>
          </reference>
          <point num="p"/>
        </mdrp>

Content

An optional <reference> element (containing one point), followed by a single <point>.

Attributes

round
Optional. The value may be "yes" or "no", the name of a standard or custom round state, or any number or expression to use as an input for SROUND. The default value is "yes." This attribute determines whether and how to round the distance between the reference point and the moved point.
min-distance
Optional. Permitted values are "yes" and "no". The default is "yes." Whether or not to maintain a minimum distance between the reference point and the moved point.
set-rp0
Optional. Permitted values are "yes" and "no". The default is "no." Whether or not to set the RP0 pointer to the moved point after the instruction is executed.
color
Optional. Permitted values are "black", "white" and "gray". The default is "gray." The kind of distance between the reference point and the moved point. This is used by some TrueType engines to compensate for engine characteristics.

<measure-distance>

Measures the distance between two points and returns an F26dot6 number. The measurement is performed along the projection vector, and the result may be positive or negative depending on the relationship of the distance to the direction of the vector. Another way of putting it is that the order of the two points in this instruction is significant; reverse them and you reverse the sign of the result.

        <measure-distance result-to="v">
          <point num="p1"/>
          <point num="p2"/>
        </measure-distance>

Usually it will be more convenient to use the -- or --- operator in an expression.

Content

Two <point> elements.

Attributes

grid-fitted
Optional. Permitted values are "yes" and "no"; the default is "yes". Whether to use the point's current (grid-fitted) position or its original position (before grid-fitting).
result-to
Optional. The name of a variable or control value in which to store the result. If there is no result-to attribute, the compiler issues a warning and the result is left on the stack.

<message>

The <message> element produces no TrueType code, but rather causes a message to be output at compile-time via the <xsl:message> element. This may help with debugging.

Content

Text of a message to be output.

Attributes

None.

<miap>

Corresponds to the MIAP instruction. Normally <move> is a better choice for moving points, but this element is provided to facilitate low-level programming.

Positions a point a specified distance from the grid origin.

Content

A single point.

Attributes

distance
Required. The name of a control value.
round
Optional. The value may be "yes" or "no", the name of a standard or custom round state, or any number or expression to use as an input for SROUND. The default value is "yes." This attribute determines whether and how to round the distance between the reference point and the moved point.
cut-in
Optional. The value may be "yes" or "no". The default is "yes." Whether to use the control value cut-in. If rounding is used, this will always be yes, even if you set it to no.

<minimum>

Yields the lesser of the two values value1 and value2.

        <minimum value1="lc-vert-stem" value2="1p" result-to="lc-vert-stem"/>

Content

None.

Attributes

value1
Required except when <minimum> is the child of a <formula> element. Any value or expression.
value2
Required except when <minimum> is the child of a <formula> element. Any value or expression.
result-to
Optional; not allowed when <minimum> is the child of a <formula>. The name of a variable in which to store the result. If result-to is omitted where allowed, the compiler issues a warning and the result is left on the stack.

<mirp>

Corresponds to the MIRP instruction, but attempts, insofar as it is practical, to separate rounding and the cvt cut-in. You can specify round="no" and cut-in="yes" or both no or both yes, but not round="yes" and cut-in="no". That produces an error-message.

This will take care of setting RP0 beforehand if a reference point is included.

        <mirp distance="lc-x-height">
          <reference>
            <point num="p1"/>
          </reference>
          <point num="p2"/>
        </mirp>

Content

An optional <reference> element (containing one point), followed by a single <point>.

Attributes

distance
Required. The name of a control value. Distance (from a <control-value> element) relative to the reference point (or to RP0 if that was set by a previous instruction).
round
Optional. The value may be "yes" or "no", the name of a standard or custom round state, or any number or expression to use as an input for SROUND. The default value is "yes." This attribute determines whether and how to round the distance between the reference point and the moved point.
cut-in
Optional. The value may be "yes" or "no". The default is "yes." Whether to use the control value cut-in. If rounding is used, this will always be yes, even if you set it to no.
min-distance
Optional. Permitted values are "yes" and "no". The default is "yes." Whether or not to maintain a minimum distance between the reference point and the moved point.
set-rp0
Optional. Permitted values are "yes" and "no". The default is "no." Whether or not to set the RP0 pointer to the moved point after the instruction is executed.
color
Optional. Permitted values are "black", "white" and "gray". The default is "gray." The kind of distance between the reference point and the moved point. This is used by some TrueType engines to compensate for engine characteristics.

<modifier>

When used as the content of a <command> element, controls one or two bits of the output instruction.

Content

None.

Attributes

type
Required. Must be one of the following: "set-rp0", "round", "minimum-distance", "color", "grid-fitted", "to-line", "axis", "ref-ptr". This determines which bits are affected.
value
Required. The possible values vary with the type. For details and defaults, see the "Low-Level Elements" section.

<move>

Moves a point and, optionally, aligns other points with it or moves other points in relation to it. For details, see the section on moving points.

Content

An optional <reference> element containing one <point>; then a required <point>. This may be followed by any number of the following elements, in this order:

  • <delta>
  • <align>, <interpolate>, <shift> (in any order),
  • <move>
  • <delta>

The first group of <delta> element is executed before the embedded <align>, <interpolate>, <shift> and <move> elements; the second group is executed afterwards. A <move> may contain <interpolate> only if <reference> is present.

Attributes

distance
Optional. The name of a <control-value> element. If a distance is specified, the target point is positioned that distance either from the reference point or from the grid origin. If a distance is not specified, the distance from the original outline is used. In either case, the distance is measured along the projection vector.
pixel-distance
Optional. A distance in pixels. If a pixel-distance is specified, the target point is positioned that distance either from the reference point or from the grid origin. The distance and pixel-distance attributes are not compatible, and the schema does not permit both to be present.
round
Optional. The value may be "yes" or "no", the name of a standard or custom round state, or any number or expression to use as an input for SROUND. The default is "yes." Whether and how to round the distance or pixel-distance. "Yes" means round the distance according to the current round state (to-grid, if you haven't changed it). If you specify "no", no rounding is done. To use one of the standard round states, use to-grid, to-half-grid, to-double-grid, down-to-grid or up-to-grid. To use a custom round state defined in the top level of the program (as a child of <xgridfit>), use its name. Finally, any number (constant, variable) is passed to SROUND for the TrueType engine to interpret. Setting the round state with this attribute has no effect except in this instruction: the round state returns to its former value after the instruction is executed. If several <move> instructions use the same round state, it is more efficient to enclose them in a <with-round-state> element than to include a round attribute with each one. That is also true if the round value is to be no: in that case use <with-round-state round="no"> and omit the round attribute for the <move> instructions.
cut-in
Whether to use the Control Value cut-in; or a cut-in value to use. Legal values are "yes", "no" or any value or expression; the default value is "yes". If the value of this attribute is no, the value of the round attribute must also be "no". (This is a peculiarity of the TrueType instruction set and has nothing to do with Xgridfit.) This attribute has an effect only when the distance attribute is present.
min-distance
Optional. The value may be "yes" or "no" or any value or expression to be used to set the minimum distance for this operation. This attribute has an effect only when there is a reference point.
color
Optional. Permitted values are "black", "white" and "gray". The default is "gray." The kind of distance between the reference point and the moved point. This is used by some TrueType engines to compensate for engine characteristics. This applies only when there is a reference point.

<move-point-to-intersection>

Moves a point to the intersection of two lines. Each of the lines must be wholly in a single zone, so if specifying the zone use the zone attribute of the <line> elements rather than the zone attributes of the <point> elements that make up the lines.

        <move-point-to-intersection>
          <point num="p"/>
          <line>
            <point num="l1p1"/>
            <point num="l1p2"/>
          </line>
          <line>
            <point num="l2p1"/>
            <point num="l2p2"/>
          </line>
        </move-point-to-intersection>

Content

A single <point> and two <line> elements.

Attributes

None.

<multiply>

Multiplies value1 by value2. If there is no result-to attribute, Xgridfit attempts to write the result to value1.

        <multiply value1="lc-vert-stem" value2="3.3" result-to="v"/>

Content

None.

Attributes

value1
Required except when <multiply> is the child of a <formula> element. Any value or expression.
value2
Required except when <multiply> is the child of a <formula> element. Any value or expression.
result-to
Optional; not allowed when <multiply> is the child of a <formula>. The name of a variable in which to store the result. If result-to is omitted where allowed, the compiler issues a warning and the result is left on the stack.

<negate>

Converts positive to negative numbers; negative numbers stay negative. If the result-to attribute is not present, Xgridfit attempts to write the result back to value. Failing that, it issues a warning and leaves the result on the stack.

        <negate value="v"/>

Content

None.

Attributes

value
Required, except when <negate> is the child of a <formula>. Any value or expression. The value to operate on.
result-to
Optional; not allowed when <negate> is the child of a <formula>. The name of a variable or control value in which to store the result. If result-to is omitted where allowed, and value is a variable or control value, the result is written to value. If value cannot be written to, the compiler issues a warning and the result is left on the stack.

<no-compile>

This element, which must always be a child of <xgridfit>, contains <glyph> elements (usually imported via XInclude) which are visible for reference purposes but not compiled. If a file MyFont-Basic.xgf contains a glyph program with an opening tag that looks like this:

	<glyph ps-name="a" xml:id="a">

then that glyph program can be made visible within another file thus:

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

Now the following <point> will compile correctly:

	<point num="a/top + another-num"

The glyph included in this way can also be compiled via <call-glyph>:

	<call-glyph ps-name="a">
	  <with-param name="left-sidebearing" value="111"/>
	</call-glyph>

The <no-compile> element can be overridden with the <glyph-select> element (glyph-select parameter or -g option). This behavior may ease the testing of programs for composite glyphs.

Content

One or more <glyph> elements; more typically, <xi:include> elements importing <glyph> elements from other files.

Attributes

None.

<no-round>

Like round, but without the rounding. That is, it may apply a correction for the "color" of the distance, but it will not round the distance. If the result-to attribute is not present, Xgridfit attempts to write the result back to value. Failing that, it issues a warning and leaves the result on the stack.

        <no-round value="v1" color="black" result-to="v2"/>

Content

None.

Attributes

value
Required, except when <no-round> is the child of a <formula>. Any value or expression. A distance on the current grid; the value to operate on.
color
Optional. Permitted values are "black", "white" and "gray". The default is "gray." The kind of distance that the value represents. This is used by some TrueType engines to compensate for engine characteristics.
result-to
Optional; not allowed when <no-round> is the child of a <formula>. The name of a variable or control value in which to store the result. If result-to is omitted where allowed, and value is a variable or control value, the result is written to value. If value cannot be written to, the compiler issues a warning and the result is left on the stack.

<no-warning>

Inside a <no-warning></no-warning> block, warning messages are suppressed. Use this if you find a particular warning message annoying and you want to assure the compiler that you know what you're doing.

Content

Programming of any kind.

Attributes

None.

<outfile>

Contains the name of a file to write. If the filename ends .sfd it is assumed that a FontForge source file is desired, and the generated FontForge script ends with a "Save" command. If the filename ends .ttf it is assumed that a TrueType font is desired, and the generated FontForge script ends with a "Generate" command. It is an error if the filename has any other suffix.

The fmflags attribute indicates flags to pass to FontForge when generating a TrueType font. It has no effect when the <outfile> is a FontForge source file. For a list of these flags, see the documentation for the Generate command. Probably the most likely to be used is "2048" (generate old-style kern table).

          <infile>MyFont.sfd</infile>
          <outfile fmflags="2048">MyFont.ttf</outfile>

Content

The name of a file, with extension of either .sfd or .ttf.

Attributes

fmflags
Optional. An integer. Flags to be passed to the FontForge "Generate" command. This has no effect when Python output is selected; instead, use pyflags.
pyflags
A list of flags for FontForge to use when it generates a font. This is a space-separated list of tokens, e.g. pyflags="old-kern ofm". Possible tokens are: afm, pfm, tfm, ofm, composites-in-afm, glyph-map-file, short-post, apple, opentype, old-kern, dummy-dsig, TeX-table, round, no-hints, omit-instructions, PfEd-comments, PfEd-colors, PfEd-lookups, PfEd-guidelines, PfEd-background, symbol. For the meanings of these, see the section of the FontForge manual on generating fonts in Python scripts.

<outfile-base>

This element, which must be a child of <xgridfit>, corresponds to the outfile-base parameter and the -S option for the xgridfit shell script. If present, it causes a separate file to be output for every glyph that Xgridfit compiles. The name of the file is the string supplied in this element, plus the ps-name of the glyph, plus the extension .pe, .py or .debug. For example, this element

	<outfile-base>Test</outfile-base>

causes Xgridfit to output files with names like Test_A.pe and Test_B.py (or Test_A.py and Test_B.pe when Python output is requested). Elements such as control values, functions and the pre-program are output as usual in the default output script or in a file specified with the -O option. Note that this element also causes the output of <outfile> to be saved in a separate script whose default name depends on <outfile-base>. See <outfile-script-name> to specify a different name for this separate file.

This feature depends on the presence of an extension element that not every XSLT processor supports. Xsltproc, which Xgridfit uses by default, does support it.

Content

A fragment of a file name, from which other file names are built.

Attributes

None.

<outfile-script-name>

When the <outfile-base> element is present or the -S option is used, and the <outfile> element is present or the -o option is used, Xgridfit outputs the FontForge command that saves a font file or generates a font in a separate script file. By default the filename for this script is based on the outfile-base: for example, if the -S parameter is MyFont, then the filename will be MyFont_outfile.pe or MyFont_outfile.py. Use the <outfile-script-name> element (or the -z option) to specify a filename other than the default. This element must be a child of <xgridfit>.

This element has no effect when the outfile-base is not specified, and the glyph programs in a script are not being saved separately.

Content

Name of a file containing the FontForge "Generate" or "Save" command.

Attributes

None.

<param>

A <param> element is a declaration that a value, a structure or some code may be passed to the <function>, <macro> or <glyph> that contains it by the "call" element that calls it. The <param> elements should be the first children of <function>, <macro> and <glyph> elements.

In the case of a <function>, only a value (a single number) may be passed. A <macro> or <glyph> is much more flexible: <line>, <range>, <set> and fragments of code may be passed. Within the <macro> or <glyph>, the structures can be referenced via ref attributes; code passed as a parameter can be called via a <call-param> element.

A <param> may contain a default value--that is, a value to be used in the event that the call element does not pass a value. The <param> may also contain code to be used when the call element does not pass code; but it may not contain a <line>, <range> or <set>.

Content

Normally this element is empty; but a <param> intended to pass code to a <macro> or <glyph> may contain code to be used when the <call-macro> or <call-glyph> element lacks a matching <with-param> element.

Attributes

name
Required. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. The name of the <param> is used both by the call element and by the code that requires the value or item passed.
value
Optional. A default value.

<param-set>

Contains a set of parameters (each encoded as a <with-param> element) to be passed to a function or macro. There may be more than one of these in a <call-function> or <call-macro> element; and in that case the function is called repeatedly (via LOOPCALL) until the list of <param-set> elements is exhausted; or the macro code is compiled and inserted repeatedly.

Content

One or more <with-param> elements.

Attribute

opt
Optional. If set to "yes," forces optimization in pushing function parameters onto the stack. That is, instructs Xgridfit to push all parameters with a single PUSHB command. Use this if you are sure that all parameters can be determined by the compiler (i.e. they are not determined at run-time) and that they are all between 0 and 255, but Xgridfit is not optimizing. If you get this wrong, that is, if you force optimization when it really ought not to be used, incorrect code will be generated and your glyph program will fail. Still, it may be worth a try since the failure will probably be obvious. Conversely, set this to "no" if Xgridfit is incorrectly optimizing the parameters in a function call. This probably won't happen, since Xgridfit optimizes rather conservatively, but it's here just in case.

<point>

The <point> element defines a point. It is used in all instructions that manipulate or refer to points.

Content

None.

Attributes

num
Required. Any value or expression. The number of a point. To refer to a point in a glyph other than the one whose glyph program is currently running (as you may have occasion to do when instructing composite glyphs), use the syntax "g/p", where g is the ps-name of the other glyph, and p is the point being referred to (it must be the name of a <constant> declared in the other glyph).
zone
Optional. Permitted values are "twilight" and "glyph". The zone that contains this point. Instructions will take note of this attribute, when present, and adjust the zone pointers appropriately. The glyph zone is always the default zone. When a point is in the glyph zone it is generally redundant to include an attribute zone="glyph", and doing so may also cause unnecessary (though harmless) code to be generated. N.B. For instructions that deal with lists of points, include the zone attribute only in the first.

<pre-program>

The prep table (or CVT program) is made from the <pre-program> element. It contains instructions that are executed before a font is rasterized, or whenever it is about to be rasterized in a new size. A typical thing to do in the <pre-program> is to adjust control values, e.g. rounding or applying deltas to them. Another is to set defaults: an instruction that assigns a value to a graphic variable sets a default when it is executed in the <pre-program>. For example, if executed in the <pre-program> this instruction:

        <set-minimum-distance value="0.9">

ensures that the minimum-distance graphics variable is always 0.9 pixels at the beginning of any glyph program.

The <pre-program> element must be present in a complete Xgridfit program, even if it is empty.

Content

One or more optional <variable> and <alias> elements, followed by optional programming.

Attribute

xml:id
Optional. A valid XML ID, i.e. any sequence of letters, numbers, hyphens, periods; no spaces permitted; and unique within the program. This ID may be used if the <pre-program> is imported into a file using XInclude.

<ps-private>

Provides access to the font's private PostScript dictionary. This dictionary is not included in a TrueType font, but it does provide crucial information to the FontForge auto-hinter; and the FontForge auto-instructor, in turn, depends on the presence of PostScript-style hints. For details, see Merge-mode.

Content

One or more <entry> elements, each supplying the name and value of an entry in the PostScript private dictionary. For example:

	<ps-private>
          <entry name="BlueValues" value="-33 -2 856 873 1358 1385"/>
          <entry name="OtherBlues" value="-578 -553"/>
          <entry name="BlueFuzz" value="0"/>
        </ps-private>
      

<push>

The <push> element does the work of the various PUSHB and PUSHW instructions, and it can generate the code to move any value (e.g. a variable or control-value) onto the stack. It may be used in combination with <command> to insert low-level TrueType commands into your Xgridfit programming in a portable way. Its content is a whitespace-delmited list of numbers, identifiers and expressions. These are valid Xgridfit <push> instructions:

        <push>2 5 89 67</push>

        <push>
          left
          right
          lc-vertical-stem
          -1
        </push>

        <push> 0.58p 2.0 to-grid </push>

        <push>1 (top + 3) 512</push>

It is essential that all expressions containing whitespace be enclosed in parentheses.

Content

A space-delimited list of values and expressions.

Attributes

None.

<range>

A <range> is a collection of contiguous points defined by its end-points. It can be used in any instruction that operates on more than one point: <shift>, <align>, <interpolate>, <shift-absolute>, <toggle-points>. The order of points in the <range> is not significant. Example:

        <align>
          <reference>
            <point num="bottom"/>
          </reference>
          <range>
            <point num="bottom - 2"/>
            <point num="bottom + 2"/>
          </range>
        </align>

If "bottom" is point 17, the <range> begins with 15 and ends with 19. But any reference point in the parent element of the <range> is excluded from the <range>, so this <range> actually represents points 15, 16, 18 and 19. The same is true of implicit reference points supplied by a <move> element that is the parent of the parent of the <range>:

        <move>
          <point num="bottom"/>
          <align>
            <range>
              <point num="bottom - 2"/>
              <point num="bottom + 2"/>
            </range>
          </align>
        </move>

Here the points in the <range> are aligned with "bottom" after it has been moved by the <move> instruction; but "bottom" itself is not part of the <range>. The code above is functionally identical to this:

        <move>
          <point num="bottom"/>
          <align>
            <point num="bottom - 2"/>
            <point num="bottom - 1"/>
            <point num="bottom + 1"/>
            <point num="bottom + 2"/>
          </align>
        </move>

The latter generates more efficient code than the example with the <range>, but the <range> is more flexible, since its endpoints, its size, and the points to be excluded need not be known until run-time. This makes the <range> ideal for use in functions.

All the points in a <range> must be in the same zone, determined by the optional zone attribute on the <range> element. Any zone attributes on the <point>s within the <range> are ignored.

Content

Two <point> elements. These are required if no ref attribute is present.

Attributes

name
Optional, but necessary if this <range> is referred to elsewhere. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. Names this <range>.
ref
Required if no <point> elements are present. A reference to a named <range>.
zone
Optional. Permitted values are "twilight" and "glyph".

<restore-default>

To reset any of the graphics variables tracked by Xgridfit to its default value (that is, the value set by your Xgridfit program via a <default> element or by setting it in the <pre-program>--failing that, the TrueType default), use the <restore-default> element. Use the value all to reset all graphics variables, including the freedom and projection vectors and the auto-flip state, which Xgridfit does not track. The all option sets these last to their TrueType defaults: the x axis for the vectors and "on" for auto-flip.

	<restore-default name="minimum-distance"/>

Content

None.

Attribute

name
The name of the graphics variable to restore to its default value. Possible values are "minimum-distance", "control-value-cut-in", "single-width", "single-width-cut-in", "delta-base", "delta-shift", "round-state", "all".

<reference>

In any instruction that can position a point or other structure with reference to one or more points, the <reference> element holds the reference point(s). This element generally contains precisely one point, but when it is the child of an <interpolate> element it must contain two points. In the following example, point p2 is moved relative to point p1:

        <move>
          <reference>
            <point num="p1"/>
          </reference>
          <point num="p2"/>
        </move>

Content

A single <point>. When the <reference> element is the child of <interpolate>, two points.

Attributes

None.

<round>

Rounds a number representing a distance according to the current round state, applies whatever correction is appropriate for the "color" of the distance, and returns the result.

<round value="lc-vert-stem" color="black" result-to="new-cvt"/>

Content

None

Attributes

value
Required, except when the child of <formula>. Any value or expression, understood as a distance on the current grid. This is the number to round.
color
Optional. Permitted values are "black", "white" and "gray". The default is "gray." The kind of distance that the value represents. This is used by some TrueType engines to compensate for engine characteristics.
result-to
Optional; not allowed when <round> is the child of a <formula>. The name of a variable or control value in which to store the result. If result-to is omitted where allowed, and value is a variable or control value, the result is written to value. If value cannot be written to, the compiler issues a warning and the result is left on the stack.

<round-state>

Declares a custom round state whose name can be passed to <set-round-state>, <with-round-state>, or any element that takes a round attribute. For an explanation of the period, phase and threshold attributes, see "Rounding." Note that only a limited number of values is permitted for each of these attributes. This element is permitted only at the top level of a program, as a child of <xgridfit>.

        <round-state name="my-round" period="two-pixel"
                     phase="three-quarters"
                     threshold="three-quarters"/>

Content

None.

Attributes

name
Required. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. This is the name under which the program may refer to this round state.
period
Required. One of the following: "half-pixel", "one-pixel", "two-pixel".
phase
Required. One of the following: "zero", "one-quarter", "one-half", "three-quarters".
threshold
Required. One of the following: "period-minus-one", "minus-three-eighths", "minus-one-quarter", "minus-one-eighth", "zero", "one-eighth", "one-quarter", "three-eighths", "one-half", "five-eighths", "three-quarters", "seven-eighths", "one", "nine-eighths", "five-quarters", "eleven-eighths".

<set>

A <set> is an arbitrary collection of points, defined by the <point> elements contained in the <set> element. The <set> can be used by any element that accepts a collection of points: <align>, <interpolate>, <shift>, <shift-absolute>, <toggle-points>.

A <set> can be used only in a <glyph> program, or it can be referenced in a <macro> called by a <glyph> program. The name of a <set> can be passed to a macro as a parameter, and a <set> can be the content of a <with-param> element.

Xgridfit must be able to resolve the num attributes of all <point>s in a <set> at compile time. It is an error to attempt to reference a variable in a <set>.

When a <set> is used in an element that has reference points, either explicitly via the <reference> element or implicitly via an enclosing <move> element, any reference points repeated in the set are excluded. This works only when the <reference> points can be resolved at compile time.

A <set> may be preferable to a <range> when all point numbers are known at compile time and the range is short, including perhaps three or four points. The code generated by Xgridfit on encountering a <set> is less flexible, but vastly more efficient than that generated on encountering a <range>.

A <set> may be defined thus among the declarations at the beginning of a <glyph>:

	<set name="bar-bottom-left-corner">
	  <point num="bar-bottom-left"/>
	  <point num="bar-bottom-left + 1"/>
	  <point num="bar-bottom-left + 2"/>
	</set>
	<set name="bar-bottom-right-corner">
	  <point num="bar-bottom-right"/>
	  <point num="bar-bottom-right - 1"/>
	  <point num="bar-bottom-right - 2"/>
	</set>

It can then be referenced whenever needed:

	<move distance="cap-horz-stem">
	  <reference>
	    <point num="bar-top-left"/>
	  </reference>
	  <point num="bar-bottom-left"/>
	  <shift>
	    <set ref="bar-bottom-left-corner"/>
	    <set ref="bar-bottom-right-corner"/>
	  </shift>
	</move>

Content

One or more <point> elements. These are required if no ref element is present.

Attributes

name
Optional, but necessary if this <set> is referred to elsewhere. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. Names this <set>.
ref
Required if no <point> elements are present. A reference to a named <set>.
zone
Optional. Permitted values are "twilight" and "glyph".

<set-auto-flip>

When "on" (the default setting), the TrueType engine automatically adjusts the signs of control values when executing MIRP and MIAP instructions. This works very well, so there is rarely a reason to set this to "off."

Content

None.

Attribute

value
Required. Permitted values are "on" and "off".

<set-control-value>
<with-control-value>

You can assign a value to a control value anywhere: in the <pre-program>, a <function>, or a <glyph> program. The value you assign can be either in font units (the units of the grid on which you designed the font) or in pixel units (the grid on which the glyph is now being rasterized). To specify which, include the attribute unit="font" or unit="pixel" ("font" is the default). You must specify the name of the control value with the name attribute and the value (an integer in font units or an "F26Dot6" number in pixel units) with the value attribute.

You can use <set-control-value> to make a control value simulate a local variable.

Use <with-control-value>, which takes attributes exactly like those of <set-control-value>, to assign a control value to be used only within the <with-control-value> element. After this element, the value will be the same as it was before.

	<set-control-value name="myval" unit="font" value="850"/>
	<set-control-value name="otherval" unit="pixel"
                    value="control-value(otherval) * 2"/>
        <with-projection-vector axis="y">
	  <set-control-value name="myval" unit="pixel"
	            value="point(a) --- point(b)"/>
	</with-projection-vector>

Content

None for <set-control-value>; <with-control-value> contains programming of any kind.

Attributes

name
Required. The name of the control value to set.
value
Required. Any value or expression. The value to write to the control value.
unit
Optional. Permitted values are "font" and "pixel"; the default is "font". Whether the value is in font units or pixel units.

<set-control-value-cut-in>
<with-control-value-cut-in>

The value is a distance on the grid. If the difference between a distance from a <control-value> element and the original distance is greater than this, the original distance is used. The effect is generally to use the <control-value> distance at low resolutions and the original distance at high resolutions. This can be used to promote evenness at small sizes, where a 1-pixel difference between the width of (say) p and b can look bad. The default value is 17/16: that is, 1.0625p or 68.

        <set-control-value-cut-in value="1.1"/>

Content

<set-control-value-cut-in> has no content; <with-control-value-cut-in> contains programming.

Attribute

value
Required. Any value or expression. This is the new control value cut-in.

<set-coordinate>

Moves a point to a coordinate determined by the freedom and projection vectors. On the rare occasions when you need a command like this one, it is probably better to use <move> with the pixel-distance attribute.

Content

A <point> to move.

Attribute

coordinate
Required. Any value or expression. This is the new coordinate of the point.

<set-delta-base>
<with-delta-base>

Sets the number that is added to the "size" attribute of a <delta-set> element to get the resolution at which an adjustment should take place. The default value is 9, and that rarely needs to be changed.

        <with-delta-base value="56">
          <delta>
            <delta-set size="12" distance="-8">
              <point num="p"/>
            </delta-set>
          </delta>
        </with-delta-base>

Content

<set-delta-base> has no content; <with-delta-base> contains programming.

Attribute

value
Required. Any value or expression. This is the new delta base.

<set-delta-shift>
<with-delta-shift>

The unit by which a delta instruction shifts a point. If the unit is "2," the smallest shift is half a pixel; if "4," it is a quarter of a pixel; if "8" (the default) it is one eighth, and so on.

        <set-delta-shift value="32"/>

Content

<set-delta-shift> has no content; <with-delta-shift> contains programming.

Attribute

units-per-pixel
Required. These values are permitted: "2", "4", "8", "16", "32", "64".

<set-dropout-control>

Sets up dropout control. The threshold is a number between 0 and 254 in pixels per em. The flags attribute is a number that tells how to set up dropout control relative to the threshold. Here are the flags as explained in the Apple TrueType Reference:

  • 1. Set dropout control to TRUE if other conditions do not block and ppem is less than or equal to the threshold value.
  • 2. Set dropout control to TRUE if other conditions do not block and the glyph is rotated.
  • 4. Set dropout control to TRUE if other conditions do not block and the glyph is stretched.
  • 8. Set dropout control to FALSE unless ppem is less than or equal to the threshold value.
  • 16. Set dropout control to FALSE unless the glyph is rotated.
  • 32. Set dropout control to FALSE unless the glyph is stretched.

Note that, for the sake of simplicity, the numbers used here are different from those implied in the Apple TrueType Reference. Xgridfit adjusts them before passing them to the TrueType engine.

To turn off dropout control, set both threshold and flags to zero.

Content

None.

Attributes

threshold
Required.
flags
Required.

<set-dropout-type>

Sets dropout type. The Microsoft TrueType Reference describes the action of the possible values as follows:

  • if n=0 rules 1 and 2, and 3 are invoked (dropout control scan conversion including stubs)
  • if n=1 rules 1, 2 and 4 are invoked (dropout control scan conversion excluding stubs)
  • if n=2 rules 1 and 2 only are invoked (fast scan conversion; dropout control turned off)
  • if n=3 same as n = 2
  • if n = 4 rules 1, 2, and 5 are invoked (smart dropout control scan conversion including stubs)
  • if n = 5 rules 1, 2, and 6 are invoked (smart dropout control scan conversion excluding stubs)
  • if n = 6 same as n = 2
  • if n = 7 same as n = 2

The scan conversion rules are shown here:

Rule 1
If a pixel’s center falls within the glyph outline, that pixel is turned on.
Rule 2
If a contour falls exactly on a pixel’s center, that pixel is turned on.
Rule 3
If a scan line between two adjacent pixel centers (either vertical or horizontal) is intersected by both an on-Transition contour and an off-Transition contour and neither of the pixels was already turned on by rules 1 and 2, turn on the left-most pixel (horizontal scan line) or the bottom-most pixel (vertical scan line). This is “Simple” dropout control.
Rule 4
Apply Rule 3 only if the two contours continue to intersect other scan lines in both directions. That is, do not turn on pixels for ‘stubs.’ The scanline segments that form a square with the intersected scan line segment are examined to verify that they are intersected by two contours. It is possible that these could be different contours than the ones intersecting the dropout scan line segment. This is very unlikely but may have to be controlled with grid-fitting in some exotic glyphs.
Rule 5
If a scan line between two adjacent pixel centers (either vertical or horizontal) is intersected by both an on-Transition contour and an off-Transition contour and neither of the pixels was already turned on by rules 1 and 2, turn on the pixel which is closer to the midpoint between the on-Transition contour and off-Transition contour. This is “Smart” dropout control.
Rule 6
Apply Rule 5 only if the two contours continue to intersect other scan lines in both directions. That is, do not turn on pixels for ‘stubs.’

Content

None.

Attribute

value
Required. Possible values are from "0" to "7," with meanings as described above.

<set-dual-projection-vector>

Like <set-projection-vector>, but the dual projection vector can be set only from a line, and it uses the original positions in the outline of the points that constitute the line rather than their current positions (assuming they have moved).

The dual projection vector is not used by every instruction: just by <interpolate>, <get-coordinate>, <measure-distance>, <mirp>, <mdrp>, and <move> (only when a "relative-to" point is present). This vector lasts only until a new projection vector is set; then it gets canceled.

One or both points in the line may be in the twilight zone. See the explanation for <set-vectors>.

        <with-projection-vector>
          <set-dual-projection-vector to-line="orthogonal">
            <line ref="line-a"/>
          </set-dual-projection-vector>
          <!-- programming here; then the end of the with-projection-vector
               block returns the dual projection vector to its former value. -->
        </with-projection-vector>

Content

One <line>.

Attributes

to-line
Optional. Possible values are "orthogonal" and "parallel"; the default is "parallel". Determines whether the dual projection vector will be orthogonal or parallel to the <line> from which it is set.

<set-equal>

Set target (variable, control value, or any of the graphics state variables that Xgridfit can write to) equal to source, which can be an expression or any number type that Xgridfit can handle.

        <!-- This is the equivalent of a := b; in C. -->
        <set-equal target="a" source="b"/>

Content

None.

Attributes

source
Required. Any value or expression.
target
Required. The name of a variable, control value or graphics variable to write to.

<set-freedom-vector>
<with-freedom-vector>

Just like <set-vectors>, but sets only the freedom vector.

<set-minimum-distance>
<with-minimum-distance>

The minimum-distance property is used by several instructions when the "min-distance" attribute is "yes." The default minimum distance is one pixel (1.0, 1p, 64), but can be set to another value here.

        <with-minimum-distance value="0.85">
          <!-- The distance between p1 and p2 must be at least 0.85 pixel. -->
          <move round="no">
            <reference>
              <point num="p1"/>
            </reference>
            <point num="p2"/>
          </move>
        </with-minimum-distance>

Content

<set-minimum-distance> has no content; <with-minimum-distance> contains programming.

Attributes

value
Required. Any value or expression. This is the new minimum distance.

<set-projection-vector>
<with-projection-vector>

Just like <set-vectors>, but sets only the projection vector.

<set-round-state>
<with-round-state>

Sets the round state. If the round attribute matches the name of a <round-state>, that round state is used. If not, one of TrueType's prefabricated round states may be used:

  • to-grid
  • to-half-grid
  • to-double-grid
  • up-to-grid
  • down-to-grid

If the round attribute is not one of these, and not the name of one of the custom round-states, Xgridfit tries to resolve it as a number, constant, variable or function parameter and use that as an argument to SROUND. You had better know what you're doing if you intend to use a raw number in this way; it is safer, more intelligible and just as effective to supply a custom <round-state> element.

The distinction between the element beginning with "set" and the one beginning with "with" is the same as it is for the vector-setting elements: briefly, the round state set by the "set" element affects the instructions that follow it; the round state set by the "with" instruction affects only the instructions that it contains.

Xgridfit generates instructions that keep track of the round state (since the TrueType engine provides no way to read it), but it may lose track if Xgridfit instructions are not used exclusively.

        <with-round-state round="to-half-grid">
          <move>
            <point num="v-point"/>
          </move>
        </with-round-state>

Content

<set-round-state> has no content; <with-round-state> contains programming.

Attributes

round
Required. The name or a standard or custom round state; any value or expression. This is the new round state.

<set-single-width>
<with-single-width>

The size of the single width, in FUnits, i.e. the units of the grid the font was designed on (usually 2048 or 1000 units per em). Presumably this width is converted to the current grid, and it is that converted value that the single-width cut-in is compared to.

Content

<set-single-width> has no content; <with-single-width> contains programming.

Attributes

value
Required. Any value or expression, interpreted as font units. This is the new single width.

<set-single-width-cut-in>
<with-single-width-cut-in>

When the <mirp> or <mdrp> instruction is used, or when <move> is used relative to a point, a single width (determined by <set-single-width> or <with-single-width>) may be used rather than a control value or the original distance if this condition is met: the absolute (either positive or negative) difference between the original outline and the single width is less than the single-width cut-in. The relevant distances are in pixels.

The single width feature appears to be used rarely.

Content

<set-single-width-cut-in> has no content; <with-single-width-cut-in> contains programming.

Attributes

value
Required. Any value or expression. This is the new single-width cut-in.

<set-vectors>
<with-vectors>

Sets both the projection vector and the freedom vector to the same value. They can be set to "x" or "y" via the axis attribute; to a line by including a line element as the content of the <set-vectors> element or the first child of the <with-vectors> element; or by passing "raw" values via the x-component and y-component attributes.

Xgridfit looks first for an axis attribute, next for a <line>, and finally for x-component and y-component attributes (neither is used unless both are present). If it finds none of these and the present element is <with-vectors>, Xgridfit simply stores the present vectors on the stack and restores them at the end of the block. If the present element is <set-vectors>, Xgridfit prints a warning and attempts to find "raw" vector values on the stack.

The "raw" values passed in via x-component and y-component are constrained in ways that make them difficult to calculate, at least in a TrueType program, but the x-component/y-component method is useful to restore values that have been saved via <store-projection-vector> or <store-freedom-vector>. For example, to copy one vector to another, you can do this:

        <variable name="x-comp"/>
        <variable name="y-comp"/>
        <store-freedom-vector x-component="x-comp" y-component="y-comp"/>
        <set-projection-vector x-component="x-comp" y-component="y-comp"/>

But because of the way these instructions can leave values on the stack and take them from the stack again, this is easier and more efficient:

	<no-warning>
          <store-freedom-vector/>
          <set-projection-vector/>
	</no-warning>

When setting vectors to a line, one or both points in the line can be in the twilight zone. You can include a zone attribute in the <line> element or one in either or both <point> elements. Include a zone attribute in the <line> element if both points are in the twilight zone. This is the same as including an attribute zone="twilight" in both points. If only one point is in the twilight zone, include the zone attribute for that point.

Here are several examples:

        <with-vectors axis="x">
          <!-- programming that moves points horizontally. -->
        </with-vectors>

        <with-vectors to-line="orthogonal">
          <line ref="diagonal-line"/>
          <!-- programming that moves points along a line orthogonal to
               diagonal-line. -->
        </with-vectors>

        <set-vectors to-line="parallel">
          <line ref="diagonal-line"/>
        </set-vectors>
        <!-- Subsequent programming will move points along a line parallel
             to diagonal-line. -->

Content

<set-vectors> has no content if an axis attribute or the x-coordinate and y-coordinate attributes are present; otherwise it may contain a <line> element. <with-vectors> works the same way, but also contains programming.

Attributes

axis
Optional, and incompatible with other attributes. Possible values are "x" and "y".
to-line
Optional, and permitted only when a <line> is present. Possible values are "orthogonal" and "parallel"; the default is "parallel". Determines whether the vectors will be orthogonal or parallel to the <line> from which they are set.
x-component, y-component
Optional, but if one of these attributes is present, the other must be as well. Not permitted with other attributes or when a <line> is present.

<shift>

Shifts one or more points, ranges, sets, contours and zones by the distance between the current position of the reference point and its original position. Note that this does not guarantee that the shifted elements will maintain their original distance from the reference point (use <move> or <mdrp> for that).

The <shift> element may contain points, ranges, sets, contours and zones in any combination and order. The following is perfectly correct:

        <shift>
          <reference>
            <point num="ref-pt"/>
          </reference>
          <point num="move-pt-1"/>
          <range ref="move-rg-1"/>
          <contour num="0"/>
          <point num="move-pt-2"/>
          <range ref="move-rg-2"/>
        </shift>

But note that all the points are shifted first, then all the ranges or sets, then all the contours, and finally any zones. The order of child elements in the <shift> element is not significant.

If you want to move points to the nearest rounded position after the shift, include a round attribute. This works exactly like the round attribute on the <interpolate> element.

Content

Any number of <point>, <range>, <set>, <contour> and <zone> elements, in any order.

Attributes

compile-if
Optional. If present, the <shift> element is compiled only if this attribute evaluates as true (non-zero) at compile time.
round
Optional. Possible values are "yes", "no", one of the standard or custom round states, or any value or expression yielding a number to pass to SROUND. The default value is "no", since by default no rounding is done on the <point>s contained in a <shift> element.
reference-ptr
Optional. Possible values are "1" and "2". This determines which reference pointer (RP1 or RP2) to use. Normally Xgridfit decides which pointer is appropriate in the context; otherwise RP1 is used.

<shift-absolute>

Moves one or more points along the freedom vector by a fixed amount (expressed in pixels); it does not use the projection vector. The <shift-absolute> element must contain at least one point to shift: that is, a <range>, <set> or <point> element. It may contain any number of <point>s, <range>s and <set>s.

Content

Any combination of <range>, <set> and <point> elements in any order.

Attributes

pixel-distance
Required. Any value or expression, understood as a distance on the grid.

<srp>

Does the work of SRP0, SRP1, SRP2. But it should rarely be necessary to set the reference pointers explicitly.

Content

One <point> element; the reference pointer is set to point to this.

Attribute

whichpointer
Required. The reference pointer to set. Possible values are "0", "1" and "2".

<store-projection-vector>
<store-freedom-vector>

These instructions store a vector as two numbers, an x-component and a y-component. The x-component and y-component attributes, if given, must be identifiers for variables:

	<store-projection-vector x-component="vx" y-component="vy"/>

If these attributes are not given, a warning is printed and the values are left on the stack, where they will be picked up correctly by a following set instruction. For example, this code sets the projection vector to be the same as the freedom vector:

        <store-freedom-vector/>
        <set-projection-vector/>

Note that a with block will not pick up the components of a vector from the stack.

Content

None.

Attributes

x-component, y-component
Optional, but if one attribute is present the other must be as well. The names of variables in which to store the components of the vector. If these attributes are not present, the compiler displays a warning and the values are left on the stack.

<subtract>

Subtracts minuend - subtrahend. If result-to is not specified, Xgridfit attempts to write the result to minuend.

Content

None.

Attributes

minuend
Required, except when <subtract> is the child of a <formula>. Any value or expression. The value to subtract from.
subtrahend
Required, except when <subtract> is the child of a <formula>. Any value or expression. The value to subtract from the minuend.
result-to
Optional; not allowed when <subtract> is the child of a <formula>. The name of a variable of control value in which to store the result of this operation. If result-to is omitted where allowed, and minuend is a variable or control value, the result is written to minuend. If minuend cannot be written to, the compiler issues a warning and the result is left on the stack.

<szp>

Does the work of SZP0, SZP1, SZP2. But these should rarely be needed (use the zone attributes of the point element instead).

Content

None.

Attributes

zone
Required. Possible values are "twilight" and "glyph". The zone to set the zone pointer to.
whichpointer
Required. Possible values are "0", "1" and "2". Identifies the pointer to set.

<toggle-points>

Any of the points that are on-line become off-line, and any that are off-line become on-line. The <toggle-points> element must contain at least one point to toggle: that is, a <range>, <set> or <point> element. It may contain any number of <point>s, <set>s and <range>s.

Content

One or more <point>, <set> and <range> elements.

Attributes

None.

<to-stack>

The <to-stack> element moves a single value onto the stack. This can be any kind of value or expression, e.g. a number literal, variable, control value or graphics variable. Use <push> instead when more than one value needs to be placed on the stack.

Content

A single value or expression.

Attributes

None.

<untouch>

A point that has been moved is "touched." This untouches it so that it will be affected by the <interpolate-untouched-points> instruction.

Content

One <point> element.

Attributes

None.

<variable>

Variables are spaces in the TrueType Storage Area. They are declared in <variable> elements; Xgridfit takes care of indexing the Storage Area.

        <variable name="var-name"/>

Most variables are local to a glyph program, function or pre-program. Variable declarations may come among the declarations at the beginning of a <glyph> program; after <param> elements in a <function>, and at the beginning of the <pre-program>. A global variable may be declared anywhere in the top level of the program, as a child of <xgridfit> (it is good form to group variable declarations together); a value may be assigned to a global variable in the <pre-program> and read by code in any <glyph> or <function> or elsewhere in the <pre-program>.

Variables must be written to before they can be read from. (Some versions of Freetype initialize them to zero, but the Microsoft rasterizer yields an error if a variable is read before it is written.) Local variables may be initialized with a value attribute in the declaration.

A variable is named via its name attribute. This must be unique in the file in the case of a global variable, but in the case of local variables unique only in the <glyph> program or <function>. Several names are reserved and should be avoided when naming variables and constants, since they belong to pre-defined variables and constants:

  • Current size (all read-only):
    • pixels-per-em
    • point-size
  • Values of the round-state variable (constants):
    • to-grid
    • to-half-grid
    • to-double-grid
    • down-to-grid
    • up-to-grid
    • no
    • custom
  • Graphics variables:

    Writing to these changes the graphics state. The "default" variables can be written to only in the <pre-program>. Trying to write to them elsewhere produces a compile error. Actually, it is never necessary to write to a "default" variable since writing to one of the other variables in the <pre-program> automatically writes to the "default" variable as well. So treat the "default" variables as read-only variables.

    • round-state (can be written to only via <set-round-state> and <with-round-state>)
    • custom-round-state (can be written to only via <set-round-state> and <with-round-state>)
    • minimum-distance
    • minimum-distance-default
    • control-value-cut-in
    • control-value-cut-in-default
    • single-width
    • single-width-default
    • single-width-cut-in
    • single-width-cut-in-default
    • delta-base delta-base-default
    • delta-shift delta-shift-default

Content

None.

Attributes

name
Required. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. The name of this variable.
value
Optional. Any value or expression. A value with which to initialize the variable.

<variant>

A <variant> is an alternative version of a function to be used at certain sizes or resolutions. Include one or more <variant> elements as the last children of any <function> element. For further explanation, see the section on functions.

Content

Programming. <param> and <variable> elements are not permitted; the <variant> must use those of the parent <function>.

Attribute

test
Required. Any value or expression. The variant is used if this attribute evaluates as true (non-zero) when the <pre-program> is run.

<with-control-value>

See <set-control-value>

<with-control-value-cut-in>

See <set-control-value-cut-in>

<with-delta-base>

See <set-delta-base>

<with-delta-shift>

See <set-delta-shift>

<with-freedom-vector>

See <set-freedom-vector>

<with-minimum-distance>

See <set-minimum-distance>

<with-param>

Defines a value to be passed to a function, macro or glyph program. The value may be any of the value-types that Xgridfit handles. Note that all values are resolved to numbers before a call to a function takes place: Xgridfit does not pass parameters to functions by reference. A result of this is that if a variable or control value is passed to a function, these things cannot be written to.

In general there will be a <with-param> element for every <param> element that appears in the function or macro being called. However, a <with-param> element may be omitted if the matching <param> contains a default value.

The order of <with-param> elements in a <param-set>, <call-function>, <call-macro> or <call-glyph> element is not significant.

If the <with-param> element is part of a call to a macro, the value passed can be a <set>, <range> or <line>. The name of such a structure can be passed via the value attribute, or the structure itself can be passed as the child of <with-param>. When <with-param> contains a <set>, <range> or <line>, the value attribute is optional.

Programming can also be passed via a <with-param> element, and in this case too the value attribute is optional.

Content

Usually none, but if the call is to a <macro> or <glyph>, the element can contain a <range>, <set> or <line>, or a fragment of programming.

Attributes

name
Required. A name: any sequence of letters, numbers, hyphens, periods; no spaces permitted. This must match the name of <param> in the <function>, <macro> or <glyph> being called.
value
Required except when content is present. Any value or expression. The value to pass as a parameter.

<with-projection-vector>

See <set-projection-vector>

<with-round-state>

See <set-round-state>

<with-single-width>

See <set-single-width>

<with-single-width-cut-in>

See <set-single-width-cut-in>

<with-vectors>

See <set-vectors>

<xgridfit>

The root element of an Xgridfit program file.

Namespace declaration

This element must contain the namespace declaration xmlns="http://xgridfit.sourceforge.net/Xgridfit2".

Content

One at most of these: <glyph-select>, <infile>, <outfile>, <outfile-base>, <outfile-script-name>, <no-compile>, <legacy-functions>, <pre-program>. Any number of these: <constant>, <alias>, <variable>, <round-state>, <default>, <control-value>, <function>, <macro>, <glyph>, <xi.include>.

Attribute

xml:id
Optional. A valid XML ID, i.e. any sequence of letters, numbers, hyphens, periods; no spaces permitted; and unique within the program. This ID may be used if the <xgridfit> element is imported into a file using XInclude.

<zone>

A zone to be shifted by a <shift> instruction.

Content

None.

Attribute

zone
Required. Must be "twilight" or "glyph".
xgridfit/docs/Gentium_period_hv.png0000644000175000017500000001237210751522252017031 0ustar peterpeterPNG  IHDR6u|sRGBbKGD pHYs  tIME'pgʞzIDATxOh[מwH͔<"bhM,BRAqJq!p"ʦ,Z{1̦bgӘYB%xO1E&WP~]5!,ssu}e_&תI|{m۶5==mL[Lz]LjIyE$ ;_0"[$)F[hmI~[Hl`2Kuh -nKbS(C[hmѫ-`̈́T@[hmѧ-$6*sssKb3bJQb]`Yض\Q$aq. "a $5&i0`I[Æ FI .dfIyy%) b5R 6Hڙ,@l,}S}C2];Hj+뿅)7< A *א֪S][kY|E# wX :`806O2O.In/ED3m5R%8ĒJ%10Iڲy5Tb[3h:[[;!h ʱ֞WKE yUINm̈́GZH6YNjpf]֫`f>3M5}B%y֢/$vBtfE{ӣ$֢K )_LI]tǔJő[4lEub;|@S r{9R,3>-$b|yyCBcA[n,m&5^sJnqI-7O@lVjsKm}*?ՖJ81VH z&~8SkEn'FFeؠW&87QTn?//b08n??Ǭh'$6IJ>ir了=]:-^ !5|VRkEnQf^lG[5;7k]> 7z)p FID 6CpNl}̚7[jV0Ʀ)~FKPӅ漑wۼ46r už|59`fMDvf[$U@lZl .x'YnӮp+8iBMֹNBfrsK-3Aj;MXBOb# w8R[f>#"۲Ȉ,ZN_@fteyZuԂe|ɋؠRmܔ**$yO_8㔢5JQ۶Kj3 tۈ{{=dbѶ0T-)K uKd 3 "bk﫵9LvZŢmřg{pHJ/DDr z;+]fߙY)h8y~Z-[&E=*/I^>q11N7|Ԓ/S"y}<zƣWR?AD(ov>̉ Ik !6H-* ̀Ffߙu P:|W}#jrClM)nޙQIj;/SԐbMkk!I_1Og?3HlЉVtIA_Zs/҅!{ȳ3yDVʭ[t ZZ8U/{V t% [ԟ1ΦgIzem!7JўZS/St C5.Cn6ĆHl\`HԦ׾ƶ%\=+70OnbYqr;z04ATc<|8gI&7{gԛɫƴŤLm! eU JmwXre87@mjuy{TjW\KfYNjZa{RSacR3I̴-ζTo S]Q{pD:75ܒQ|HMg)NpO>3m hQRJ}` Sjt/Ѱ'%Қ_r3Aj&}fh -fيHG9ȅ> {tG"gfߙz},OnR^S9RΝǐby!H.Lt4c+9cR|JI&.AD>Fnho Ik @OnM%j̑ۧrA0+&j՝<4 Z-:Ãk[RSٹ>ؘ /5UM(bVtVnR~ 'MDYCZtDI;aXI_β᪤ʢ\]:;PbObvejJβ)Dؠ)3B)GJmּ4;ɝIm&\X(/ '/\"nI-4)wڜ ^ҶmD9pff{ZHm_qϬ㎟R,^0!}}Zﳽ}֌u};}Wrs ,01!&&[&x.rrT]Jhˍ\}R 6joSM %FpV]b) (ErYivcؠ{ ZgdQb8/R!:Axik ړZȲOŹ Joa[̂}TY)piH-4+R3HlWyJӣX[h)} &a#%0~H5߸M(E!ؓ/ܠ5cl!6H,&@lH 51R&q8{\MjFyÒHdWa+Cb$5hOn")£Tc:{hVRnf>ī-bb+% I-TZZIM]{~hRs'5uxlzh{l-T' encl&}flKbSpd+Jb@$$5%\JjOn&7>3qRS;6>Ju+0&(EC5 G89E$Rt/vhKfn9 ^Ie6J.P?R)% u)!Ӛ[jpPi EԐZR#L_ZJmP~FRaJsUZWQjϺLhRpc$.ȫ㤵pNmߡη0 $._wHjݧ#3$ӏ$5}:l/MmH-L[Æ:[aǎA ?mUغDh*%k'8tIk~%#2@lIm-CԢ[f7/CN)$7Ѓ6a )2&điMR+1$+;kIJ"59RĄV_ Z~HlPxn=Jm&&bZb@nGS5NbՄ[IVOGcG 1m -V&RtUR+]Fj@bKtI:PZMOq6%5[MV 61~j<ۡX6]7|ý3ӑ<;㽷2GoM;=~/of؊E6 Ùʕ+嵾>O.˯٧Oo7E~͍ciТ=f]l?lu~~W4{<)pJz 3y~](E b=JfJnIuVRi&$K KP}m X81Mfwx2d#iv[-;3%50aV4t{mWWBmCDd`Qnʢڡ'U!4 O+ci$KV DV76o)"H^Y"b~*~/H>'Arݷ>Tb[xҞx$ϩJoVKE،qWo[pJ-'Od ^ NSaέEn.e G6U$&Jv| ^ͻӔLn""Ձꢺn6+676dIyܓ'G65KlnUǹi n7ylaow%jq(T7O,fw%* ڼRr$'8gnnk!MI;-7wzsKW (E%>nm^ r Hl%5oY7Jj@zTj޲4)Rs'7^-@lВԼeiR-Ky4[tnX4[q&-M5„l]P[Z:L|JQĦ<~LHkjKkx]Hl@b@l  6@l G/Æ 6 6ɤְ!6@l  6]XŢm f6'˭[""Ţ (m۶m1kzzژ]S(v2/>0^[ 6bF/.El@ ?`.PIENDB`xgridfit/docs/types.html0000644000175000017500000002501210736451601014703 0ustar peterpeter Xgridfit

Number Types

The TrueType engine provides no facilities for conversion between number types and no type-checking. If you pass a negative integer to an instruction that accepts only unsigned integers, you will receive no notice of your error before your glyph program crashes. You can catch many run-time errors relating to invalid numbers by testing your font in Rogier van Dalen's TrueTypeViewer.

Xgridfit does distinguish several different types of number literal, and it does prevent your doing truly outrageous things--for example, using a fixed-point number (which normally expresses distance on the raster grid) to index a control value. But as TrueType does no internal type-checking, a program compiled by Xgridfit does not do so either. Xgridfit will not catch an error that cannot be caught at compile time. So while you can't do this:

<point num="2.5"/>

You can do this (and you will get no error-message, though it makes no sense):

<variable name="p"/>
<set-equal target="p" source="2.5"/>
<move-point>
  <point num="p"/>
</move-point>

It is largely up to you to make sure the numbers you are using are appropriate.

Integers

Integers present little difficulty, since it is generally obvious whether a number may be signed and if there are limits on its size. At present Xgridfit does not distinguish between signed and unsigned integers or between integers of various sizes. This may change in a future release.

To represent an integer value, simply type the number with no decimal point, e.g. "-64," "23."

Grid distance ("F26Dot6")

There are three ways to write these numbers. One is as an integer, in 64ths of a pixel (the smallest unit this kind of number can express): thus "32" is half a pixel, "64" is one pixel, and so on. A second way is to type a decimal point anywhere in the number: "0.5" for half a pixel, "1.0" for one pixel, and so on. A third way is as a number with the suffix "p": thus "1p" is one pixel, "1.5p" is one and a half pixels, and so on. These numbers may be signed: "-64," "-0.25," "-1p" and so on.

Note that, if you write F26dot6 numbers as decimals, the number you write may be rounded to the nearest 64th of a pixel: for example, 1.1p comes to 70.4 64ths; Xgridfit rounds it to 70/64 (= 1.09375). This is due to the limitations of the TrueType engine; it is not a problem with Xgridfit.

All arithmetic operations return F26dot6 numbers. You should keep in mind that the limited precision of these numbers constrains the kind of math you can do in Xgridfit and the TrueType engine.

Vector-setting numbers ("EF2Dot14")

These numbers may be written either as integers between 16384 and -16384 or as decimal values with suffix "v" (e.g. "1.0v," "0.785v"--the zero is needed for validation). For further constraints on these numbers, see Vectors.

Control Values

To work with control values you must understand three distinct numerical types. When you set up the Control Value Table, you must supply numbers (signed integers) corresponding to the units of the grid on which you designed the glyphs in your font:

<control-values>
  <control-value name="baseline" value="0"/>
  <control-value name="lc-round-bottom" value="-23"/>
  <control-value name="cap-round-bottom" value="-27"/>
  <control-value name="lc-x-height" value="850"/>
</control-values>

But before any of your programming ever runs, the TrueType engine converts these values to grid-units ("F26Dot6" numbers), whose exact values depend on the resolution at which the font is now being rasterized (measured in pixels-per-em). Finally, all control values are stored in an array indexed with unsigned integers.

Xgridfit encourages you to access control values by id; indeed, the distance attributes of <move> and other instructions will accept only these symbolic identifiers, not numbers or variables (this is so, at least, if you validate with the schema). But the index of a control-value may be retrieved, if wanted, with the <control-value-index> element:

<control-value-index value="lc-vert-stem" result-to="v"/>

where value is the name of an entry in the Control Value Table and result-to is a variable in which to store the index.

Xgridfit converts the name of a control value to an index whenever appropriate: especially in the distance attributes of the point-moving instructions <move>, <diagonal-stem>, <mirp> and <miap>. When passing a control value to a function it is the index that gets passed, and in any expression involving operators, the name of a control-value resolves to the index. (Thus a shorthand way to get the index of a control value is to put it in an expression, e.g. "lc-vert-stem + 0".)

When the name of a control value is used in an arithmetic instruction (including <set-equal>), it is the value that gets used, not the index. The name of a control value can also be passed to the <set-minimum-distance> instruction, and in that case the value is used, not the index. The same is true of <shift-absolute> <set-coordinate>, <move> with pixel-distance attribute, <set-control-value-cut-in>, <set-single-width-cut-in>, and <set-single-width>. If you need the value rather than the index in an expression, use the control-value operator with any expression that resolves to an index into the Control Value Table:

control-value(lc-vert-stem)      <!-- The name of a control value -->
control-value(0)                 <!-- An unsigned integer -->
control-value(baseline + 3)      <!-- An expression -->

Expressions

Expressions have no type, and, except where the schema forbids it, can be used to express any sort of value at all. The schema insists that only the name of a <control-value> can be used in the distance attribute of an instruction that moves a point; but even here you can use an expression if you don't validate: the attribute distance="2.5 * foo" will be acceptable to the Xgridfit compiler, if you can justify it to yourself.

xgridfit/docs/vectors.html0000644000175000017500000003062010736451601015225 0ustar peterpeter Xgridfit

Vectors

A vector is a direction represented by a line. The TrueType engine stores a vector as an x,y coordinate pair--that is, as one end-point of a line. The other end-point of the line that defines a vector is always at coordinate 0,0. The actual location of the line is not so important, however, as the direction the line defines. Vectors stored by the TrueType engine determine how measurements are made and how points are moved.

The TrueType engine maintains three vectors:

  • The freedom vector. Almost all the instructions that move points move them along (i.e. parallel to) the freedom vector (an important exception is <move-point-to-intersection>).
  • The projection vector. Almost all instructions that measure distance (this includes almost all instructions that move points) do so along the projection vector.
  • The dual projection vector. This is usually the same as the projection vector, but when it is different it is used by the <interpolate>, <measure-distance>, <mdrp> and <mirp> instructions--also by <move> when a "relative-to" point is present.

Most of the time the three vectors all point in the same direction, with the result that it is easy to visualize how instructions that move points work. For example, this code

<with-vectors axis="x">
  <move distance="left-sidebearing">
    <reference>
      <point num="a"/>
    </reference>
    <point num="b"/>
  </move>
</with-vectors>

moves point b along the horizontal freedom vector until it is positioned the rounded distance "left-sidebearing" from point a (the character origin at 0,0), as measured along the horizontal projection vector. When measuring the distance and moving the point, the TrueType engine treats both a and b as if they were arrayed in a single dimension, and the y axis did not exist. These images illustrate the effect of the move:

before move of point b after move of point b

The freedom and projection vectors need not match. In the leftmost image below, the glyph program has moved point a, which defines the top of a serif, up to the nearest gridline. As a result point b is too close to a and ought to be moved up by the same amount. But moving it straight up would alter the slope of the diagonal line whose bottom point it defines. The solution is to set the freedom vector to be parallel to the diagonal so that point b moves along that line without distorting it. This code will do it:

<with-projection-vector axis="y">
  <with-freedom-vector to-line="parallel">
    <line>
      <point num="b"/>
      <point num="c"/>
    </line>
    <shift>
      <reference>
        <point num="a"/>
      </reference>
      <point num="b"/>
    </shift>
  </with-freedom-vector>
</with-projection-vector>

The middle image shows the result of the move, and the last image shows the same area of the glyph after execution of <interpolate-untouched-points>.

before move of point b after move of point b after move of point b

Notice how the curve that joins the diagonal to the serif is preserved even at 16 pixels-per-em. An anti-aliasing program can give an impression of this curve, as in the image below, which is enlarged 8x.

before move of point b

A vector has a direction, though this is rarely significant. When the vector is set to the y axis, it points up; when set to the x axis, it points right. When set to a line, it points from the second point in the <line> element to the first: imagine an arrow on the first point.

Instructions that set vectors

Instructions that begin with set set one or two vectors, and these remain as set until another vector-setting instruction is encountered. Instructions that begin with with set vectors that apply only to the instructions contained within the with element.

Instructions that set the projection vector, freedom vector, or both may do so in any of four ways:

  • by including an axis attribute whose value is x or y.
  • by including a <line> element as the child of a set instruction or the first child of a with instruction. You may also include the to-line attribute on the set or with element to indicate whether the vector should be parallel or orthogonal to the line (the default is parallel).
  • by including the attributes x-component and y-component, giving the x and y components of the point that defines the vector. The sum of the squares of these numbers must be 1v (or 16384 if integers are used). It would be difficult to calculate these coordinates on the fly, so this method is chiefly useful for restoring saved vectors.
  • by doing none of these things, in which case a set instruction attempts to retrieve the required vector(s) from the stack while a with element only saves the current vector(s), executes the instructions it contains, and then restores the vector(s).

<set-vectors>
<with-vectors>

Sets both the projection vector and the freedom vector to the same value. They can be set to "x" or "y" via the axis attribute; to a line by including a line element as the content of the <set-vectors> element or the first child of the <with-vectors> element; or by passing "raw" values via the x-component and y-component attributes.

Xgridfit looks first for an axis attribute, next for a <line>, and finally for x-component and y-component attributes (neither is used unless both are present). If it finds none of these, Xgridfit prints a warning and attempts to find the values it needs on the stack.

The "raw" values passed in via x-component and y-component are constrained in ways that make them difficult to calculate, at least in a TrueType program, but the x-component/y-component method is useful to restore values that have been saved via <store-projection-vector> or <store-freedom-vector>. For example, to copy one vector to another, you can do this:

<variable name="x-comp"/>
<variable name="y-comp"/>
<store-freedom-vector x-component="x-comp" y-component="y-comp"/>
<set-projection-vector x-component="x-comp" y-component="y-comp"/>

But because of the way these instructions can leave values on the stack and take them from the stack again, this is easier and more efficient:

<store-freedom-vector/>
<set-projection-vector/>

When setting vectors to a line, one or both points in the line can be in the twilight zone. You can include a zone attribute in the <line> element or one in either or both <point> elements. Include a zone attribute in the <line> element if both points are in the twilight zone. This is the same as including an attribute zone="twilight" in both points. If only one point is in the twilight zone, include the zone attribute for that point.

Attributes

axis
The axis to which the vectors should be set. Permitted values are x and y.
to-line
Whether the vectors should be parallel or orthogonal (perpendicular) to the line being used to set the vector. The default value is parallel.
x-component
The x component of the vector to set. This has no effect unless the y-component attribute is included as well.
y-component
The y component of the vector to set. This has no effect unless the x-component attribute is included as well.

<set-projection-vector>
<with-projection-vector>

Just like <set-vectors>, but sets only the projection vector.

<set-freedom-vector>
<with-freedom-vector>

Just like <set-vectors>, but sets only the freedom vector.

<set-dual-projection-vector>

Like <set-projection-vector>, but the dual projection vector can be set only from a line, and it uses the original positions in the outline of the points that constitute the line rather than their current positions (assuming they have moved).

The dual projection vector is not used by every instruction: just by <interpolate>, <get-coordinate>, <measure-distance>, <mirp>, <mdrp>, and <move> (only when a "relative-to" point is present). This vector lasts only until a new projection vector is set; then it gets canceled.

One or both points in the line may be in the twilight zone. See the explanation for <set-vectors>.

Instructions that store vectors

<store-projection-vector>
<store-freedom-vector>

These instructions store a vector as two numbers, an x-component and a y-component. The x-component and y-component attributes, if given, must be identifiers for variables:

  <store-projection-vector x-component="vx" y-component="vy"/>

If variables are not given, a warning is printed and the values are left on the stack, where they will be picked up correctly by a following set instruction. For example, this code sets the projection vector to be the same as the freedom vector:

  <store-freedom-vector/>
  <set-projection-vector/>

Note that a with block will not pick up the components of a vector from the stack.

Attributes

x-component
The x-component of the vector. Both the x-component and the y-component must be present if either is present; otherwise the one that is present is ignored, and the two components of the vector are left on the stack.
y-component
The y-component of the vector.
xgridfit/docs/o-bottom-unrounded.gif0000644000175000017500000000364410643720040017101 0ustar peterpeterGIF89ap,A1H7Q ',P܉P2ʜRQ[r//,֑>qwnf|^/6wujhe_\~WT|PMUJ[kkn˗pzcrNs{Q%G$E#x-!L0_Az . zàe&[o}6)!CVuz5N%T,FZPD&96a/Z"wO{/I<,y%F 42k!@ 6&rB $oHKPlX@_Ύlͽb0^m݁<jz!JUVsۉwpJּxvOwww{Ђ(h& F(VhfA~aW5"'T* liU[=ԈhhbJ%jUxT@n"$]C U4㒆cn)J9xWZVQLxIF#eU j;[&s&`”g dyܝx)(]ˌ1$:fRw9icGXH&ёJ*h^w)+"c8*əڜ#颠zh; +:k&W+ڬ[Hjk-ސ&k&d2J>cRK궊m˯:m CzoL0|.6 1_\ho2Vvrr2"-tQ~MC=GsKaM;A5ntoFH4do5gYtYe3= ,v}4<27IwyM 2Lx7^rr3s9|92J⤃9<.ࢷ.ŅW⌯ͺ;߾{#AG/Wogw'lɞ'9:Ŀ/eo}˷_:rcTЀ 8څx+@.pZl.xO'E}Oc ;@͡0 RP IC }iS 滤mcİCkZהhEQP@HLJ_ +H|rO52Hцt\"%r'FЂ!'C@^pa=!$GE>ҁvb 56qp$"uITta(8H2ޠ@,eUz5%()sB29( 3)X17Iґش6'͵}>|d6Rm^OA!Vf6@g'Kz>Z>KLT`hy j }шE`F y 4(M)( =f'89,bkjSƔ$%2[ C EQ]T:u;b9IY42թ)ʤBՖh%8Od=k*UzrMoצPJV)5&՝u`yXՈj-ka W6c-g YZbRjCW?Xv5%"iKԬR57ۦvŪi_IӶŭc]3|'eѣvVi(u{6ltt+Y7ġz ;xgridfit/docs/arithmetic.html0000644000175000017500000002246710736451601015703 0ustar peterpeter Xgridfit

Arithmetic

Xgridfit has a number of elements corresponding to the arithmetic instructions of TrueType. While it is generally best to use Xgridfit's expression syntax for arithmetic, these elements may occasionally come in handy and so are mentioned here. The <set-equal> and <round> elements are especially likely to be useful.

Arithmetic elements generally have one or two attributes for operands and a result-to attribute for the place to store the result. The result-to attribute can be the name of a variable, an entry in the Control Value Table, or one of the graphics state variables that can be written to. If one of the operands is missing, Xgridfit assumes that the missing value can be found on the run-time stack. If the result-to attribute is missing, Xgridfit attempts to write the result to the operand that normally appears on the left in an arithetic expression. Failing that, Xgridfit issues a warning and generates code that leaves the result on the stack. The behavior of an arithmetic element is somewhat different when it is the child of a <formula> element.

<add>

Adds value1 to value2. If there is no result-to attribute, Xgridfit attempts to write the result to value1.

<subtract>

Subtracts minuend - subtrahend. If result-to is not specified, Xgridfit attempts to write the result to minuend.

<multiply>

Multiplies value1 by value2. If there is no result-to attribute, Xgridfit attempts to write the result to value1.

<divide>

Divides dividend by divisor. If result-to is not specified, Xgridfit attempts to write the result to dividend.

<set-equal>

Set target (variable, control value, or any of the graphics state variables that Xgridfit can write to) equal to source, which can be an expression or any number type that Xgridfit can handle.

<absolute>

Converts negative to positive numbers; positive numbers stay positive.

<negate>

Converts positive to negative numbers; negative numbers stay negative.

<!ELEMENT    negate                    EMPTY>

<!ATTLIST    negate
             value           CDATA                #IMPLIED
             result-to       CDATA                #IMPLIED>

<floor>

Yields the greatest integer less than or equal to value, which is either an integer representing 64ths of a pixel or a fixed-point number. The returned value, if looked at as an integer, is either zero or a multiple of 64.

<ceiling>

Yields the smallest integer greater than or equal to value.

<minimum>

Yields the lesser of the two values value1 and value2.

<maximum>

Yields the greater of the two values value1 and value2.

<round>

Rounds a distance (expressed by value) according to the current round state, applies whatever correction is appropriate for the "color" of the distance, and returns the result.

<no-round>

Like round, but without the rounding. That is, it may apply a correction for the "color" of the distance, but it will not round the distance.

<control-value-index>

Assigns the index of a control value to a variable. Use this if you need to get such an index for any reason, since the <set-equal> instruction yields the value, not the index, of a control value.

Attributes

value
Name of the <control-value> element for which we want the index. No other kind of value is recognized here.
result-to
Name of a variable in which to store the control value index. Only a variable is permitted here--not, for example, the name of another control value.

<formula>

A formula is a block containing arithmetical instruction elements. Within the <formula> the behavior of these elements is modified slightly: when a result-to attribute is missing, they do not attempt to write their result back to one of the values passed to them, but rather leave it on the stack, thus making it available to the following instruction element. Further, while Xgridfit normally issues a warning when an arithmetic element takes a value from the stack or leaves a result on the stack, within a formula this is the expected behavior and so the warning is suppressed. The instructions within the formula should be chained, the result of one operation being used as an argument for the following one; this results in tight code being generated. Example:

<formula result-to="minimum-distance">
  <round value="lc-vert-stem"/>
  <multiply value2="0.8p"/>
</formula>

This rounds the control-value "lc-vert-stem," multiplies it by 0.8, and sets the minimum distance in the graphics state to the result. The original entry in the control-value table is unchanged. By contrast, if this <round> element were not the child of a <formula>, the result would be written back to the control-value table.

xgridfit/docs/Gentium_period.png0000644000175000017500000000430010751522252016324 0ustar peterpeterPNG  IHDRLG0sRGBbKGD pHYs  tIME& zc@IDATxq8a H ۡqU0%l?|`#yf2ߗf׉~yRJ[۶i?V[5W`L^t:Ef@0@0@0,8LLL@0_L{&`&`&`&`BkF0@0@0@0sX3 `>3PΚLLLLy߾Dd#t~J~a„c10aRWMN8N&ry)&ل`3@0ᰡ| k)~AS4d"nsRJѴ`o,N&k92Ƙ~|Wj8nv뙋tyX¯_]h>Vd}5c„!5m9e ]9a{sLe t:ْ}|4 s&!x4uEM9~k5 %MxuG5}_ &G5<M΀ [L)+@z.Lbf^6W4A0@0g(Y]Γ-]]k5+:) ܘ4[r#Xt`&`fr?˶\{cE&`&ȥ~.e˾^t:E}`HC9<&3LDnv-}qz慹.ң1}eG~{E okx]g͘09Ĺ48>5QD0)&7#:5SH"TBH+LLꊨ7}̸c`K &5'kF0@0@0̭9 ֌`&`&`& sLLL@0 &X3 &`Lf@0@0@0L8֌`&`&`& sLL|IENDB`xgridfit/docs/q-no-delta.gif0000644000175000017500000001075510643720040015302 0ustar peterpeterGIF89a *=5M{{Pt~~܀'!Created with The GIMP! ,I8ͻ`(  rO슴p3>[pEj2Z I_7:bH:kM녕㥖}aGN~/Cs?uxrvCz*|2~AA)tCyQ*U)XSUHn]-&}*Oũ0ͬP0ޚ?DI &R4ϥV1lA{Tp9# p3jܸq0"*5%pKJDb2d2`1=S -BqZ)zIӦhQ`Sө`!6XojmRmWnArf҂Uv/#YXʨYz%"9DHLe2N  0[ ]'Xͺ ZS~ ɵd:vko'5q6x+[9kWWj $s-0SQw||Cwvޒj;qфҭWka\|H1 ԽuѦhs\)]xa"Ih Xxt_y*θ)JFaNlMՏ1Ț@Җ^x䖴GD#[GexW ېtzf)7[`X)Q@%Qeo8 ,ۄc*W@Nt:(睈:s;)GI\U(uZꨧ[A@>x"%蜜Z:xb*2_$².# mdKruna;FI~YN*o8%1Zb(uK0a71҈nfif"\ˎy`h0kñ7g!s y&_I$\eT-HHz2L/4 a ec]JsnL m{{qYo6wa&w`.з7EhR4NF+UNy\qy ! ZM:mz 82XgOd 5,˿ \Av9'8ƽ7X™~"&ꉮ%rv{$CJz 1qmLzP\UpYKЅnk#Hnݎ=*A) }tjhCpv:-g8ɦ^99'pH"JHA+ HԢ_G#/pioS#++R"̘8/3+]&zщg)V^ee$60) IȄ1:הV*r-<8n9퍖"fZrTֳzDnkNHQ,4K@r"d*K_BSfGk~k6M]D8(PLa;Y.r<~ttaL-y& 5{T탅 d@V4 ҳ.y)mD{C(q }샟OtfNI3QrM@epOD'%g<%SNO8*^S"QU/X53dĚN[ktP*DGtA˔MpTM̕<]h4{hr5jlLKڕ=,,O2#gىvb4g'+&EX20+e%my#} H;[{ֶmvZ ⵷nX]V_G;v}`uZVDAsCexlm]Oj{!{&vMz͔6+͊W/{WjMI;3*=kK*gxrpN6=qp(O4*4uDjQJ*7xͦ0 []UoEbX eviEDCAĢyoh" #bes]8|n&\ɺ`|r4cؙy Ews13+!5+Oh:z6]]Cg3MhX„dl*zصc0 ]S#un6m@|nnmoWt6ztlbZڦ[CcL;Ƅb{6G Aϻu]t-*oD.'.=&{z\Rv?/d44Qd6^b?n57&?JG3/f7Án42n@@nI7e{Wvc0}Ǵ.3F9WE|qT,77!co |%&?+؁t0Du8(/d.|G{ dB1RG S~1ׂa,CjJat:AUpAXyM(y$+g%u6Z2Vy?wy 1|~Bco"*['lw&d7%Tv dgT(rGeЄp2fe+VN-*uȆpgf& 0ST<"+-w[gmwyz+QGi U~z[·ex;HG 򓍻h*x]p*<5DDȍTsz$%d(u8gV6}ų#49Yy9)Y4!p)#y(+00X/!>Hlb7yu@}ppwj^P!_vrg&?pP<ɕs;{oFNRhHP%ji=$=nI5zr|SXtЉ;c2Qr5uu(HkbW,%9b3ՆՋ( ksw.3ukZTؙ)OEx3)9>FuAf&E)g=ևpsziWfjB9CI9jy[vbyv 똗y]_Iɜ9QJ&ogYl6;Ӕ qilWC5d3e!@Y2VkYJǡse'A,٩kz-ڝ~Y9 6b7:yY)vƘv QpvY >i0q](o6x٥Z0% H:UyFDFQ ћyO_ &ڣ婣j}'¨/ l Ʃ@w^:&Z݉;({9|I)ܹJ]d\zI5Jڪ *4Jiڟʪz Z*ʭʭʣn8ͺyo9WJLqȧoJ'fchfxrk*cd٥BTSw ;kyڤHz"OɲiPKʰxZo*{8笝t fV@!F2*ʣwE{Q\ 7(<碵m@Zvs5 G$9!i[}k$Qʫ|۷2"2q]{FkK1r˺&Kmnz)xG@VRl%k)K+/[3\*^Zýe ha"w&` .[ﻧY;mR.{ d$OehXA γؼ;GG\֏O[K으G%r!+ۡZN[0@sJ"..G(!ó6,@Ꝃ:=ܘH+@L4GTZ\4\qpɡ| d\fZd %gMƦJ< 4KǓ#|,jm$J; z D}cOɚ Ql۾Ty kۦ\+ d쩮8Ō|odž|ÅM6᳜@a|Yp ܼ͗\\lƌșZ0m`@  0`쳩9`*0 @`V9`*0 ř'i -洅 *yGijDC[kK_l/m=̶ЅM,\_b^[X@ 00a 0 `*o͞{Z⹧$ /u=onDCJ)OF / H:jo Ws]!DWa Y\F%f8dx-]yJuWQQKW<K<ԕW ZS&R!Sk[\T_T`@# ZϽM`pLQh` *bq%f/!F:H*p%ze`3 Pom ߛ{lQ:ĴR}@D?Ѯ' HU$Xo߶޽=#RA s'L|QDDz7g[gn&7.se{67j:tbF'OIUD-Py4Ly`m֬cSH_~q,P)c埒fs" a.W4ʟ'@z]IqA$\ TҸhH~shI ^oRw3 :Uet@PatW1e  RULҸh*R ,7P?m^q]Vي6L_Mr1\&Nᮥ.m /]傛 0\2kID-Che1+ sʅU7"6BV mPb!QYL BwbNi:M5[6XBL\uE1)M /čuy5?Q`[dT`XOb VM48Qxq٪I]i~/ +ڝ$jҸ;!F4ӏSØko 1i#@}Z!{瀉0-! /!#L SCp-]]4qw}#]H\q'ǽJ3q }`"z+V $/=7LO\`Xnl6ܟ؜&5*<X/μɶ-(²ރ2K?۸{eeіTL~_'2.h`~7СT`uth^; Sb*~ث\CoȘmm[i}7UD *")ɠ: 0|7BR}U Bx`Cw!Iֺ ݍd \4)u-S xt# 0̩DX*Mi\4ƎU YXǬƫs6Lb@ї7{OoyLxՁ NI"A0m[۳ t/^Pϟ?-H/P#rgw('kߗÑgn|f~5n۱38]H1q*2{ $)IM]' 1jI^lJEU*8!zC?0:ئەnWDDQì U`OZO8) /ׄK>T eHܟ[怉0(q"/ǿ Uxu 7& 0^4G`XVMo*̫Ŀ@0 yՠ=E! Sґ eb0E˅W-ܸj"M0.?\W_6#{ەn2{:Vەm!j5ukw?itT} EFaֿߍׯ YѼi֨~7+*,,*c_\bWa"0 ,Z}Eo&18/XVmT_+æS̷o?[Ħ6IkXmC.q/-իՏmOϥ+/NT^}(M&όA_lo&~ٍ\`:>lZ\ڇGKAO=`@Vr3}ݞ}#rH&c`NlÞA[vUX\v_'K/RhB|f 0$wKk] C&!DNw$һw9fmFx10C,IxZtdl[ `CoQ18B^״uOë޻In$UXK /]T`Wy/6 hxCLi=M0-~9=O`!)@q1VmѷLS*7/i{J)ągڲe s/kptDou[a%5 w`9/mQKt,`Qןv|5T`DD}jV@ 0 njַ@ 0 n+7%P38C[i k+Q8yGCB{hymI5E-I Xgridfit

Installing Xgridfit

To install Xgridfit on Linux, Mac OS X or Cygwin requires GNU Make (you may have to install this before proceeding). Once you have downloaded Xgridfit, copy it to a convenient location, open a terminal window and unpack the archive:

    tar xvf xgridfit-2.1.tar.gz

Now change to the xgridfit directory and install. You may first have to become root. Perhaps sudo will work (as below); but you may have to use su, entering the root password. If you can't do either of these things (or aren't allowed to), you'll have to get a system administrator to help you.

    cd xgridfit
    sudo make install

If you are installing on a Mac, type

    sudo make install-mac

If you want to install the documentation as well, instead type

    sudo make install-all

or

    sudo make install-all-mac

Xgridfit depends upon an XSLT processor. The Mac and most, perhaps all, Linux systems come with xsltproc, part of the XSLT library for Gnome (in Cygwin, you must install libxslt). But other free XSLT processors are available: Saxon version 6, Saxon version 9, versions of Xalan written in Java and C++, and 4xslt, written in Python. Xgridfit will work well with all of these processors, and some have advantages over others: Saxon 9, for example, is very fast when compiling large files, but xsltproc is faster when compiling small ones. To switch from one XSLT processor to another, run xgfconfig with the --processors or -p option and one or more of the following arguments:

  • libxslt
  • lxml
  • saxon-6
  • saxon-9
  • xalan-j
  • xalan-c
  • xsltproc
  • 4xslt

If you choose one of the Java-based processors, you must supply the complete pathname of its jar file after a hash mark. You can supply the name of more than one processor; Xgridfit will use the first by preference, the second as a backup, and so on. For example:

    $ xgfconfig -p saxon9#/usr/local/share/saxon/saxon9.jar lxml

If you run xgfconfig as root, your settings are saved in the file config.xml in the xgridfit directory (probably /usr/local/share/xml/xgridfit). These are global, applying to all users. If you run the program as a user, your settings are saved in ~/.xgridfit/config.xml; these local settings override the global ones. You can quickly restore the global settings by deleting ~/.xgridfit/config.xml.

You can also use xgfconfig to choose a validator. For details, see Using the schema: validation.

xgridfit/docs/moves.html0000644000175000017500000011313211121210707014656 0ustar peterpeter Xgridfit

Instructions that Move Points

The most important Xgridfit instruction is <move>. This may move a point to an absolute position on the raster grid, to the nearest gridline (or rounded position), or to a position relative to another point. <move> does the work of the TrueType MIRP, MDRP, MSIRP, MIAP, MDAP and SCFS instructions. (Xgridfit provides equivalents of most of these primitive instructions, but their use is not recommended except in special circumstances.)

Other commonly used instructions are <shift>, <align> and <interpolate>. These are generally subordinate to <move>: that is, after <move> has moved a point, these instructions are used to shift other points along with it (<shift>), align other points with it (<align>), or reposition some points so that they are properly located between it and another moved point (<interpolate>). Another instruction, <delta>, which moves a point an absolute distance at a specific size, is discussed in its own section.

Some of the following instructions should be avoided in favor of higher level instructions but are here in case they're needed, or in case the programmer wants to produce more efficient code. Such instructions have cryptic names (e.g. <mirp>) that echo the mnemonics for TrueType instructions. Those that are suitable for frequent use have clearer, fuller names (e.g. <shift>).

<move>

Moves a point and, optionally, aligns other points with it or moves other points in relation to it.

The only required item is a point to move. Xgridfit moves this point differently depending on the presence or absence of a reference point (explicit or, in the case of a <move> nested within a <move>, implicit) and the "distance" or "pixel-distance" attribute:

no reference point or distance attribute
The point is moved to a position on the grid determined by the current position of the point and the round state: for example, if the round state is "to-grid," the point is moved to the nearest grid line. If rounding is off, the point is not moved, but "touched" as if it had been moved. In this example, the point "bottom" is moved to the nearest position halfway between two grid lines:
<move round="to-half-grid">
  <point num="bottom"/>
</move>
reference point but no distance attribute
The point is moved so that its original distance from the reference point is maintained. The distance is rounded in accordance with the current round state. Here the original distance between "bottom" and "top" is rounded (presumably "to-grid"), and "top" is moved until it is that distance from "bottom":
<move>
  <reference>
    <point num="bottom"/>
  </reference>
  <point num="top"/>
</move>
reference point and distance attribute
"Distance" is a value from a <control-value> element; the point is positioned this distance from the reference point. The distance is rounded in accordance with the current round state. Here the <control-value> "lc-height" is rounded and "top" is moved until it is that distance from "bottom":
<move distance="lc-height">
  <reference>
    <point num="bottom"/>
  </reference>
  <point num="top"/>
</move>
distance attribute but no reference point
"Distance" is a value from a <control-value> element; the point is positioned this distance from the grid origin. The distance is rounded in accordance with the current round state. Here the <control-value> "lc-height" is rounded and "top" is moved until it is that distance from the grid origin. If the freedom and projection vectors are set to the y axis, the distance is measured from the baseline:
<move distance="lc-height">
  <point num="top"/>
</move>
reference point and pixel-distance attribute
"Pixel-distance" is a distance in pixels (e.g. "2p" or "2.0" or "round(control-value(lc-height) * 0.8)"). The point is positioned this distance from the reference point:
<move pixel-distance="2p">
  <reference>
    <point num="left"/>
  </reference>
  <point num="right"/>
</move>
pixel-distance attribute but no reference point
The point is positioned the specified distance from the grid origin:
<move pixel-distance="2p">
  <point num="right"/>
</move>

A top-level <move>--one that is not a child of another <move> element--always leaves the RP0 reference pointer set to the point just moved. When another <move> follows, with a reference point that matches the point just moved, Xgridfit optimizes the output, "chaining" the instructions generated by <move>. Here is a series of chained <move> elements:

    <move distance="std-stem-left-side" min-distance="no">
      <reference>
        <point num="left-sidebearing"/>
      </reference>
      <point num="stem-left"/>
    </move>
    <move distance="lc-vert-stem">
      <reference>
        <point num="stem-left"/>
      </reference>
      <point num="stem-right-a"/>
    </move>
    <move min-distance="no">
      <reference>
        <point num="stem-right-a"/>
      </reference>
      <point num="stem-right-b"/>
    </move>

A number of subordinate moves may be packaged inside a <move> element. This is done by including <interpolate>, <align>, <shift>, <delta> and other <move> instructions after the <point> element. The parent <move> element supplies the reference point or points for those child elements that take reference points (<delta> does not); in such child elements the <reference> element should be omitted, the reference point(s) being implicit. Here are further notes on the behavior of nested elements:

  • The points and ranges in an <align> element are aligned with the point moved by the <move> instruction.
  • You may include <interpolate> instructions if the <move> instruction contains either an explicit or an implicit reference point. The points and ranges in the <interpolate> instructions are interpolated between the reference point and the moved point.
  • The points, ranges and contours in a <shift> element are shifted relative to the point moved by the <move> instruction.
  • The point in a <move> element is moved relative to the point moved by the parent <move> instruction. Unlike a top-level <move>, a nested <move> does not leave RP0 set to its <point>; rather, RP0 always continues to point to the <point> in the parent <move>.
  • You may include <delta> elements both before and after nested <align>, <interpolate>, <shift> and <move> elements. Deltas positioned before those elements are executed immediately after the <point> belonging to the parent <move> is moved, but before other nested elements are executed. Normally these deltas are used to make fine adjustments to the position of the point just moved; if you omit the <point> element in a <delta-set> here, the <point> belonging to the parent <move> is assumed. The <delta> elements that come after other nested elements are executed after all those elements have been executed: use these to make fine adjustments in the positions of the points moved by those other instructions.

You should use this nesting or packaging feature to build programming structures around the visible structures of the glyph. The payoffs for doing so are more compact and legible program code and more compact and efficient output. As an example, here are the horizontal instructions for a letter n:

    <move distance="fhijklmnt-left-side">
      <reference>
	<point num="left-sidebearing"/>
      </reference>
      <point num="left-left"/>
      <move distance="top-serif-x-width">
	<point num="top-serif-end"/>
      </move>
      <move distance="lc-serif-width">
	<point num="left-serif-left-end"/>
      </move>
      <move distance="lc-vert-stroke">
	<point num="left-right-a"/>
	<align>
	  <point num="left-right-b"/>
	</align>
	<move distance="lc-serif-width">
	  <point num="left-serif-right-end"/>
	</move>
      </move>
    </move>

    <move distance="hnu-width">
      <reference>
	<point num="left-left"/>
      </reference>
      <point num="right-right"/>
      <delta>
	<delta-set size="4" distance="-8"/>
      </delta>
      <move distance="lc-serif-width">
	<point num="right-serif-right-end"/>
      </move>
      <move distance="lc-vert-stroke">
	<point num="right-left"/>
	<move distance="lc-serif-width">
	  <point num="right-serif-left-end"/>
	</move>
      </move>
    </move>

The first <move> block relates to the left "leg" of the n. First the point left-left is positioned relative to the left-sidebearing point; then the points that define the left ends of the serifs are positioned relative to left-left. Then left-right-a is positioned relative to left-left, left-right-b is aligned with left-right-a, and the right end of the left serif is positioned relative to left-right-a. The second <move> block works in a similar way, each element nested inside a <move> taking that element's <point> as a reference point. Note that the <delta> in this element moves the point right-right.

instructions for the letter n

The figure above illustrates this code graphically, the thick lines showing the relationship among the reference points and moved points of the top-level <move> elements, and the thin lines showing the subordinate moves.

Remember that <move> elements are not "chained" inside other <move> elements as top-level <move> elements are. Rather, after a nested <move> RP0 always points to the <point> moved by the parent <move>. One might say that chaining inside the <move> is vertical, from parent to child, while otherwise is it horizontal, from sibling to sibling.

Elements nested inside a <move> must come in the following order:

  • <delta>
  • <align>, <interpolate>, <shift> (in any order),
  • <move>
  • <delta>

You may include more than one of each of these nested elements. Note that the order of <align>, <interpolate> and <shift> is not significant: Xgridfit sets the order in which these elements are executed. Normally this should not be a problem, as it would be very odd if the content of these elements were to overlap.

The <compile-if> element is not permitted in a <move>, but nested elements may be compiled conditionally with the compile-if attribute. For example, one set of deltas can be compiled if a font is bold and another if it is not bold (a "bold" constant, either true (1) or false (0) being defined in the top level of your program):

       <move>
         <point num="p"/>
         <delta compile-if="bold"/>
           <delta-set size="5" distance="2"/>
         </delta>
         <delta compile-if="not(bold)"/>
           <delta-set size="3" distance="-1"/>
         </delta>
       </delta>
˙     

Bypassing the Control Value Table by using the pixel-distance attribute is usually unnecessary. Yet this attribute may occasionally be useful. For example, here is a function that guarantees at least one pixel of space between a character and the diacritic above it:

    <function id="ensure-diacritic-gap">
      <param name="char-top"/>
      <param name="diacritic-bottom"/>
      <param name="diacritic-contour"/>
      <variable id="d"/>
      <with-vectors axis="y">
        <measure-distance result-to="d">
          <point num="char-top"/>
          <point num="diacritic-bottom"/>
        </measure-distance>
        <if test="d &lt; 1p">
          <move pixel-distance="1p" round="no">
            <reference>
              <point num="char-top">
            </reference>
            <point num="diacritic-bottom"/>
            <shift>
              <contour num="diacritic-contour"/>
            </shift>
          </move>
        </if>
      </with-vectors>
    </function>

Attributes

distance
A value from a <control-value> element. If a distance is specified, the target point is positioned that distance either from the reference point or from the grid origin. If a distance is not specified, the distance from the original outline is used. In either case, the distance is measured along the projection vector.
pixel-distance
A distance in pixels. If a pixel-distance is specified, the target point is positioned that distance either from the reference point or from the grid origin. The distance and pixel-distance attributes are not compatible. If a distance attribute is present, the pixel-distance attribute is not consulted.
round
Whether and how to round the distance or pixel-distance. The default value is yes, which means to round it according to the current setting (to the grid, if you haven't changed it). If you specify no, no rounding will be done. To use one of the standard round states, use to-grid, to-half-grid, to-double-grid, down-to-grid or up-to-grid. To use a custom round state, use its name. Finally, any number (constant, variable) is passed to SROUND for the TrueType engine to interpret. Setting the round state with this attribute has no effect except in this instruction: the round state returns to its former value after the instruction is executed. If several <move> instructions use the same round state, it is more efficient to enclose them in a <with-round-state> element than to include a round attribute with each one. That is also true if the round value is to be no: in that case use <with-round-state round="no"> and omit the round attribute for the <move> instructions.
cut-in
Whether to use the Control Value cut-in; or a cut-in value to use. Legal values are yes, no or any number; the default value is yes. If the value of this attribute is no, the value of the round attribute must also be no. (This is a peculiarity of the TrueType instruction set and has nothing to do with Xgridfit.) This attribute has an effect only when the distance attribute is present.
min-distance
Whether to maintain a minimum distance between the reference point and the target point; or the minimum distance to use: legal values are yes (the default), no, or any number. This attribute has an effect only when there is a reference point.
color
Distance type: black, white or gray (the default). This applies only when there is a reference point.
compile-if
The <move> instruction and all its contents are compiled only if the expression in the compile-if attribute evaluates as true (non-zero). The instruction is also compiled if this attribute is omitted.

<diagonal-stem>

Given two lines (making up a diagonal stem), makes the second line parallel to the first, subject to the operation of the Control Value cut-in. If one <align> element is present, the points it contains are aligned with the second line; if there are two, the first set of points is aligned with the first line and the second set with the second line. You may, and often should, set a new minimum distance value with the min-amount attribute. At the end of this instruction the minimum distance will be reset to its former value.

Usually it doesn't make a lot of sense to round the distance when calling this instruction; and yet the default value of round is yes for compatibility with other, similar instructions. You'll probably want to set the round attribute to no; but if you have several <diagonal-stem> instructions together, enclose them in a <with-round-state round="no"> element to turn off rounding beforehand and on again afterwards. In this case, do not include the round attribute with the <diagonal-stem> elements.

By default this instruction does not set the Freedom Vector, since the best setting of that vector varies with circumstances. If you want the Freedom Vector to be the same as the Projection Vector, set freedom-vector="yes".

This instruction is not suitable for use inside a function (though you may do so if the <line> elements contain points rather than ref attributes). Also, I'm not sure whether it will work if the various points are in different zones. It may, but I don't guarantee it.

Example:

  <diagonal-stem min-distance="yes" distance="cap-thin-diag" round="no">
    <line ref="left-left-line"/>
    <line ref="left-right-line"/>
    <align>
      <point num="left-right-b"/>
      <point num="left-right-c"/>
    </align>
  </diagonal-stem>

Attributes

distance
A value from a <control-value> element: this controls the width of the diagonal stem.
round
Whether and how to round the distance the point is to be moved. The default value is yes, which means to round it according to the current setting (to the grid, if you haven't changed it). If you specify no, no rounding will be done. The other values specify one of the standard kinds of rounding or a custom round-state. Setting the round state with this attribute has no effect except in this instruction: the round state returns to its former value after the instruction is executed. If several <diagonal-stem> instructions use the same round state, it is more efficient to call <set-round-state> before and after that group than to include a round attribute with each one. That is also true if the round value is to be no: in that case call <set-round-state round-state="no"/> before and omit the round attribute for the <diagonal-stem> instructions.
cut-in
Whether to use the Control Value cut-in. Legal values are yes and no; the default is yes. If the value of this attribute is no, the value of the round attribute must also be no. (This is a peculiarity of the TrueType instruction set and has nothing to do with Xgridfit.) This attribute has an effect only when a distance is specified.
min-distance
Whether to maintain a minimum distance between the points in the first line and the points in the second: legal values are yes (the default) and no.
min-amount
The value of the minimum-distance setting in pixels. The default value of this setting (1p) is more often than not appropriate for vertical and horizontal stems, but usually needs to be changed for diagonal stems to look their best. This attribute applies only to the present instruction. The minimum-distance setting resumes its former value after this instruction.
color
Distance type: black, white or gray (the default).
freedom-vector
Set this to yes if you want the Freedom Vector to be the same as the Projection Vector. The default is no.
save-vectors
If yes, both the Projection Vector and the Freedom Vector are guaranteed to be the same after this intruction as they were before. The default is no.

<interpolate>

To "interpolate" a point is to move it so that its position relative to two reference points is what it was in the original outline. If the distance between the two reference points is not what it was in the original outline, the point is positioned so that its relationship to the reference points is proportionally correct.

The <interpolate> element must contain at least one point to interpolate. It may contain any number of <point>s and <range>s. Like most other elements that move points, it may contain a <reference> element; but this element must contain two <point>s, not just one.

This instruction may be nested inside a <move> element containing a reference point, or inside a <move> nested in another <move>, and so having an implicit reference point. In an <interpolate> element so placed reference points are needed; the points it contains are automatically interpolated between the <move> element's explicit or implicit reference point and its moved point.

Example:

  <interpolate>
    <reference>
      <point num="top"/>
      <point num="bottom"/>
    </reference>
    <point num="bar-top-left"/>
  </interpolate>

Attributes

compile-if
The <interpolate> instruction is compiled only if the expression in the compile-if attribute evaluates as true (non-zero). The instruction is also compiled if this attribute is omitted.
round
If this attribute is included with any value other than "no," all points referenced by <point> elements will be aligned to the grid after being interpolated. Points referenced by <range> and <set> elements are unaffected. The possible values of round are the same as those for <set-round-state> and <with-round-state>. Note that the value "yes" will use the current round state; so it is usually not necessary to specify a round state here.

<interpolate-untouched-points>

Interpolates all points that have not been moved or "touched" by instructions so that they are positioned correctly relative to points that have been moved. Most of the time you will want to place this instruction at the end of the program for each glyph.

Attribute

axis
Interpolation always takes place along the x or the y axis. If you omit this attribute, interpolation takes place along both axes.

<untouch>

A point that has been moved is "touched." This untouches it so that it will be affected by the <interpolate-untouched-points> instruction.

<align>

Moves one or more points along the freedom vector until aligned with a reference point. Points are "aligned" when their distance from each other, measured along the projection vector, is zero. When the projection vector is "x," aligned points end up stacked vertically; when it is "y" they end up in a horizontal line. When the projection vector is set to a line, the aligned points end up arrayed along an imaginary line orthogonal to the projection vector.

The <align> element must contain at least one point to align. It may contain any number of <point>s and <range>s. An optional <reference> element contains the point to align with. If the reference point is omitted, the current setting of RP0 is used.

The <align> element may be nested in a <move> element, in which case it is not necessary to include a <reference>: the <point> of the parent <move> is implicitly the reference point.

Example:

  <align>
    <reference>
      <point num="left-left-b"/>
    </reference>
    <range ref="knob-range"/>
  </align>

Attribute

compile-if
The <align> instruction is compiled only if the expression in the compile-if attribute evaluates as true (non-zero). The instruction is also compiled if this attribute is omitted.

<align-midway>

Must contain two <point> elements. Moves these along the freedom vector until they are aligned midway between their original positions. Measurement is along the projection vector.

<shift>

Shifts one or more points, ranges, contours and zones by the distance between the current position of the reference point and its original position. Note that this does not guarantee that the shifted elements will maintain their original distance from the reference point (use <move> or <mdrp> for that).

The <shift> element may contain points, ranges, contours and zones in any combination and order. The following is perfectly correct:

     <shift>
       <reference>
         <point num="ref-pt"/>
       </reference>
       <point num="move-pt-1"/>
       <range ref="move-rg-1"/>
       <contour num="0"/>
       <point num="move-pt-2"/>
       <range ref="move-rg-2"/>
     </shift>

But note that all the points are shifted first, then all the ranges, then all the contours, and finally any zones. The order of child elements in the <shift> element is not significant; but this is less confusing:

     <shift>
       <reference>
         <point num="ref-pt"/>
       </reference>
       <point num="move-pt-1"/>
       <point num="move-pt-2"/>
       <range ref="move-rg-1"/>
       <range ref="move-rg-2"/>
       <contour num="0"/>
     </shift>

The <shift> element may be nested in a <move> element, in which case it is not necessary to include a <reference>: the <point> of the parent <move> is implicitly the reference point.

Attributes

reference-ptr
Addresses a technical detail: the SHP, SHC and SHZ instructions can use either RP1 or RP2, and this attribute determines which. Chiefly useful if the RP you want to use has already been set; otherwise the default (RP1) should do fine. Xgridfit automatically sets this correctly when a <shift> instruction is nested inside a <move> instruction.
compile-if
The <align> instruction is compiled only if the expression in the compile-if attribute evaluates as true (non-zero). The instruction is also compiled if this attribute is omitted.
round
Causes any points referenced by <point> elements to be moved to rounded positions after the shift. <set> and <range> elements are not affected. Works like the round attribute on the <interpolate> element.

<shift-absolute>

Moves one or more points along the freedom vector by a fixed amount (expressed in pixels); it does not use the projection vector. The <shift-absolute> element must contain at least one point to shift: that is, a <range> or a <point> element. It may contain any number of <point>s and <range>s.

Attribute

pixel-distance
The distance (in pixels) to shift the points.

<move-point-to-intersection>

Moves a point to the intersection of two lines. Each of the lines must be wholly in a single zone, so if specifying the zone use the zone attribute of the <line> elements rather than the zone attributes of the <point> elements that make up the lines. Example:

  <move-point-to-intersection>
    <point num="pt"/>
    <line>
      <point num="line-a1"/>
      <point num="line-a2"/>
    </line>
    <line>
      <point num="line-b1"/>
      <point num="line-b2"/>
    </line>
  </move-point-to-intersection>

<set-coordinate>

Moves a <point> to a coordinate determined by the freedom and projection vectors. On the rare occasions when you need a command like this one, it is probably better to use <move> with the pixel-distance attribute.

Attribute

coordinate
The new coordinate in pixels.

<flip-off>
<flip-on>

"Flips" a range of points so that they all become either on-line points or off-line points. The <flip-off> and <flip-on> elements must contain a single <range> element. The range operated upon always runs from the lowest point to the highest. The <range> element may contain a zone attribute, in which case the operation takes place in the specified zone.

<toggle-points>

Any of the points that are on-line become off-line, and any that are off-line become on-line. The <toggle-points> element must contain at least one point to toggle: that is, a <range> or a <point> element. It may contain any number of <point>s and <range>s.

<mirp>

Corresponds to the MIRP instruction, but attempts, insofar as it is practical, to separate rounding and the cvt cut-in. You can specify round="no" and cut-in="yes" or both no or both yes, but not round="yes" and cut-in="no". That produces an error-message.

This will take care of setting RP0 beforehand if a reference point is included.

Attributes

distance
distance (from a <control-value> element) relative to the reference point (or to RP0 if that was set by a previous instruction).
round
whether/how to round the distance. If yes is specified, the round bit is set and nothing more is done: so the current round state is used. If to-grid, to-half-grid or to to-double-grid, the round state is set as specified, the instruction is executed, and then the earlier round state is restored. The default is yes.
cut-in
whether to use the cvt cut-in. If rounding is used, this will always be yes, even if you set it to no.
min-distance
whether to observe the current minimum distance (1p unless you set it differently using set-minimum-distance). The default is yes.
set-rp0
whether to set reference point 0 to point at the moved point after the instruction is executed. The default value is no.
color
Or distance-type, or compensation for engine characteristics. Whatever. It's got to be gray, black or white, and here gray is the default.

<mdrp>

Corresponds to the MDRP instruction.

Similar to <mirp>. This will also take care of setting RP0 beforehand if a reference point is supplied.

Attributes

round
Whether/how to round the distance from the reference point.
min-distance
Whether to maintain a minimum distance from the reference point.
set-rp0
Whether to set RP0 to the moved point after the move.
color
Or distance-type, or compensation for engine characteristics. Whatever. It's got to be gray, black or white, and here gray is the default.

<miap>

Corresponds to the MIAP instruction.

As with mirp, it will try to separate rounding and the cvt cut-in.

Must contain one point element.

Attributes

distance
Distance relative to grid origin
round
Whether/how to round the distance
cut-in
Whether to use the cvt cut-in

<mdap>

Corresponds to the MDAP instruction

Will round a point to the grid if the round attribute is not no; otherwise will just touch the point (i.e. mark it as moved).

Attributes

round
Whether and how to round
xgridfit/docs/Gentium_o_fitted.png0000644000175000017500000003507210751522252016651 0ustar peterpeterPNG  IHDR1esRGBbKGD pHYs  tIME$$ ]~ IDATxߍ"UI]Ը⭠9a*E\*]U+I&%d;+\RUMvV\ 2b&Y|Y *Y01".դBy>Otϙjj{zvyyOCc~iv|O؎B7Pr;B0!#JB(1B%F!!PbBB(1B -Z:O!n֐V^q I s' !cbBB(1B!#JBB%F!!PbJB(1B z{2?lvT{$F4㽶\^Zg;#m)/"Qpu؎píp(v;I4J,vlG'Lb&1B@ku_LeA[֑ϷDU`Mӗ&0Be I7&{t(Yfn:B*Mbj"_lTX D$R FN:ԍk:BbH5EYM&0dF(1BlSyͲrY^V)8&F!#GGAQ .M) XƔѠ%0 Ѡ&g{V|Pb \IA4hAwW5/iAOXЛ.ӍLrߍbGEz&9 y$>!=vM8Stttߠ" eAԎ+x =w=y ?Ku wuf9--xOomGOCcѴ {7EӚ&M{}/---ڋ/~R|g!V(5Ma<1۰]$ygܽn=]mHkcq})cR6mBӚe5ؼi?H b&DTa0$bfKKN+œ nE ݴuuchh3L^3&ӛJFuqS-iٱeQtzL>2 |ue4UH\QFNqߗirY}LHɺrUr*4=y,3*E\M`fiY6Sw׭zy*׬1N9b2E&W8ٕ䤮RӗY`Z*ֽ+ M7a5RR+57F2pqrǿT&Z7 ~EV*RVjq;IJJgv墸ʗ讀*;IDユb66P^.LZ` p$M3>.Y\;Iqać5R1}jrk3A|9^L^5o_7I#X*GΝO` ^j:c##B5øqh<؈X*;7/ dּ}!VzJ%]w߽paB5啼n{47?v=\6X뚩E'#awʑRw$5`ӌlwv $L JXDb=r._qK!/5e9M`r٫>N\\Կ^|"n]d&0Tm2])DbrcAv؈,b{ Š25l%yIayYT RX^#s,Sj"2(%IaМ|g8_Ah+5u'}U\ w׭E2E{ySZ jD&cƢ( @R!+!6zOX"HA_yāNTUq,k"J%F9؜t+]ѳQ55B;I8ηg=^fokن=+eA`"~6WI,8=Tv<!JYd퉤BP ">!=-VD,OxҮLkƗ+yf9,ћ~Nq imoWꢳSttt).hc„\yG 4-v3ްkS[&7e>42Mq<݀/}徹G~~l9b;LüyØ9yo{}ޙ|J``B*œ9q@?^|]w9& -K.oTl?[+Vd঳7ixPM*$*/HM+߻p?lC碞H X@X>fad햛 I+Gn ٳ9YRVԬKGf-h9|= X2^s) Lc}fZM[8MaVjc~N!2?Қ*5;YS{*ssQZ[X>QbU¬ƽcco7)*0ilrdKye*U\RhN=~擒|JdLbU¬uo7./ILX+М3:T^k9+2OS%pwҼy&|IL>V|B"KW ӖYHAɊ^9E?6Ny݌|@(;I.0bUdwSYǔ鮨ne4f%RO;QRvX,C,R`ELH/hCS+.Y &1x}\|9{?Gl~֦&}- U̦NIdNEǔU٭dIRcQ`LE$[9-s(jNd^NBʋYNćYE=b9"2zQbF#^:wszgI3㡞C$J`K(vf7oyQ]6=Z=P*:94i}sX-8sW92(Xb!cdW9W)'dVwtDc`a xrtR\&XX12r;bn>4@&SVJc^\`݋'nуgSC&0ՉN\7o}#9s(M K&0S׉L~g }w=X Ҏ1RXx~e7='o.}Ia8qk HayY RX,taEE̅AO輱_Dx14']v'] >Q cFZ{m;QU077㹾>{)+zѼX1 2Y%*ED0ٕ.XUՋ6 E%q--XRbU.0d2>Q`Y(1\<<&淛GN(p"%nono^3 ~łHc<:Y$cenN|-E`+)Afo"EY#Lb:]V5xo|<0( L $ygdw'. >-H}i]Er$֛oG"3iDbZg8אv҄:;;EGGGRz{!^}S,9\}ϒ%3co\rOhJ]l2Lxa]{͙/D5)G_VG؍_lod#m=4~(ih&p\v'znNRY;8zQR1|8жGru?m ~ui-~`H`^JILI]fIl>W4Nh%KcXҘBDMc?:wa)%{$fNJ6oy SqƜЅcNV37R1z뫾m)% 1Jت.Z,YOpmϓ#w)L$Pb>W?a)-?Rz"9g7y16_}OڻnU"?#ĭne1WYTM{Is}GF*KY[jVYnvJbE-^bo)K Ň,,0rue=Jd?rI/vJM]NMU'1)0'꭯6o'Rlؓ=kb2mn011՞r9zOj˲6ޅ|KVX ar)uɦgޏ_,]`j~&?' XksaO Bڍbl죏~ ,>Vj',0"FQ'zQr*bq1)lbhNMuFH K/y,,x*Q*orW¸_DV*PO`O>dY" Yʾ$a [a,0 b劬nդWYQ5]o5 |ձVvvô,;MgUB[q8xpFhJ]L0L8<ƋcDsymŊ5~@;q4L_nBb޺-F ;&TeX%sE#zbu .dBf2l܉vM@W0t 5a^$F ]]B*0u%fFB[iNiL]Wr|p@,#h0AH2;ku0(nG䯻~=zd]g)0Xß"#af'NZE=[#YBZO ԟU!%F!!0:' ֤'Z{ڻzJ,`oޢH']mjTi)HKI ??DFDW_E +IHhr[\ObvOj巈"nyXd%b# 9fg(&ʁ}11"]c2#d qPZ0Lb%>rԄ-l|Xhz5= 4^={'Y$I$@ g8ͷiߓx\CݸcەиFիzI/| %ʛ}}EXJ]L0LsMQ={*&1V~jއ%F.36_~t]$ˠ6(DC1>]ɮT?9˝@{'?׺fXWb!y+2QbϏMIIHId$ՎֹɏWX ?Lc$TJ,2"RĴj)EEz)0j(2y\I,`~$ hy1J!vcc6Ps ~$cb~f -{*^/' -\+cbo|(~a;Joo~*GdMM~.VMX|O7]_gMSE$LɄAd~wjO\j6d7l׋J`rdV L.Qvxr9uzZI2Q\޻@r4bubXՆuL kGD op)*jj#Mw"1/EvWϿyV.b~fm_"nJ| 2_YL9QHҕkOb }K/hӏLD&ӱ17h@ p~dD+Gd*|]#ӝb%0 {ʓh&#dA‹W ZGF4&1Blgs>!$rS{*A,3WN&v'I;Zζ6>1aD!SP G;i yXDƏ(!jRmE;ڠVT%-{BsB̗?rP_^RcKX.!`hG3Ws4uh~JY(vca'$OnT\MMѾa]^^N 9ٕ JVM+8v) ^bl,@ô_XbZ2@y%aמM;h*k8- axgg|-PeaΝ*>:s&嗿DtLԎcǎW^7t,$d+/;lR׷'_ lݰNno+DIE4!Мse T^X5CS_J_DeNYBBt"D2-T$ILaHHȊ"̉:4U/o^~3/ a~+:8wܙMʼn9b{y˾&15-_ v܉-30j?d+ﷻKsAh$1X vvO9"=$ٕ H$1uP_4#I>3Khng6t  b_d!!I܅[GH5!ĆrMn^~r}bN̜ML*/oo7/ٳ dNQb%n$ rP_&"U6^|Hb C63X%iל0 T+/G5 caبT8yy9cd+ԚgIOL*o//a-ÖW^Zɧ>ᾕ}1<ܹr_hIDATIyar <1O&AS\p˶bΕغla3[&>~a;\W\QOaM`r/١)-seW}ʪ)f+vr]w(J^V"ۙ؟M`_C 뗿D!/W :RXAV/;teSWwwH$Mso}ڑi"[mE&2a1Ԃ/5IXcaA0:qm]ӗHd u¸o8@`[mt #I\dLb$0rYR]I?DNp"Y`T#a:ň+gfk#F(0JQC(1odɈ7h>UypzI^.y%&ΜOKĵϳ"Ka_ ܼRX**.eZ3ٸ3tmRPR\+IdžHrkԒΚaz?$eF˗Rߎhh&(0 QºGz {`rؾ;g͵cv]jG,fUł X,&奎EEdزS7/D$FLajXX$e~'yp Z:-BE"GH/h3<ӝO1⸆޴ܖ|̯F7 񸆴ja#.Ҡ6(bh;6+^2k<؈wo M阠 O>2~|e쥳qg"Ӛ'nC&s%bwR;ֽsx+Nt4M!*jGum467BE NluFU\Y[p~PgRg׽407-2}?"A>׺O8:yM/j HJDf%jR5s$"3, Lf3K#I<1gYY?V)1Ef50R*/] rKd82&ޕ'9SsDV.vj6(Dm1tM;Ȝ1R<mK 261A)CĤua+F[i @N sS`;Y)),I,Hp$F䦱Ƨ>_pa}0(nu)-o, yHu'1/So}Odei^Qqڑ&Hc+䕽"b#$x/j}e%ۋPԩij_rH{K(vzX adʔ]af^%22U&17f:;j3K$oYL;>MLaõØv|ZżT)˭Ԯ p{{&}Wci,/_ͭv_.Xu,E2y&0\lmb#&I}-<ܘ$U $JىL i2M~}Š~~a;JZiq\lk,C5S0IaRXыdD;iԥ$$hjQ XXTbnwk,;iNdrҘ>~a;JCMa~TdAbMÔ. \0L NŠOl . ƧLk&[P`&Y0ìR^}~. \@q~6d'JUZD.YMBkw+T(1H`2˾UAr4FSXȩ*a-2+|.%T2iL^"PyҖL`K(;Vf"y9ѰY icy:W@@5u##۝:#V"+&RlS9n?4*NR[[zfi/KEBG*9V9]bVxX%VekE&{ļ,C ~'H4Od\ڍVE6=ޮ+J*P`Bhv"rtg2n-"oB|XCzZd,zrfZ38n@m|Гa jotkڬאN;{&l):::/ q35e4i q7%9''y`AnX3fh=7A~H}6\z l B?8}z!&O,ZLk'vMrh~,\(=nO/ E#m& 4MB8{.NdoLx?g R`UXEFm  Gˍ$0R˴fpRd$$ր#In6)0#up7ۍ p[s*&u2Z6G@}I\C;.oǍtWw_ɨ0, 0,˛z4ROP$Xwzx횲 O,2mTVHq!q90v7-; '|9`e*rLJTQ;"8@>:ɣǍ9"?Bh%()EC%u3]SvE~ޘQdFAjٝT%VLRJ" OR4cuQIn]R#֝yWuMc֌a}TQ$c8QwS;ں:'߉~=Iq#^miKJN4oڵI;*;[|=u6d JdLO^Ȏ ]H$K/}'O~t! ~NQ1'5r%7lT -*:1r U+ܪ$V8Z{̮]Y!ȼ̉*{z ' uY9}ޚŶJ^;w޵S`ޯfWY_]*oui͔4 É9`sows?XY0E5r&RfuSɩ whH`RdN^g0悅K)2Qbe!XȬ.U./f.X#ifVj&~{:Y}=`}t҉ԣ .ԯ=iWiUM_$ 27!VĪ)Y2NZv#)'),؊McvIL"dNH :(dSetII,>$"%F; KMfyTi.ZݻPRRPUU,De&/FR .ʁ}q*;i?e11'۔,EٝTyLL.$F\Mfu9]Oۮi l;1c V*6u]dg/|}aNKכ߽؝ZDyQbޤ1Jêjű! udf}5|٦Վd(2E/a=:zrtFy?'-Kzꘛ:"Q`'VXb6%18Qw";E$Rj'^| ]ȉ;22O7d H,0 FVN*SAv1'Hَs&:!;#-}Nw>z.Ň5  /U}Y ?Gn> LZV.;!-dVue" )/ߺlwU]4ɓ!-q"IT.f|${ȧqH& $SYx\q 鴳ja#r_91 ٹg-;l q+M_gl|S¼yǁ߱}7n\kjǗ7~*_W[spU\>p̝O C 04m& ҝ4MU۝b2ˮ%")2uҞYRVeZGǾH3߂œY->)dQ _Rg'LkƐX+"i-om/9t&/&2J"VÁ-7nf>"ș!ӗ,,QOc@vdE\U(02Mb܁ *&@9n@m|[>ނU–-u+WZ[?3 #}sa9ASUJ˗ƊW%/ҡ^z%F\⸖ru[NFe/4&SW>{ K1[&1E%W1)Lv rr.&oz#6^"yX2)XUҩKj+ep_M`ꘘ:&1 wZp\o`ns{J(1R$j 0^VЬ$U**k'oq/Udވ(-BTdVHq[5ol9PdE%al9-oV"-4.ƫIV]Km%Qds)Lr ^(hޭYm-G_偌]s)2BUcȜT)$8棑Rdv7\E P~-@z-@|pΙsr%sK,R<'g;hIH5]ɶ  KMH7Yms%\d 0H.5[,edfj+d E+_ }l [@U@ :gd^~4m{Mf48VS]7\sinb2sihSci"Ӊ $HWMK˗KNNKJIo*Ҷ6Ҿ}N:͙#͘!ݛ:UWIMMґ#N'=*-[F#pQP^-\)|[ZzzLVI]785Hmm-Xgjo{np9<5kK/5',ommٱC9S_Y;虜ܹ͝o Ϥ2]x쳽Ř1.51}}|;56wȍNM}$m"z%?w 5eSW'ĉ1קeSmjhҞ=TCmLd jjӧMMRgX_{g^26?qw,ɓ҈W aĄ)SmL2,.n5?.?l!_u^JZbpn,1HOvb#[rpTSv k'L '~sL-]&M2=kEa^Po4yRMlڹS/8H^w͞4{vq#[n]a&LM/o/f@d[d (@-d PQ C/ 4@^@ʥE3ljRsM)c$lB!ؒ̕YL0El%r&' [&$"[X4!:.[6 FA>UmQ8[|Se"\d ֟HcÓp-p+f-/$(sy- Y(t9T,܈.Y眙L $JHXf\&i-K$[P [Aɀ <@VVIPEs lB&e*<.]l! F"|G.)i6I9J- Y6\@P%2b K(@l}l,RF@,PR i6w"M;yrO%"[(wܰw ɲ%-fHht $[4¡Te"Iئ֔$\-ȹHʕpo6"[Dh֥2e@P˫ۺLir;,'6 eX6E*$ܸP@qm eI@m%E gSj #ٞ!}l*ڢjC|e}RْhC+!竈G-p9@Ql؅C@Yq=YlIl"\d mlPEl-% x&"@J6jYb~. [Dd.V W$K%" 7 [Dd)-PJ@hѦ;uBV -^f.FI-DM#@6VNA6l#Hqnw:mP/h̜sdX9ŸwO_~4m{Mf48VS]7\sinl;\dC%aɯrLsbI=۾4|t4o曩jk3M.tӜ9Ҍ޽ Gc ~t^-\)|t8Vnpk[.=\UH:jH!͜},wR~\7|#[ JR_4~8_Nmyhlt:| [D JR]scOm PpFnjjӧMMRgX_{g^26?qwHsp Lm357;ZDƍ3͘eܱCZtp/D,n8z%TwRW{{U{;::6=f&۲ld3ҧ綾̦N55{Mjuk0Y_lXѣn.HMw˪c=f>hվ!h 2] 7Uq}PF! ~2Dm^9AVtknGHI%l!؀7e'6ޥN E0v6(BAH-hHߐ2BhlCHbV2Ϙd ?K6}[ iV2Ad!F3F7=#U˴PF-EL, d b3AH RPg( DB!b.ɶ\}ln$܀ANؑ [tR/vрQx=>dh#?zBG2#P>A>D.&- 3@"r3FPՂRBPWv"]D lIeJ@b#@ Dnlu[dTK@7 [R- [dKe@m--)}y]p Jmh<̮e6=1"\;xj%>S#[KFj^ ]-^•+ ?۵k~[:|ӤI矗^{M袼Z~jPd{W^wǗkKSKK\iݺgdˎ ̞mM'OJǎIjNiMjm"/pH~h.\|'v G^_[nqPL*ed[¶GIŋ%Fem6d PA#[;Rd[bG~G"ȵY%K!lM~Rg PD]]{1mjl4-Zd:q|>=0ktҨQ]6m{557K|gss7 rnȑһJǏ;SOIܩg&Nl#DBZ曝9'0=&=4oӘ1^}թ?K?/;}ffM~ӳw4rtyNk8mޜhsf淿|eԷoLBw=}&= Mg֏cwBBY4)׿J'Ԗi|GK[i~GI[Ha;}o0ݎ0G庬HPpD#L uw=7w.Ҟ=TCmL9d ^zE /7iɓ҈Wmؐstay G<4ٙ<ݯ~gMSLm3Yڪ|MҒ%_zirl\7޿u9R:<5k6o_RGd[VC /4}Nnj1uu@)Y9nX}n%8JNIgj6S#ݰzϞ4vl鞑ygp@S q'#Ni۰!HXXٖ7$-Yb.'T7kn635_7!?c&۲ld3nv6gffwe۫ltIE~➶m࿻&^_*ʩi+^y&ܦ_oRvx9 M~|e0`MOn![d T%fR!ܔbmJٖV! HlRq$)vdsZ@Dp\hl m]`Gl@8ؾ@r0-sWƘ]h:FO\Q ! Omd.8#US’jE65[d $nd .`gWPGRm*t p-ɖ2 7'iV ?lHZ-尛y$d lT+g"xn Kd e~̎7H%DHqc-ݲPv&[.Z-#- cȿ0T+M0 [(C ItM)ٖBKKqK'H|)&k'erJ\K><@- ~d[4-- }d -th>-)Eq 6<mBΙYy.Z-@0~?dDB*˶TyVG@|0&ѷn:g![敍TK Yg-sAўd > [SOAe}lڛl;oQF+>ʼnp!X; um:C⦌y 7UIj3֚MwMӦyzwvODg.BI|Ǜl`i8oZ/6:%;&ymڋ\MMSm:FlKxm2mmӥ}t3G1Cڻw{o7͟/-_.uw;uw;-]*͛'=[{Mhi i~?Iz}i*…nwV1Ѧ #mU[+wznd.^תUfw1l~g19RƗ{22޵kS{]ѣ;w]vˡcmo1;3? 7k;w!miy!_tℿ+ BكT>B0.cÃƏnx⿻Np[G~d"-0 ?nSCꤞ#zzLw[<Zm/p(oo۸;I{/AMt|pgI=*$ZRmu7@ +1NhHfٺufGʎ[g6i8_ݬ׿6;vLv׿ڶo:;;"{;BO%;!XX_.OeJ8e Z[ƎxهKfS彦N5ۺ5u-[&O6k9pe<"ZdlYY]-'Ȩݲ"\F 2@,rddXHA-Gp) Zd`L`lhI gMÃ%܌p}T!gIsSek.=ElnSs|FeeH; 8]l\DWN4 Ådy6CQ*d}F-TCQn-ɖQ&a_^N@ђlYHRI61NDlKB3a"݌ӘWEzZ?$[(*M.ud,T- Av))J~jy}/7d[%a;yprJ`f:閥/lQb 0ƋĆ)]!ܒ70MQE**DwHGѝGܡmeI@Dk"lnxtM-PF(;m, 7B*ܤ $ï dR$[L1a6/=`Ed%.K- [@PZ"Zd *fB1IDAT- Yli6T?F(p"o< E0ц@!6buיF4ovӁy #"ΰ~Wx@:t_B[eJ adedngEmm.h?.=, [(Lɇ,!ىd&@ jJbR.d]HN}}N+V]ldX цd.1ctڹj($q/I? ٲ/\RnwiMNIytHȖfOYoF2}ROiӧIŬW$ޮv*@}}z{{/[ tRDHQUlΰ_*~e+gm{ Yl.]yOu'Պmr]dKsIdOZ%Q.r] x- reȞ`5n9Qf> elE€l'4"!]ڷA9s3{}i|ir۩iRi<7+P7E3'UL nA:xkߵKZ:W]%55IG8tl fVWGG%noojMGd_jw 77_gfδeL테w}lhΝf]6rsYxe[K"2rݿRd4nYWp_l ϧ g9g'N~ .0җY2;,'^yRe]ƶÇ'?7Nw!0ᶔ飏-[^N_|oltukݦI==G|r7͛t>z- [066nN%hj:;KPS#>_|;NF:m~w@Pav֯V{Z%X18̒%ҥ֭ǥǽ-|pp)SmL;pMҒ%_ziӮ]L8Ad}}Vc7heKfS彦N5ۺ5u-[&O6sRNekwxKn?|y3Ǜz2Y^xGw/[iݺ=i졇iiqjiɿ=fx>&ܦ_mI>P--@'ԂIENDB`xgridfit/docs/l-bottom.png0000644000175000017500000001035210672600255015115 0ustar peterpeterPNG  IHDRkbKGD pHYs  tIME ,l'wIDATx[u3D*مgJpRr^d!"l{Q4!(67J2%Ң1"D"Sy8aZkśgLR (,RJ)%ƨ56(((( " " " " ((((( " " " " " ((((( " " " " " (((( " " " " " (((( " " " " ((((( " " " " " ((((( " " " " " ((((( " " " " " @,Reɖ@D@D@D)A}zӃ>F n4w@YJPg[55|X`Aۿ'r-v*&Qrr]w믿v'Nl?se~m}:ۼysvmqW\Le˖nݺhnn_~%Ν;mu].\0R#k2dH];8vXlܸ1fϞmMDV.]YfYfźubqhŋRKW5xhЈaÆe/{,DjtҴe˖W_*=/^RJYJ)rJδ; N"3fty_SSǢ XfMDDlذ!zv4GRv˟849=cƌpm;6tqIjvС6mZ?BKmJ!&Rk T~)K9q(5vС}CEjGDٳcÆ ɓ/_H+WL&M'N ':yXc۷om۶EDD]]m_.Uѣ[nI_{w֝5V_\FDQF_uI?4|iÆ t߼O8u-K,飏>9^#G{'y晘l~Θ1cbΝq7[" "56)lݺuiձgϞ8{l5*yxoQ[\QaBh ?"_/DD W)+tQ*7" ((@;\rH]EDPEH@:yEqƥx %r~/ȑ#q3fLL:5|ɸ{K4- [rJ/ut;v;vD}}}*Őۅ bΜ9)":s߭KS4Yn]+R%;v|rեHǏO[nMgΜӧO͛ӭZm5kĀ1.\Ο?ݻ7|͘4iS+o&Rw>HMMM1bĈ/gΜ 80 fvÆ ˹;vHk׮믿>>쳨xBuLE}>h6q8|pL2>tܹ8{llٲ%M<8eѩSfs̉ԩSW^IK.]/ƾ}[on @SxByƴ:M6ѣc߾}1s8p`4hP5kV߿?.\^xb=>}-խo:һxA΂D[DŲ3N\+%"ZBդ*7iZ@LMUS/ܜ5|#ڽX,ۻ}E˵X^ޭX N'nBD"ZjlNoolhauKZkL\{؄bOcr[6J unƱCFX]hZ1+ЀѓP%=lBTj\uQ_^( Wu["qǝL^Mg`U? XM1t753Z2}pj-5FhjՏZ5XЭZ#:^%\ˉ&}1TDQB.Te@slB{])~}M:XP&MP9MY1't 2 i#*T s0CDMDPLxIDM@j0Wu< @)d\DDDDDQQQQQ@D@D@D@DG)"˲ds P,KQBD$ "=)Ke)D'QQJ^s֜qJ\vo7Q6fmw9զ)À>T^DovV;iH)}8mll,xڸ5""і/vnO]+-2MUono6>e!I4\mTV1^v\Ir}mv/n)]aղ]:xYSKc ctof +siBSc5Lfj iT[N5T})z_@/u#=ڱHPys֜}VZh=˅ZnhonвhǺX[ cIORtͱ ^5"ޓm-//׍Qss|~^[͡ H K !{#ttՈ-_S JW/='i¬Wg9ӛTW+VL.SZE{KU{z"95!ED^*z_mB/_~2Rl+M7v zunQFP!-&fD } " " " " " (((( " " " " ((((( " " " " " ((((( @Xf ҇IENDB`xgridfit/docs/merge-mode.html0000644000175000017500000004161311312705275015565 0ustar peterpeter Xgridfit

Merge-mode

The method described here replaces earlier, more cumbersome methods, which do, however, still work. Those earlier methods are described here and here.

If you have used Xgridfit to write all the TrueType programming for a font, the process of getting that programming into the font is quite simple: just run the Xgridfit compiler to generate a Python script and run the script in FontForge. But your job may not be so simple. You may need to add instructions to a font that already contains them, or you may wish to let FontForge's excellent auto-instructor do the bulk of the work, hinting only a few glyphs by hand. If this is your situation, merge-mode may be the tool you need. Xgridfit running in merge-mode produces a Python script that can:

  • Set a font's "Blue" values.
  • Run FontForge's auto-hinter and auto-instructor.
  • Merge Xgridfit programming into the font without disturbing existing programming.
  • Preserve information about the original state of the font so that Xgridfit can be run against it repeatedly without adding redundant code.

In short, Xgridfit in merge-mode aims to serve as a one-stop shop for everything related to TrueType programming.

Running in merge-mode

To run in merge-mode, include the -m option on the command-line when you invoke Xgridfit:

    xgridfit -m -i oldfont.sfd -o oldfont.ttf newstuff.xgf

This command produces a script, newstuff.py, that reads a file oldfont.sfd, merges in Xgridfit programming without disturbing the programming it already contains, and generates the font oldfont.ttf. Run it in FontForge thus:

    fontforge -script newstuff.py

Auto-instructing the font

To make FontForge auto-instruct the font before merging in Xgridfit programming, include the -A option:

    xgridfit -m -A -i oldfont.sfd -o oldfont.ttf newstuff.xgf

Now newstuff.py makes FontForge delete all existing TrueType programming and data, auto-hint the font, and then auto-instruct it. If you have already hinted the font or refined the hints by hand, add an option -H no to skip the auto-hint step.

Programming for merge-mode

There are almost no differences between a program written for merge-mode and any other Xgridfit program: programs you have already written will probably compile in merge-mode without alteration. To understand the few differences, it may help to know a little about how merge-mode handles functions, the pre-program, variables (storage locations) and control-values:

  • Xgridfit functions are added to the end of the font's fpgm table. TrueType functions are indexed, not named, and Xgridfit functions always have higher indexes than those already in the fpgm table.
  • The Xgridfit pre-program is normally appended to the existing prep table, but you can choose instead to discard a font's prep table and use only your own pre-programming.
  • Like functions, TrueType variables are indexed, not named; Xgridfit expands the existing storage area to make room for its own variables, which all receive higher indexes than those already in the font.
  • Xgridfit adds control-values to the font only when necessary; it attempts to avoid duplication in the control-value table by adopting existing entries for its own use.

The Xgridfit compiler knows nothing about the font that is the target of its operations. Instead, the Python script generated by the compiler queries the font and fixes all the indexing in the Xgridfit-generated TrueType code before installing it. The following sections explain the implications of merge-mode's behavior.

Control-values

The default behavior of merge-mode, when it adds control-values to a font, is to avoid duplication. If your Xgridfit program contains a control-value like this one:

    <control-value name="lc-vert-stem" value="125"/>

and the target font already has a control-value with value 125 at index 23, then the control-value "lc-vert-stem" is not appended to the control-value table. Rather, any <move> instruction that refers to the control-value "lc-vert-stem" actually uses the control-value at index 23.

You may have good reasons for overriding this behavior. For example, the x-height of your font may be 1000, and also the width of o. You may want to apply a <control-value-delta> to the width of o but not the x-height, and in that case the control-value 1000 should be in the font twice. To make sure that a value is appended to the end of the control-value table, add the attribute index="append":

    <control-value name="lc-vert-stem" value="1010" index="append"/>

You may find that the font you are working with already has two control-values with the same value; in that case, supply the index of the control-value you want to use:

    <control-value name="lc-vert-stem" value="1063" index="156"/>

Note that if you specify a value different from the one found at the index you specify, a warning will be printed and the value in the control-value table will be updated.

In merge-mode, the index of a control-value is unknown at compile-time. This can cause problems with the <compile-if> element and the compile-if attribute, which may have to decide, on the basis of a control-value, whether to compile, say, a <move> with or without a distance attribute. Before the appearance of merge-mode, the recommended way of accomplishing this was as follows:

    <macro name="move-pt">
      <param name="cv" value="-1"/>
      <param name="p"/>
      <compile-if test="cv &gt;= 0">
	<move distance="cv">
	  <point num="p"/>
	</move>
	<else>
	  <move>
	    <point num="p"/>
	  </move>
	</else>
      </compile-if>
    </macro>

In merge-mode, a control-value index cannot be evaluated against a number at compile-time without causing an error. However, since you can count on a control-value index evaluating to something other than a number in merge-mode, this will work:

    <macro name="move-pt">
      <param name="cv" value="1"/>
      <param name="p"/>
      <compile-if test="nan(cv)">
	<move distance="cv">
	  <point num="p"/>
	</move>
	<else>
	  <move>
	    <point num="p"/>
	  </move>
	</else>
      </compile-if>
    </macro>

If you want the macro to compile the same way in merge-mode and other modes, you can do it this way:

    <macro name="move-pt">
      <param name="cv" value="-1"/>
      <param name="p"/>
      <compile-if test="(not(merge-mode) and cv >= 0) or
                        (merge-mode and nan(cv))">
	<move distance="cv">
	  <point num="p"/>
	</move>
	<else>
	  <move>
	    <point num="p"/>
	  </move>
	</else>
      </compile-if>
    </macro>

If you like, you can approximate the behavior of other modes in merge-mode by including this <default> element in the top level of your file:

    <default type="cv-num-in-compile-if" value="yes"/>

Now a control-value index in the test attribute of a <compile-if> element is always resolved as a number. This number is not guaranteed to be the one actually used in the font. However, it is guaranteed to be useful in validity and equality tests; that is, it will evaluate as >= 0 if the referenced control-value is present in the file, and an <alias> that references a control-value will evaluate to the same index as that control-value. Thus the first example above remains valid in merge-mode if the cv-num-in-compile-if directive is present.

The pre-program

The pre-program generated by the FontForge auto-instructor is quite simple: it disables instructions at certain resolutions, sets dropout control, and sets the default value of the control-value cut-in for various resolutions. By default, merge-mode appends your pre-program to the one generated by FontForge; but you can override this behavior if you wish, by adding the option -P no on the command line:

    xgridfit -m -A -P no oldfont.xgf

Now your own pre-program is substituted for the one in the font (or the one generated by the auto-instructor) instead of added to it.

Functions

The num attribute for functions has been deprecated since version 1.0; it is incompatible with the <legacy-functions> element. In merge-mode, the <legacy-functions> element is unneeded, and it is ignored. Also, any <function> elements with the num attribute are ignored. If your code contains a <legacy-functions> element, you should edit to convert the functions it contains to <function> elements. If your code contains <function> elements with the num attribute, you should remove that attribute. The num attribute, of course, accommodates "raw" code that looks like this:

    <push>3</push>
    <command name="CALL"/>

To keep such older functions, search out these CALL instructions and substitute the name of the function for the number in the <push> command. The Python script generated by Xgridfit will correctly fix up the number.

Variables

Xgridfit uses the TrueType storage area to track the graphics state and to store variables. It has never been advisable to use number literals to refer to storage locations, and in merge-mode it is impossible to do so.

Setting blue values

"Blue values" are appropriate to PostScript (Type 1 and OpenType/CFF) fonts; but FontForge needs them for proper auto-hinting, and it needs hints for auto-instructing. If you wish to accept the values supplied by FontForge, then simply press the "Guess" button for the blue values in the font info dialog; otherwise, you may set them here. Include <ps-private> as a top-level element (a child of <xgridfit>), thus:

    <ps-private>
      <entry name="BlueValues" value="-33 -2 856 873 1358 1385"/>
      <entry name="OtherBlues" value="-578 -553"/>
      <entry name="BlueFuzz" value="0"/>
    </ps-private>

Any entries here are set in the font's PS private dictionary; any existing entries not specified here are left alone. Values for all entries except the one for "BlueFuzz" must be space-delimited lists; FontForge will complain if there is not an even number of entries. "BlueFuzz" must be a single number.

The <ps-private> element is ignored in all of Xgridfit's modes other than merge-mode. Note also that the PS private dictionary is not stored in a TrueType font, but only in the FontForge .sfd file.

Defaults relating to merge-mode

The command-line options relevant to merge-mode can also be set in the file with <default> elements. Here they are, with their default values:

    <default type="auto-instruct" value="no"/>
    <default type="auto-hint" value="yes"/>
    <default type="delete-all" value="no"/>
    <default type="combine-prep" value="yes"/>
    <default type="cv-num-in-compile-if" value="no"/>

Remember that command-line options always override <default> elements.

Saving in merge-mode

When Xgridfit running in merge-mode first reads a font (either .ttf or .sfd) containing TrueType programming, it reads the existing fpgm and prep tables, and also the relevant maxp entries, and saves them in a dictionary of its own. It also stores in this dictionary a record of the control-values and functions it installs in the font. When merge-mode saves the font in .sfd format, it attempts to save this Xgridfit dictionary in FontForge's font.persistent object; if you prefer, you may instead store it in an external file.

When merge-mode opens an .sfd file containing an Xgridfit dictionary, it uses the saved information as follows:

  • reverts the font's fpgm, prep and maxp tables to their original state. Earlier Xgridfit programming is discarded and freshly compiled versions of your functions, pre-program, and maxp settings are merged in. You need not worry about stale copies of your Xgridfit programming getting stranded in the font.
  • keeps the control-value table as revised by an earlier Xgridfit script, but when it finds that a control-value has previously been added to the font it declines to add it again. This is true even if the <control-value> element has the index attribute. However, if you have changed the value of a control-value, the new value is substituted for the old one (a warning is printed telling you that this has been done).

Things happen a little differently when Xgridfit in merge-mode compiles an Xgridfit program with option -c no or a <default> element with type="compile-globals" and value="no". The generated Python script uses the saved data from the previous run to resolve the indexes of control-values, functions and variables; it cannot install its glyph programs unless this data is available. Thus you must always run a script that installs these global elements before you run any script that installs only glyph programs.

As mentioned earlier, merge-mode normally stores data in FontForge's font.persistent object. This can be saved only in an .sfd file, not in a .ttf font. You may, if you prefer, store the data in an external file. To do so, either include the option -F filename on the command-line or include a <datafile> element in every Xgridfit file that needs one:

    <datafile>myfont.data</datafile>

Now the generated Python script will store data in, and read it from, the file myfont.data.

xgridfit/docs/invoke.html0000644000175000017500000003777011354363674015061 0ustar peterpeter Xgridfit

Running Xgridfit

Using xgridfit and FontForge

Open your Xgridfit program file and make sure it contains an <infile> element containing the name of the FontForge source file (.sfd) or TrueType file (.ttf) to which instructions are to be added and an <outfile> element containing the name of the file (.sfd or .ttf) to be output. Now invoking Xgridfit is simply a matter of typing xgridfit on the command line, with the name of the program file (the extension should be .xgf or .xml) as a parameter, e.g.

    $ xgridfit Junicode-Bold.xgf

If all goes well, Xgridfit will produce a script named Junicode-Bold.py. If the file named in the <infile> element is present, you may simply run your script in FontForge:

    $ fontforge -script Junicode-Bold.py

Alternatively, if you're feeling confident, Xgridfit will pipe its output directly to FontForge without saving it in a file. Just include -f on the command line:

    $ xgridfit -f Junicode-Bold.xgf

The script produced by Xgridfit will open the .sfd or .ttf file, add cvt, fpgm and prep tables, add instructions to each glyph, and either save an .sfd file or generate a TrueType (.ttf) font.

The xgridfit script for Linux and Mac OS X takes several command-line options (the long forms in parentheses are the parameters to use if you bypass the xgridfit script, as explained below):

-a value (max-stack)
The amount of memory reserved for the TrueType runtime stack. The default is 256, which is probably generous for most fonts; increase it if you sometimes write <delta> or <control-value-delta> elements containing a great many <delta-set> elements.
-A (auto-instruct)
Auto-instruct all glyphs in the font before installing Xgridfit programming. This option has no effect except in merge-mode (option -m).
-b value (delta-break)
Obsolete, but retained for backwards compatibility. This parameter formerly governed the number of <delta-set> elements that could be pushed onto the stack at one time. Beginning with version 1.11, it sets push-break to twice its value (since a <delta-set> has two values). If push-break is supplied, this parameter has no effect. It has no effect except when FontForge-language output is requested via the option -l ff.
-c yes|no (compile-globals)
Determines whether Xgridfit should compile functions, control values, pre-program and maxp entries (default is "yes").
-C gray|black|white (color)
Default color of rounded distances. This is the setting used by <move> and other instructions that move points; also the <round> and <no-round> elements and the round() operator. It can also be set with a <default> element, and it can be overridden by a color attribute on the elements affected by it. For an explanation of color, see the Apple TrueType Reference.
-d
Run in debug mode. Output is file.debug rather than file.pe or file.py.
-D (delete-all)
Delete all instruction-related programming and data before installing Xgridfit programming. This option has no effect except in merge-mode (option -m). In Python mode (option -l py), instruction-related programming and data are always deleted.
-e
Echo the commands used to launch the XML validator and XSLT processor.
-E
Report the time (in seconds) used to run Xgridfit.
-f
Pipe generated script to FontForge. Do not save it in a file. This option overrides -O, and it is incompatible with -d, -S and -z.
-F file (datafile)
In merge-mode, Xgridfit stores and reads information about the font's state. By default, this is stored in FontForge's font.persistent object, but this can be stored only in an .sfd file. Use this option to store font information in a file instead.
-g glyph (glyph-select)
Compile only the specified glyphs and skip all others. If more than one ps-name is given, they must be separated by "+" signs. Spaces are not permitted. See also the <glyph-select> element.
-G yes|no (init-graphics)
Include or omit at the beginning of each glyph program a function call that initializes variables used to track the graphics state. The default is "yes." This option can be overridden with the init-graphics attribute on any glyph element.
-h
Display a help message and exit.
-H (auto-hint)
Auto-hint all glyphs in the font before auto-instructing. This option has no effect except when auto-instructing is requested (option -A).
-i file (infile)
This is the name of a FontForge source file (.sfd) or TrueType font (.ttf) to be opened by the FontForge script generated by Xgridfit.
-l py|ff
As of version 1.19, Xgridfit can generate a script for FontForge in either of two flavors: Python or FontForge's native scripting language. Use this option to specify which one. In Python mode the default extension of the output script is .py; in FontForge native mode it is .pe. The default, beginning with version 2.0, is py. An alternative to using the command-line option (in version 2.1 and later) is to set an environment variable XGRIDFIT_OUTPUT_LANG to either "py" or "ff".
-m
Run in merge-mode. Xgridfit produces a Python script that merges Xgridfit programming with TrueType programming already present in the font.
-o file (outfile)
The name of the file to be written by the FontForge script generated by Xgridfit. If you want FontForge to write a source file, the filename should end .sfd; if you want FontForge to generate a font, it should end .ttf. It is an error if the filename does not have one of these two extensions. It is strongly recommended that the infile and outfile names be different--that is, that you do not overwrite the file that your FontForge script reads.
-O file
Name of the FontForge script to be output by Xgridfit.
-p value (push-break)
The maximum number of values that a single PUSHB or PUSHW instruction can push onto the stack. Longer lists of values are divided. This parameter affects the way Xgridfit processes <push>, <delta> and other elements that can work with long lists of values. Its purpose is to prevent strings in the script generated by Xgridfit from becoming long enough to exceed the maximum allowed by FontForge. The default is twenty; a higher number may well work for your font. If delta-break is set and push-break is not, the value of push-break is twice the value of delta-break (since a <delta-set> contains two values). This option has no effect except when FontForge-language output is selected with the option -l ff.
-P yes|no (combine-prep)
Combine the Xgridfit pre-program with the prep table already present in the font (merge-mode only; default is yes).
-q (silent-mode yes|no)
The xgridfit -q option does not take a value: when it is present, silent mode is used. The long form of the parameter requires a value, yes or no. When yes, messages like "Compiling glyph Adieresis" are suppressed. This can lead to significant increases in program speed. Warnings and error messages are still displayed. The default is no.
-s value (max-storage)
The size of the Storage Area to be reserved for this font by the TrueType engine. The default is to reserve space for 64 32-bit numbers. Xgridfit reserves 24 of these for its own use (and so this value can never be less than 24), leaving 40 available for user-defined variables. Raise this number if you are likely to have more than 40 variables in use at any one time: lower it if you use fewer variables.
-S name (outfile-base)
When this option is present, Xgridfit produces a separate file for every glyph it compiles. The file has the name specified here, plus the ps-name of the glyph, plus the extension .pe, .py or .debug. If the option is -S Test, you will get files Test_A.pe, Test_B.pe, etc., and also a file Myfont.pe containing control values and other global elements. Note that if the <outfile> element is present (or the -o option is used), the -S option also causes the resulting output to be saved in a separate file. Use the -z (outfile-script-name) option to specify a filename.
-t value (max-twilight-points)
Maximum number of points in Twilight zone. The default is 25, but few fonts require so many.
-T file
Processors other than xsltproc do not have native support for XInclude. If you use one of these processors with XInclude, Xgridfit uses xmllint (part of the libxml package) to resolve XIncludes, writing an intermediate file which it passes to the XSLT processor. Normally it deletes this file at the end of the run. Use the -T option to specify a different name for the temporary file; this will not be deleted and may be useful for debugging.
-v
Show version number and exit.
-x
Skip compilation. Use this if you want to validate a file quickly.
-z file (outfile-script-name)
When the <outfile-base> element is present or the -S option is used, and the <outfile> element is present or the -o option is used, Xgridfit saves the FontForge command that saves a font file or generates a font in a separate script file. By default the filename for this script is based on the outfile-base: for example, if the -S parameter is MyFont, then the filename will be MyFont_outfile.pe or MyFont_outfile.py. Use the <outfile-script-name> element (or the -z option) to specify a filename other than the default. This option has no effect when the outfile-base is not specified and the glyph programs in a script are not being saved separately.

Here are some sample command lines:

    Compiling all glyphs:
      xgridfit myfont.xgf

    Compiling only glyph uni0312:
      xgridfit -g uni0312 myfont.xgf

    Compiling several related glyphs:
      xgridfit -g a+macron+amacron myfont.xgf

    Producing a file to aid in debugging:
      xgridfit -d -g a+macron+amacron myfont.xgf

    Specifying input and output files:
      xgridfit -i myfont.sfd -o myfont.ttf myfont.xgf

    Validate before compilation:
      xgridfit -V myfont.xgf

    Validate only:
      xgridfit -V -x myfont.xgf

Bypassing the xgridfit script

The xgridfit executable is a script for the Bash shell, available on Linux systems and Mac OS X. If Bash is not available on your system, or if you prefer to use an XSLT processor that Xgridfit does not support (such as Microsoft's MSXML), you can run Xgridfit by invoking your favorite XSLT processor directly--in which case parameters have a longer form. Here Xgridfit is run directly with xsltproc:

    xsltproc -o Junicode-Bold.pe \
      --stringparam infile Junicode-Bold.sfd \
      --stringparam outfile Junicode-Bold.ttf \
      --param max-twilight-points 29 \
      --param max-storage 128 \
      /usr/local/share/xml/xgridfit/lib/xgridfit.xsl Junicode-Bold.xgf

Or for Python output:

    xsltproc -o Junicode-Bold.py \
      --stringparam infile Junicode-Bold.sfd \
      --stringparam outfile Junicode-Bold.ttf \
      --param max-twilight-points 29 \
      --param max-storage 128 \
      /usr/local/share/xml/xgridfit/lib/xgridfit-python.xsl Junicode-Bold.xgf

Here is Saxon 6:

    java -jar /usr/local/saxon/saxon.jar \
      -o Junicode-Bold.pe \
      Junicode-Bold.xgf \
      /usr/local/share/xml/xgridfit/lib/xgridfit.xsl

Or for merge-mode:

    java -jar /usr/local/saxon/saxon.jar \
      -o Junicode-Bold.pe \
      Junicode-Bold.xgf \
      /usr/local/share/xml/xgridfit/lib/xgridfit-merge.xsl

Xalan C++:

    xalan -in Junicode-Bold.xgf \
      -out Junicode-Bold.pe \
      -xsl /usr/local/share/xml/xgridfit/lib/xgridfit.xsl \
      -param infile "'Junicode-Bold.sfd'" \
      -param outfile "'Junicode-Bold.sfd'"

Xalan java in debug mode:

    java org.apache.xalan.xslt.Process -in Junicode-Bold.xgf \
      -out "Junicode-Bold.debug" \
      -xsl /usr/local/share/xml/xgridfit/lib/xgridfit-debug.xsl

If you like, you can skip generation of a FontForge script file and pass the output of an Xgridfit run directly to FontForge:

    xsltproc /usr/local/share/xml/xgridfit/lib/xgridfit.xsl \
      Junicode-Bold.xgf | fontforge -script -
xgridfit/docs/Gentium_o_cascade.png0000644000175000017500000011761710744214620016762 0ustar peterpeterPNG  IHDR osRGB pHYs  tIME7y7 IDATxٓ3Ǖ/@}GIZQ377pKtuDD -wc4P].@wCN. r"HfT.#<|, ^\֤_BQɓ䉯e0߉[jgɟޛA~e˰,}_ՕJymnb\x4.0@\i5)PT"rG^NvHm|Gu"x`XP"\ 0_o cLޚK(~%_ {̷ $ӟtaa dt$O買$>Մ#eTa&Ĥ^xJebu 2R0X`}|'W.5)P  Y$RqcO◐6d~|W􏣝U-7R8HyhćR*L8J%Mq$X]7&U߭LGqaF[[7~OޚK(c)/!m|++.ibeDb%'eggZMUvkZ<7Wr |\gie8F+Ea}۸sLkkȌZ;_#b'koME'K|i@_+(T8H\M Xe8IeiAv?wMSwT*Fqjw; 8/wW|S{%~e-R,\Ŏ6cR`{ ?85Tbw.5)PNA.ICf4)][׻Mә(.<]a?kĂ3IlJO<} #,7lyt_\e:]luI&L($n1iIoVeN%ۍq3{twNmo޽lo<nj ]e,9(07'[V gG1@׽0U.W hZZMno\ g/ݿmm`e|W>H^L$t=rw05)ca(.h͏'zuI^}s~孭_<ȫo./\(ro{?DT--noU,Ra, NZ=UӑZ- Vj*2({{Z  eIh˂ȊUծaiY&)f89#u8ΚE&x?EۃrL3I$TYJRвx¶ xQfD⫫?jjuVXl^߫z}<@w:ZuVc-ZXP36Ų&ƶ :j2:1Md2t,S,;57wRy`YX_q"^n[VwBvX+42`5\ιj= ,0Lo, o,M[EƗeeXnYi\#CHXӲˑy9elުa=oMOƲEfn:eLeI܀IܭUo=di 0 C3 0T*v`+0b=HG:$Xv@ݖ$0˞u[`,EQ(8AB![K%qۚJI@'}'GY^ mLޫV ~꩓-3XR.Omޘ R "H҇wi[ZJMon,zRLُevɳ߅+>FYӼT$"ךvvzS `ٱ:AQ%te٠hTfLEQ[X[beB ~?4d}Z[YTzmFoɾ8u߯FwP׵PhV+Dj*3htea{ڏ FW à(zTQ ZUwٍFD"AQZY- bƞě1O^>dY_8aJ-j5~#<#nTUk4VK eVaMMwjQyEQh$ S霈8~YW@$ /=ds cIQLd(ʍ_Sb3jЀt<>J}@*I$VW@4..|}\(e!z+ _뿓D"fc%"1itiXX蓂j NOt9ڏM8?V,-}~i,66r2/5ꪹWv׻76^_sy~>ꪹK߬jy`O})QVWѕ@Z]a<ދ`Y,fe2YEOdmjnL4Mkt0zXE^')AܤyPY⛺!8H(B 1{I`paqo~,;.\f=>vn0fiw{H&\t:e{B!}4O66^#߻q0ǖugW}suGstv:kklm`m-pp9[{{lw+G3E5)*99|{{(;k5lnRe`u_8_tw7֗66^v'%z ٙ[mbN05?o { KpPPoLi/kys[b ?FKTaD-7J,'ˁGyElx\m_/3#߬GGGܓ8-omʲ|YXxy} HzZ&מjsaOhf]lnt$`y{wbO⍙DX7lگԃX[Jyoo'Y~QNOO Y( + ZaØI7͚aTuo<>:xt'?l݀)P t^._YS0==m Yۅb}8lD\s}n-MVV~d/IW׉76^[]/oo|e;;Z_׿~\%5Cӽ $67w8t|,J_aGb+cNM44,+ak67_|QˢORsAԃHVT*ifն[TU-\::7Uu|jfnv,F쓱CiR Rp4cbe+uBVVn<gh[$IJ|s~~EA%˺p@ិ[\|aNJ 0X(\^OEB^ B"RJŽUʣ 6\`pntཽE#;;!8Y) 5AEݐ(v/:VTa\<$@4l?dr}t/; œгF ^J@*M1){03EU~iAbFQ욦jA PTFȊH:8xH#/] y<'(*4 ;l,W*yolry3\wZ~ؙ}0.&h,˩j(e9(v-]$)zմn7\mb綨|VL&5kc$G'jZ-7M$\OH$ a[-xܪhfX̴bf5ry#lcO"hH$VN E4>z=(~Y0 MS2 4MTYVE#TRh'Sx,әc_D44hpkkWF7nm WֳЃ-A A#ܳ,wsH VVz㝝i"ʇ?U>b"yZӾg9.MӁt)B[]Ec{+F fos܁e-SmupA&bo% ۪ssbv% +Phmn _"UQ,'v}>[[c5Mڢ}JBⶶl9Ŏd|^H$yVaspqj_ ;;p.vMoy4E.EfiGВdj\UGMQc,Cvm-Y/>_mcO t:(\μ7")Qb1AU@j%,Ć 0|H8,J jӖlcO"hre]%0BZrHXEi-t( i˲,2M0Nl6I|R\xˆ5^8NDKiu s@y.hPRj1RMqӬ:F K'44]A2&Ʀ7͔e1El"N?0>Ma2.z`AQfU:­ j@Dz-+)J,lԥa8ZD(\^_HIבmІqh9xȿV'88@{"j]4HĚhtqq$@(f_i[VRm_ɜXuxF2MRj6Xv%LO:E 枷MYveZ$zOczn=6&]T 8;{?N> O$20)`YHZ==VUO-È..>4N Iϕ 4Mbp80 ðϝ㵤.`e9BPݮVhHt0E$CA"ǥv#inig*4@)e bZ[3I A|+afִLJF O ޱxM3+ SbQ( cTrycgW(|L{{bE(f0NYQTA e- Ņ cckzUC.`QeѻoRGV(z6{U;qO|dҊFhl~ȥqŅY]\[3heyr4a:}駟 I`0T>VmMp&f a_PsoY#2({{ C벰Nl/\S(?Ngjwſ=>7/~~A0.>Z^^fLze%Kww gtӔ,cy9wwE,/Oom  ?>>nωdW`X,ҊQOaY6VA]='r@F,.~O&׳,&Ėf_8Jtkk5:U;eݮP*T}yA$>/˱,pBQ`aH$"BT"I\kZ.1;!WQN]~uèwnZSt.ϜDS84Lt`!%ө0N)*dM[`]h Z<4-t/FT^PM[ggMR (t$B= ZV~,CQHDe`EjPGhZpFh  g~$xp{2o4L}0e!~\Nf^WH0:7\-sex@:~b},\!rhd/p~n@*c$z景!mr9a%/L QfO^3dm ԵZ\N;f fO$R f3eVyYfFJZTP\ (NY,{ݶ)y#J(Cu h;ɞz#ˁ@ni&j՚dc$ˊ(V=l$ZnOVJ;~wW\wplhBj𼹰0uu3@w]Z<ββu!HW|)Fei 퍍VV|'''(zr9L6MXeIWlpduʡ) 댃l,sv?d䷹ߜiF IDAT8}qzz4X N3#djsʥ筃J^ho-4CAH BS'K/H$++ٝLMӹF?vv077~PD&K-^{ٵaѾc6FlI뒦@ aI%`&\Ӕl-L\TfBX, amC0O74u)( <% e6Q̓Ň $m=4L68U;It *H| H,Tu04Zd>}eR_aY?`u:f3ht&S#M/8 xu.|t$4\0Cۧ4c.I4D4hƤK9"ryuht@KŲ hv4ffrŢ 8{b_zޢieu]nˊR#)R4qDeuuErK,KZQ_t+'3`ٞl "˟27|-gr2eu϶ZԠ)dgX L&]Za0('T8,J$қubr1;+U|$[n$4⋂ |(<͘tryU(\W]9k4`j)LCP`qQ66^~$W~,n4M-GG_U˲HkD|mk & !i4*SSS5^63"v:`P@2ƒDrEG")Ho`q4B71E\y@{m<1ӖUdArL24˲YMڝ(0 UUUUځI7 l=:V(ț@g}&<5&gPp}76 .>;'`g[6ps VptDׯǦ)jMDss07Hd4_0=B(BHz+x"6{qpq3gd2N3<߿8Nk686c`\xLnhweqd[|( YJ5y7H+ O<]nl g77KQ.G\a'gf25P $ZV@QcY(J0dAT91#N`S F`Y6ѩI]>뤪]GhpMh6LzZU'U ]ZzZ$8{J%z^f T7 E˲vkn Ii&m䉘5055R#=qj*ntqq!I-ٳ?7@󸙊ўqOơcc}ROƴaYv[̮~ kT؊DF7eꫜd_d$$v:Hd6?t2bh|:L ǡPQXiSqMlͲI,+ξX(4M2 ^B14 GGZK7nLfh6htq7?pbU=iE]?}/  #W\+ђD.l[<n…x ݆w @v}>dRE lYzpiJ}c>==(<ws`mlK/e2u]95v;hv;2drZf!m0w f 3+{&TlV憤)Ac|"(Ob,+kki4=zH$PCp5O4]30E)6Q*\qfA`Ye5A@2ZUN t9UKRE*S55ih=LMXdEqPv$2/e!q 7agI8 n ʊsNQpa?> f9ektuZ+F9>FɸEl6qvX֌(2WٯG"s_'ٯs\R9.yao3FsSSωbi3weTYFhz`'Py>βLfo湹oD 6L)O=jJ [-ѰQNi%UU JCR4#t)# [=ys$]xYv4i4e#0qh*'Ym45ͮSI↡Jfنii6h DFqm1W$"y"dx|%i<ɲ_QB`iY9]xq,\$N)J0 I)F.E.xY]DJir/--Nm!. 4Raa %IhS #д[,u㽜xeK;@ѣN4P0 Lt:G++\.qzV԰[3,35L3;%Ei*J. j }` ht:9A,ao,(:xF|\sɲ',Ozxj~*Sͺ7KBKKVho1wpҡDOX4"?3FON>r7zPS Z.BGGoj'[~.Z 0,GNN05gf(ةYQw:;e~fk4ͩjƊqHfsټ2v&(&H< Ȑ.B8`9!9,Wc䠖L6 33yOMO>_x_\|˯ 0 'jPf ?ffƜWZ󞑣n!!fc*y6k6Lq Z8z$ݦz}A`pz6DO618NEQ;TG #E[(đUQ>: U!eE,ٲ$Ӭtߏhl %KmuSQ(J >_bdx|{0Aq`5I߉(rVjBJ@8< =q^Ҵ]6F޺yЀkoqV `rx["ZjY-R=›r~ '~W$&a+fQ̅0\XQ|LBHD"AR$y0Mqpqq}W zXE;C?g\fmE"J.Pն ؝aB&Uy벪VF38D05<]aNSNV;;MgnW G.g1]_ad礷t%1Eu4 n9ĂabyKUlsaR%{N+,p hkݣy*BH&3B|F(_mϪխ˙AXac2ggv,|$z(v;ll<$gx>d' [M, @Vf=|qq\.ZHQfS;= ZS: [TDA0}vY#g ,+ɲhSU˲/Z:o|U=o'h`\e!p\_`Ya ߟDjjPRk}oqzv.R/,]*_\dkoT>OmlVKZM9t:U9Z>Ԓ?pCIGGrdF(_?n{K9 ݿf KR @8<0N^wmC:r`PhȑI:=ؚke#"} QQNh: Idi\Kt$*'ҫ0t,km/.>Q.<|"E,Emj;~vcuUmùg~qROTOOv$xzݮ7v%,Me:{=Um۸RtɋK\f_irl:y4'5fc6H$O>9<T,;++Z8;#NKc垽<{OOM=CӳD_\pN!ƺ5)HôZ4瓢IOQa\nGi垷{s@hi.|W̲um"MJeQaz\) pQ<96686 Z(@yLT :K$Zn Yg !I Fl#ՓbhZc0Umj< r6&,$i!:YiAntnw0DE(Jc*0 A;TΠak,,!3lW< |33ᩩ`0e2$x[|+ejSءzYk(`q><*1W|7<;;3xK'[4mC܏$ˍjh|-e!LSL&m Eۅ`OWL+ D'%؎ĞEnE6UU;6f&hHR+sefvlri?:ڽxW-T4ZH&v1oMHR+}!_Q64v5o~ W djtƲw ѓ,Qt7ncn9HYϩuKU[@2|u_86EEqZ-Fp~OMAU1ϣ驾%(VS̲e_=9ѻ݆/.>`&i{ X\R(EQ]0GmUmgeo &*0y{sTnA9ôkZ[ 7la4MU=EykR~JVvUj9WՖ({b{bldfxnXl]F;dfX49e A #R=p͛}p+a>˲ǸmIL S NՃS.ӜiNo3Z ٴPqd JQ.PTRՎJ P PgDƉ&(^ $մeӌtkItu^.o\҆%a(8cXOO(A1S,.:[s|35XÛ?&݆,#AvDVA~> E1+F(_Xv/,j5D"eZIJ MC2[-D"=շĆ ,Rq$IQ:pʖߟ.3ȹ@LP (=|Fȱ  %H0ȧRy.@QTn6 35ueKZ ]\xlڥ޽å%㨽~qAƼ5)&rt$8vg獕WAQi6a0W|~/#_>d֣, :%\aAA;]Bn{Z/O`o5:y'zy?;Fmnl63:݊&tD[gL&8Zm`rŲ:Ee4t ]tbY0Lo'&KLQ}շ |> u]4Ez8*= D,k$ITΚΐK} X.{W`"<ϐ8A\aTuMQꠜb\4 ͉b }fFߟDޯYܙOzgiQ 3`6y<zz@,ߞ|#P+4w0j ¡PvPAQƮHc|V(J}cuEeOژn~xRA31Ǚ<QM(z@QdcA@Q]ne LTa<`Ym4ؠzV+8?8m~ŀyŝn JYuL%ei)[6Bo v^/D"$ t2\][{Y wLS栝.lڠOA\s0-.v=d2C(wtm=) ,˶\K9v Wu,jNS ap ûѓj^4ۭ7hiqp`O/6YpSp*arSl9[w w'<ͦi:\iƞUs'Fne X{!b :x/b`ED_`HqP.azj@+֬TD˜ >;K$ m.9 |BȄ.iwǨJƲ$TUU'bu s1u=U&4M%Lp9k:)C8dYmM *Jlvc09%aFGn[Xe1]5/:7H*<:@%Uh >(\.Q0'*_d2+0R3SA&ݮa@=è:jݛj( aT!& C@ӚDebzae JO$,ו5?X 1L>Ȅ.hj6JUT3N&SŪ^;Mh6!!M?jGX0os/F9D}e& $nd4c^8ck^"qdlֹUL&B6(~n$E[51O@׽Ri.˕{Aw4^O0O ujI*&IryUUy66 71`mm x(쿓 >i4Q5 `],+q Q( BPL4!`۴=CL`^z!@4I̚JQ>m42%), a @b{8% ofWHH& SI,cۺAjGXu]ϳ\$G9D/Mӂv[ hEQ$xO߁kG1݉7<I$#'J0  ҹRXֲe$p !/_7 ۥ1 ]0h3Csxq<3h6!Vm$iӡSA@0v;<]ǶMc4/ 1yHp&.^e|d2Yljry9ʊVx@pM A C Lae `Q=C=]Cl$]mP/$HKS=NSS<6gU*2@T\jnt?֗0?{_MtnU*o.,t ¯SŢmљ*Qzpg6//xnnQS4@.rP 4!.v]Qv]7ln WMv 99LIe2hZcx^Ʋ+A,q\Op[\Yx>ekfYIE,eynswipkYxDڣCʾ$zCpx C$lˋAF;; ^ hu5r-6 c}sR8OZAbDBsWR$i//\sQUp=6,!goo`h`KB7i؉k;=|rGGH,MފA\-f6΢r }Z?<$8WYF#HRyJ]bֶg|<<ܢkBGKu#iq~hݹ,Oִ)*磬O𢨷Z h46^*p*ff&>?ʦn]U騞!LOE9|Ş7ؐ_1rq=6iJ>U,E.%', /@ NyACP a2/%dTꚪ+7o1 jNNYTYwknnw]{@8Nۆn6?U754۽;,Kףf jbܜ(=XXX岎i6K|)GAU%D&$y>\Izi>7uV&'FJL2,I&cYo$ÐC P 0$Vm˲L*g<l۞E5u Hزkk\ӗ+4BqA7*7W`s+  cEOH4lkuY78z˯Vav[ރQ MTY*;zo=!$]nm/VmAR˺L=Y o;ZI,\y< 4ղLvyrŲB#ɯ,@smIZVUPdALaeM11:K:J&\:?k(wk:B5*$ ^sa((b5=z{{07ݝ_OM=]}ϿV hW_ J`V h:h~OC8p:>>yͶXs,I |PpͲ,Rϲ.Q+v6e!4e@.cð"j2՘atGV@kP&L\aY/mM}.*(UOT=OưV'Ϯg< N GXYu]WLTWBƥIri| #q^*i<؊, H-]oߍrEUDVV\߸tBr90+:HE˗qU+7U8H4?ƥQR`a;%]oxgTF{ܽ7ǹ ȇX\.V'QyClC!a~<bEIQ5M ER#hݽloTUvԊU Ht= 8Wv[+'ׯ_Ù4QONOb`l!!dX.ھvv~]t@{h ī쬇jsseqHdRzɽ=MH7VT~r9{?GΣr9ou6hy[`cTE%ǩ$sj~8n@VUYUh46C % fa0 ~mnĂr@?[)&ܫ%8帘/`aa(rissрVk3HdVj7^ l\X _[Z`~J=sO^[x)￿no>-l%i7nz'OIeb;#8>yQ%)'IeϓO(+ےehٶN_ O] ² ln6G@T5UDQu1'(~gf2?~ >Ȅ.ʶk.Rz;) W*qXߖAL'!~8`v&~k,oD!g'ckooO,GL"*oq#R!=}LN(usr| w$H\]}5ꫯrblnW:*a1C6J 2͟>{p𧥥h_}G++6;mn2e=궢diӱj?So4߿h{?,ҥ\BoÿȥE,G.J/KRTQĢVA\u=f[kZ}dyٌ۽Er{Ux~hUmh'Ԛ-L|0 ~ l~wztQBP8}e0G MӣS @BR(X6ฬ5D]?>$1=Nig80#)UK WV~ͮjکAӚAXK{u6 /B!=o4S)aa/F o@t -QoZ nY(eM6uVuwDjzzO?[\N4qR4 @6{Aht XߺA$Dq>VOQRNrtЌ~mkF&lC!>SAGBqq92eЫǁQĠXkbຘbt8N8E0Ø1R˗/ YA=I2T*lBpC,l>!2d {X_`}@a4KGոqpnEac'!wy_qO-62?JOAkjsϮ|Z- ( ,նm5-KAx3Cyo]HU]ru1;ycOsFGrY|ĿKaEq)AFh](u_j(5(#j-P.$ĠXk:Eml: qtHAT䳍J￿JMQX$¯Jt`6[.-bԃbhހJ cH"h A&&A&~y[`U4M&G+8ÊeOf쮪>ftp*5IX80`*k^ZabD8-Tca$QE۶5jqTï\ Cv@ϋ#D`8Ç$h~ ;08S ,`kkIҚt6ȹD.Z|@g)1TCb/2 Iobra vh Uŗͨ̚$y^.:޸lC"e\$E11O 6LMA muSZrD6Zf2fGNMiPy[`([cύRϫdǰbY7ۺ.a $I&BR'u2u0$QUt$ɌaImGaX/q@Y(/ b2zj.`F{Qo~C|[mBיHA\~q{rFc`jwWiaY+V 5yр͟:Pc}@dEm{뭻[qOs}󃐭1 bŵۄ0-}Ҳ 4E(Uf$EN3Di̝%4AzoTiL|0 ~T-d(=KD4M݈+#'zaaa|_l޿&i݅RyD?0{9"V,P[b#\XDZM.+^J8jyvm%Yn%cD@Q #WQA;Sn2MAש/jP9nw:K?]$!IeaIE!ǬD^ժ)ʠ9:Ų a]bq7==0`H*^g(==oe/g<ۉ6Iz;HjQR.t IDATQn-/N\9&$s ߸{'nU*oFM妧 A}a,.B*AѱD;\ӦLQ8SkkmoK3t՚J&4S< :Mrt RD? DZO*<USjQ#hf޾ot]w7.=\s6.9;~ƛjĦw +T#0{ގ-|=4o(JΝ G;2&IE95r/%qa4-y$ F9;$>?P$Isjjujj6$-xbX=0ѫZ=΅Nw18}%[5ދiÜy^(RӴ@ӼatѶ1uGn^?fԲ@U#bPt,1x6C&Gy[x>Zu ۦ0JO08x0Cضi R_aʾ$ɒ$DzYFDҲcvy i6&LΡ!y~G&iYQ1L2,+a.34m?U<:|LxkC8DP`))Y0N'8M1 < =Lďyt]Ӳ;[ql _y^jxzQW~? z폎n^N0:05cAѱD0\E+4Ǖ`hAwTR(#0@`z<h:iZ#&(ÛF$i|0!=Abq 4 \ ~HaD7RFTzp !5PeA$92i4-b8&CLLRVkr(J|z33 "`xAǏ}a=6>Ȅ&/ju$Vraayzz~qQD Ü$5a ~0 f3@xff5I#crxnV 't*8l{U2l&?9vxp]1$@"1X""0droeJ(D1E R|Ѯ+O'WK&{œ J44Kr%,Cӂ(eٯ׫zNlCmGH(^L|/8NWrC ez (33 cҴn%I6 (_{FkQ*0XjF+À^\W Iข H$fQ QaIf LRӟ+0 9J=g "=~s$٧(DK@7e'I&&yr||Ri}aZ&3533>RЀjFC>}­V ZݚN`n.}ppБQy>?Oc!)xfۿ} 0uxPc>EDft'V3NHY$mHI$p08ndr4 aHaa,g '^{ޠ+4sc4i&lh:IӉdr=lm\(ƫw4-%@kf < Qj^u[-sM~>Cn4v/bT&3| ٔd833]t>k68:$=~2Ngf9*Cm'>Ç$_o&vbX f6{-0N v)4!wAQVe<ync8;Ga,ΞN:9qPy K&+{L3[`ѱjQ GRM"E|e!4:"(ino@K)zg+7@ksi%NL(:=u˲3 2 J&Ftp_Y{Ab( MQ N2I=!QQv|}yKK&e5LXv*7Etz۝{yKQ|؀% EMcp@yaȆQKl4ޥli"yI]? T>8hanE H&x^uS˦d 9ZpAn+ܼy,.V%N(ztH<3;{ WtHMc 4s[=&% e/dV\7s.h?!hE!‰DEUף4+Z0)q\r1j|?< snw 9<樞SS+KKܹh6h4ǧq| exxH7>=^fˡGGfAxFF㉚~\{p Wr(V D X6\<<гòSTK8|ikΝm c<ϠEIZ@|[M~Iޞ\ɞGa(ŲeTNQ\"I& /eEANL(H@:-vDgpx:>泵rAZE}SՐ,A< b9Dg229}` EeUMmiaNZnXKNOae%iee3\ny8﹤'hr%@"` ~J&s>U*𢐞< nIDG/ggf\Z3=犿")67>˦ 1zHa- $331梱_GF>4(#ù ́½{P.}h[IvۍK߮T|,^_4x+bqRK@QXy@$$>qn>ҧߕ9.'I+SXHLz-fb{G} fKHiLlb33*VBݐ33+_ qʓJgivK_(*!μ5>Eib j`&9eassܹDs<(%~tB6Y!ZtDT Q,дI]?qoeYſu,wJsfœ -5-7{zɣ[AJ6{4TVçȂ#FDMKq\g2(IA^@JFr%is<Q D)j T4m81&Q= 벮ˆ`,feuLױV\ %uq4I)Jy (w Ie`ۘa>X:bkKi틈=u2L^r]lj۱\nmuBgZZz9{4-^,:?/KtԸDshaV].]dz8>&tMoa<<RU(.c\{NCMfmc$ݿ_F&y>/I(mZQRC N&'Zr\BG5cHSb=jx/|}^9.Gl2{-b~>FݱOdž X)AщDR&n6k:,q٣[ ᣣ<=>p4a~!ӧGaXg4ǵݽ;HN"EQcYNÄj < NqYRw&q$$m,$ H"!Ie3,q4q/ QӠ\I:-UWscYިT?Qy{?u~_|V!rr$cɇ?!l%ҥԷ=7 [ZV QGQXםn6M/-Ydž(8Xh&A EjE]r(ӣzx0bbIץCU;a@p/r [ᄈmu,]={BeP$6ME'bP Ri_J](\  b k7 Д\Q^(F= zqa yReTEK T9R r%]Ct PU8>Ν[`uj*XAQ(pxXOo,V.`bqz:\W;? XP( T 8$9.= "zẌ>+ۋFqQ$bXu]U-A_)|X~=INJrKhp[,>#HHt*[^^t '%F}d2 #2MgI4hL fgg//l Za~>3GPy8vwܾ[!bMՇ^9<]w:zכÑaٛ7? 1r\đ.eRXBAn o@.gӴG.I'3.Imzzw{v{W 6eHAA@be@(y8vq OLk&I'h|[[0iE.6p\frU |aneÃMRAoZCa`\zcTeduQ*% ww瞻H$a/T 769 } @ f0F&3w7Ž3uxxz)eY /}p&ۻiG"c98GG^LrQѫ.mjnG] PmY9qQǭG+!$'6q&ZR>gN篑zPІۂҨ &q5nW'RN?=HaIBb4iEq͡F,@x]F>ũ_~DLMM ²(;;|/𼧪y^;Cnjc}s2%ՏO⵾R(<cW~'xRl|E9Ũ/H$1D8CIϣ=d4O0qqC9mB)!&8N J,I?\`j RQvi߯jbq"Q>OLfRyk ڐ,co׳OFEOM-ZK"Z LԭT45-$evumɫ>zǂ0{]dJ$rq,1jZ3$ xᅯ5$F wttt󼃃\C(rpp0:A5F 8*v|/O)/B9;IDAT% %Et@ͤFXㅂ{";0L+$Px^l3{b?DσtM$Cmf{yY6= &{(U!I[ Fz`y~J{ZX|\ӎ ]9K!ڶj}џrjX4R2]OZLIJ%0f$8NSqYߒò'׳!"ߛ9JeJU$xqP<ץv1qFlH׍uffH;zZT+$@VD!1eEmrŏ.|R0gXh뻂]HR77f'If] PsE3$94}z?fWlh68^ 5{a%?ŏX'IHmo b= p\:4dUUu6q рNǻ|0"[- l z=]Ax=0\~-+۶alvq '024(%1 hp|PTb{-` /+Wd#bQgYuyW-UŋEZOQTMHS(|?6tnKo.XhͲ%usQU1z-Dd2ţ? ղE&nki L KK`v^J3I2cph˹\1X"–nllo|/ywm֞[[gp;Si?T189Fl۲m vTEQG>^=]3?غΐLzS 3Ryce{\Ֆ67۰~aZfh*1==qeyYwa34=mkgKKn6^V21v._3ѧ)]$ˮ[`7 I CzkڞH*k8fML.Y6ͺ;;P(4e9-(MϻnGJ˗ Y wtyh46P/Xo IuQA`4@aA ˀƞǕ P|x Kz4]04v DZ}s5M0 Ag0L,^D$+W ]ӄN }1 0C>>5IZ-E1}4Nt]<d\dٳm4ʹ,&}f)Al1 57: .a^ N#{ NS~._J"+JYff;8H<8vXjZ2$%$キ9/{IF$bq8w tu ^ܔSe`8ꨁq](Hx^haɔpuF Oj ^\|&4 !ۥs92lbhTILQpby'7Oe, $äIi(sU8)IeIZi:y̒du3t:TMv:jGGVj5xY69iۤǹ.Ǖ!Od>_.e2 ReIJhYTɲ'A@U!,-%H2[{;w?YT9l:: ?T*6[~m/޺kۦ~'0w3|O',jo;</d,z7JoS{}yΝ?]s<{\qqzzl_U+WDyUTHӰwGm4nlUu7*7~5eēO NO1ɭlQUi۶cYr8i}Qqr),uq<G"}p]uǭ~߳,۶Eii E9E(24%2sT18D&ߣiʲ ۗpes8N8.0̟x9kێil6GQqdl3&[=bMY*5_?D\Q^ŲtTBۚf+>oa4:N@աx!z:!Fc]`(Ž|Y@wZ?kC;5uV+ڭ:#\u?r+Ɲ}$}AY6nܐjt< 5Gi{a0*DCnoc:˲RlLekyTUU-u^Q!53Mlf!du*\.|.GG{sqDzӍ4͋~&Ik(Xq FGw'V?E,i |W>WU4/8Bxz^˲,,P8a(8eo4](0 yQ= 0b(ΨRrY);[0^Mz(lDV76kk]dEx%D􏾺RI6<x[[d!zDbu-$LfyTސ5IZQxi{e5d$u˲N)'$ E ïѯi^9X[$IWK`ydR_ہ>DQX\tyFG9M$Fwwwdjo{A70 : ;Qi!Df_$ ǚ$Bm]5L&MC:h~^[[#@hJkP$(|h=-/=81rN''of+HBArՖ$PUH&n  r9Hv|| '⥐=E߿ oMOm  0v[0(}&Izhg/<_U/ydh@캹*܇UC.xg8=tu(^dGSSw+9p$"ݻw b8UOWr@A.'R/"ISHke;eH|W p5U}ښ!$L6e҃4ͥRf٦ i.|}l'h$`a>8 ^G-ƊVV(XYx>0^H$EH"`qAHE}~$]nn]$/ ZpE%ZxPdQt4|=b&&ѣuif`p*~;J}uf&J2Q*1v\Czc`xbzH/zT!D$ v-/hz8\ToIkG߿D>NQԹsf s}ߧAw >:i=tv 4|$yqaSd9+Ii 惓ilmsaMU^J( RMg{7Qp \,0t F]b;%I `/WW?~][X6ΝaL\vR kץ$ TFiU-0% 8e sXaGX,0B0'!e"˲WBmnn>~{ߧ]bqij9e'IK75 Qd( EŎbIGܬ.wz}.2VVK:xε vW*J>?#ebb`l'VDq!LRlp5#9Gx( ptT4 ÞJcbݑ/%y?wj =9q4.6&;-<$`8;؃$pZZh!t'|p 8C"0MдpvMBO+I8n4ARss\61uCD(&ަ`ON$VI!o \Ѝ̸eT~6lJu0v}:HGia ("H]_YU$Aa </@iE`WBDn\L&(+CAhmI&JR ʽ]j .Gx1~BIb`Ss?BxBP0" {uI,WVÀe"2l$EM{o;Fac"R?$)QW(|m|dYBѭS؅ZF|ų?eHeE!#]WfV[M$g!YΙ²lj֗hU*?j4P,vj8c: q"Bg0-{2j IRx ;4M{=$E,2EVJj\rFHT֚%@ǭkU?=/.E"+o4kP0sa!%iE @'Ed"GGIizqV`]Ix@%E!+ jE-KPs$ sjK zxA㨮aI{=²0吮:sX-w*y'eQRi}nyY`$ֺA@ let>6R  h^kz^k4Ǒ$AI2^GVB[֛8̮d"a<栖fbqmcbEYY^DQ;ɧviSX²"N 'q@G0P&d,6 Y g2c0C1n5aAU%^\;>U01t]aiq|{ P >ߘ,:::O}B>i]l'S)> RQ@†gG\o/z@.Νk~_q 68HTf 6}n@ @``*_Iy4,uB7>GsK~väRnZgV +> K_O{sQ5ׄ'JNty`4|y :H?t|e9n&qt:لt#HRe]/Z/7_jӃxշl (Quuc$G4=`\,/1xΥWߢAvWK(<Ӿ}zhqqANZ#K7)ː5X|Iv02pVni|pMSnE687lʿ8x*B/6xΥ]d=i[?A 45IENDB`xgridfit/docs/q-delta.gif0000644000175000017500000001023010643720040014654 0ustar peterpeterGIF89a܀'!Created with The GIMP! ,H0I8<`(@$ʢ;ƲH-.r'8.C\5Q<ϙ SV[ݦh Cͬ&I̭umOt_v}x8yz|q?fwp~=e(u3TkPK+9n'r!D ' J±Ŷʹ -$- дۻMG#K,\1&DD:aJ"pb%bx 5$ b H8#@QqfK) Cy'>d XR6->;TS&7Yr C[UmAmX-U-Cx+7-ݺ>nnjB8/e|qnzQ3/{< jȮ-v9ՉIzi"nL;8%OF.6cdMT?fXÉs|%`:9< '#TYL~R-㽖q5f}Υvsst^J26Z9wAܩV܁q`v J>1*N4faq]}f R?VmG㐐!Qh=h4%7ibk )v ,]/~~+9MP)ԕ;3E?iXH9^I&;'*yYznYv2X(M$Al6f ݣ"^TTDex*id6:($H(hТq2zu6tG`h( kެSM-B:)$*'*J߈̅avu\ <%IIr|^)䅖܆~j-' ze0F V[kgvpc,+`\"'rCܵYn)8B-uOreFPBK'ϻ4M3ԅnQ57luIǴuT-=1|q˚hBr]z:8Mww9Gf?C3?6܏0 R@'aЈfqC7(Oxù [B.N*~n#XJB8I&{mJ5gAe\=~ "5~RjPp(3ƂrX,Hpb b>hČ,Uki`Ϊt_KlZ_6l*!J—qfIsxqBuLXRd~l Ի;nkUfI]W t1GF2 L0 9+y1Ucٵ4pjMm3rU3?||zsN*hXʆޚ~9:4.&iM1j.24 3vr$N̠*Wg2Jw5Bkbzh ];[ cpv-2;eL)vdN5y;5wע2 th }rLT5{V;]еF"NyE?`2]LZmO[5f<2Glqn6$_r+$n z+~^gg6:9z*l#\,GV]h\X@2LJf|.{[lg7^Zf#`WWkdK~o~tH/~ m|0w}1'KČ1*k]{}ߑ6b+ x~{~&qtoot7O|f׷}'_ %`ۜJB1Wf~w۹<7 ##7pLJȖ\Wo|!tl&h׷Gy0{4AWׇ͑)(wzgZR!-؁6qfy'j!|yg.{:ܡXan{wIGW8фQxϡVhjRya3kul؆npr8otȆ]xqo} u8fi(8bF#cxZ2ȃGXZf !&q׉+VqN6QHw$hFׅI^8lkȉٗ5gpFlG^p;}6sPG:ENme5e5Ӹ4p8lF6X"rK7xRR8苮T'u5dđwciFh")Z*qExA 9dh/ 6W9XhVJU``UE;(DYi8wS&5[ .YSy a!֓G0CitVq7(\ُhZ{|l֘84^˦,( 8m:阙vh y'֑JܨƏ =̅cVaՈDHtvٗHE2)(@yeHgz|ˉY)])Eɝa: ~Iiiɩɜ iKyyOeXc'Gm)9XWXȒ|:9pٝZ*y虝ZniWɞڡZͩV3 K2텘ibi)\֎츙PʓMNIј隬 ;=򧚸i`ً,-=k8zJ|wPRӠ0iZ:!a5g0ti%1&zɃu1JUɨ3Ss*92DL4#VQER9y:(zBQک4jw¬gz JLdZxjw{ᬁ*z5 ZJz'd򊭼ٚbTdz)rظFZK70BBDC}O:QjHA<_Iئ=(+(ASs A;: '1Ǔ(M ڡh!*zʖ:M[([t iɴA yBbηڵW3˒k j*늷 {Sʫuzظu fy4+aQ0к]銘vR[qPnkH/ wo{Zuɭʺ#zi:۰ L8KK׫h3QۙW*E@TȦ;d % پGkF qIzk )KkūNJܶ쓸k:\+;xgridfit/docs/A4.png0000644000175000017500000000776410643720037013640 0ustar peterpeterPNG  IHDRxpZU#bKGD pHYs  tIME  2MfIDATx]ksXH \uRu;u8yH<>J#h>Vwvfvv^mf A t tm555е@@V]]][ ;2ۭ9O|mflP[<AC FAjbCm\EQt:hxw (nP.K4Ė%I$Iv7 PðFVbApE<%Q`^@eYcooorEPF<h { Ft:ft:6u9$I(#5?a%G,<ٖ?y}+2L&ht.Њxl4<6M`}6s?ѯh<y^n6(o ҁIn#D~ 7;``&l+ zբA=\9tsMa`t p84H(5 m=%ffl(/14x7E;l4r\x=<<>; tk12mj)'۝sRNu@ 18d4*'CMgV_F3Jf}t4 wֆiR1ZV5 y)&نv3i e4!YJLOCEn \f}U:0=OV \n:;ЪtFA݌Leaaӡ ݵt "i4V Ym4qH$vem3)&Ihq3F(ՃaDZvOswʸ҈ qsS3jkxᙱtjbh4GTncf1pWApW\CC4QntF_ tP؆Q}HbIP:X܄ 8 vGrdT0\ַ>at:uݏ?>==i:q6#N8&f04jMa@zdpoxb {MmQ{r\NVZ@7}Nmj/ C1LM uVUkb m!=60'(t:H:Ѽ"0h&khQS<%NFhi RPa`ZkVk? ܊2:9,dV0- pw4C{9>@ƽ._:;__uPgL"*fIcJ8W#y]. .\**]_-cBwd)(T&%1e b)b(c+dy/F_MC1ќΰ |ĝs2eXY֮iODAGQ1YFd24],o27‚2ͼ,qyO&udLvhO4;t+e-%`FDyAkL͇2.:e&81(1-}K⃡. ׽v/.Q&1e z}ӌ枢 +k|l7ȤTs:`)RH2% iF@&N~ 0,[͝RtX`Fy=9LǍS"0Z=ݫ\) zWB7;^Hy3HǞ?e.&aH{, VcJΏz%N0ea鑔? A)865vUH#Ɏk?3q!(bнNet漃I<2ZSk$(<@_hF XC,Ǵ@T^`1<,3!Ly \/u+aA7b4xP+`/Sb6R1wP%=儙oV:D:v\ Q8TEMjYS `alrzcbewJQvWβudnzNA&5> @lb~ VFY'и^*T9Ȱ8Z!v3tS7"ՊVtQFkqVj:]] 4e 0d,MN4\ i4bȏhZ0SXlsd eɯN&i_7R_cKFcA+?(퇍7QES`- RXL @XeǏrw\&R=MSZVx0@qt@f|OGifx?Oab`Pl<p8 #TEm X@hDX(-d4??n-sLQ~2!< ݬnC@*2F|ev  (2 = ϟf z&K2[^Wo߾})[mO|{t~ݮz'2z0}zzzz||D{w~^1U0c,Q9H.ʞ}鯿I~?y J$.Qf:aV_W`OOO^~R+ܞ籆 >8=HZ ʞzj!#zcy(zޣڳp!E9 7ʢQ} ϣGG(1Z)a42QDqw-.ZlO( 7yy`%W~#?˕)p֬!x?]4m_ZIENDB`xgridfit/docs/o.png0000644000175000017500000001234210643720040013610 0ustar peterpeterPNG  IHDRXT̳lbKGD pHYs  tIME /R<3-oIDATx(GRɸO'R.e:QQ}Y{Ϟ=l6.=$t]gnZ @"D{(ZgxC0tX:>0Atstҙ.PaDY,zCD^ 0Oᡣԅ5z~[RDH%ۗ }VmmLjw+U^o8VzzK85&YU<x I¾Ep$ =^|i9c!Zߒ9#uWΚ\@jݷ4K<wO3. 5()W({!lo~M5LЁ.@Z 0dU ߛ'kv7\@jo8[)t? A68<˹'s~`k.@80|8'aD jSP%C\p Y 0K{'#_O\[DE Pp"H` \N(zZkmu[ S"40hDaEt:>/ܱ1܈ A@ Ds"2.@,.\#nc`s  3-(xxQ\ӈ͇#S1xp"8I|it+KRH- $to஍wc§㤩r\δ@^3d_نЏKl"@/[ 4{:^naӞT. ,sG]Oۆ xȼ΄"4  - $l4gڜq"XA@`?δ~\k(Ϳ.@ cMB P)iXĮ* N =QXR 4MHIjA^z@E44Ӥ4;A{{oFeAc*`A :xgT1_aI\afx:.x5ZqAqA]"F sAqA5 `b &Բ}S)v'Y[ _Mjkuc6as>M{P%UYG=yܳ?3`gj\0\t7džv{:6* ʌ,`' G=v8RD3@C/(iiV2D @ZyBJŸ߽ \#p66/\0- {ǃ{ ʎ J|_ (H0~W6 Kia` \,4Uiԑ Y@$$'bH R'c%p P,YrAXK2\,j]/qS# XSCqV黠շZF@,@PPx/$@oIA4J Ze L9b(;.he- AA ZdH`~ ZA E%PG\&lj Wŷ@^Kg"Ŧ06 0LPa`nn$ B~Dfk[@wުs  W͹`mgPݹ`{وUH@8Pg1$B{IcNX5 $Yx ( ι=&'&J-u򂪊&|os;DgݺoM8Pp`X0ɯZo_F~[o"^"`nmnʝJ*&KhORdpbP,HkS &`}b@@h \FfY< dl^,᪻}ԓ kXmljz=7 Kb/{;J8f;GiZ\%;&B[4,NDFFP07ۄ,mu@%] &APL3 uf4-@d"`ЁIA"&K." / XK."4F=2⊀pP p!([DP&n"X"`@E"  3  $o䅈 @ 2@ B@Lܮ"# lm. ﺾ]0i|mW8s;h\.ֺFb,YV0V~g}Lf~w". AcM D*/c\@]t]טfdV#Qicz!N=w~}|0,#m3Nf ,CUg jRUe`}P"lų3 ܝNYF㽺@U}D$I Pޞ;#E0WJ0W6Dh SH^jZ;> "D @@k޲;7 @D @P@P/Nh-!\"@6vhR-3!P>@U!KޭwpZ\zkhU\R@9pU"P v3dAx'q臗x`h) !djі'  -l|L}kS] ҮLPP|R "t,,yW[<+@X@+"jR>5Xq~i 5!+=b!qfe'L\ @ထ>sA@٥Q⻀9CN .4 ;"pEOI%ш <@? (F RH r"kx ^yJ 5]@P 8Ͱ@"X 3Vmbpt.-ye.PA ھƏ{Z@RM AAp-δ!e$Y?zI6\`nE|V\wIAu"0z_ƤA-& J9XR4{_ǴV[1Uk`\ޝ ܛB_}s%X^0C/ء. ;sFjg VP ^}RJ3; ]P} )a3@#`6óEe11= "عX ^3pz5cf!R,\ Rÿ NWTNXZ,'"χI`Y@rQCa\Aܮ:".8kMvJ9n[#$CAoXxNh-KN p 3wu, yTTL JͽK*B\"X -ݺJPûg׆\جIcnWU~j:Dcc'bg.b8xZ;,ph{cZԹ<Ֆǯ|wªE  H  0MDQ` jHD0Uטӄ\]U7"ExVyh \¤?Rǖ?rmll8l%uD}+,Sa70HTC/2ܾ/P ~ Fd#_ `?X#.p qt>/v_a}5o, "̺9s? 1|v$>w,T^6N{Zg78ccn.^m|۞*:x0m HMJ<cE#~ǾhZ`ls@y m𒉰"V݋4J[b/FxI"ػ f\T'4y,0®.R&R7{W߳@[^  .>ѹp .u5]/,uA S6Υk 3]44@W ]`9V(#^D0]wXbY( H.@  Ё5ٹ1&*Ssk{Fn9D\v֘.Y'>bDtz!ׁd]G``R (TӁ@G}R&O߯?^CR#83  xS 석})sh )D މkX2„Uï63BvNϘuW{D*3?Q/LO<4>G¸L{8b~QO,K~?] yu;@D[U!U7.;"HU\N"D @"D @ uS]IENDB`xgridfit/docs/advanced.css0000644000175000017500000001177211122400216015122 0ustar peterpeter/* The big containers */ html {margin: 0; padding: 0;} body {margin: 0; padding: 0; height: 100%; font-family: "linux libertine", "liberation serif", "dejavu serif", Junicode, serif; font-size: medium; line-height: 125%; background: gray url(parch-dark.jpg) fixed;} /* Basic HTML elements */ h1 {line-height: 125%; font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold;} h1 span.chnum {font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: normal;} h3 {font-weight: normal; font-weight: bold;} h4 {font-weight: normal; font-style: italic;} hr {background-color: red; color: red;} p {line-height: 125%;} pre {font-size: small; line-height: 110%;} blockquote p {margin-top: 0; margin-bottom: 0;} li {line-height: 125%;} dt {font-weight: bold;} table {font-family: "linux libertine", "liberation serif", "dejavu serif", Junicode, serif;} th {background-image: url(parch-dark.jpg); color: white; font-weight: normal; line-height: 125%; padding: 0 10px; border: solid thin #B8860B;} td {background-color: transparent; border: solid thin #B8860B; font-size: medium;} A:link {text-decoration: none; color: #A52A2A;} A:visited {text-decoration: none; color: #8B4513;} img {border-style: none;} /* Anything we want to say only to old browsers */ .hideme {display: none;} /* Our versions of the elements */ p.first {text-indent: 0;} p.continued {text-indent: 0;} ul.detnote {font-size: smaller; line-height: 125%;} table.std {margin-top: 10px; margin-bottom: 10px; padding: 1px; background-color: transparent; border: solid thin #B8860B;} td.blankhdr {background-image: url(parch-dark.jpg); line-height: 125%; border: solid thin #B8860B;} td.blank {background-image: url(parch.jpg);} td.plain {vertical-align: top; background-color: transparent; border-style: none; line-height: 125%;} td.hw {vertical-align: top; background-color: transparent; border-style: none; line-height: 125%; font-weight: bold;} /* For poetic extracts that start in mid-line */ div.bigindent {text-indent: 7em;} div.bigindbqtr {text-indent: 7em;} /* Bad name: actually the side menu */ div#jumplist {position: absolute; left: 5px; top: 3em; width: 220px; height: auto; font-size: 10px; color: white; line-height: 115%; overflow: auto;} div#jumplist a {font-family: Verdana, Arial, Helvetica, sans-serif;} /* Hide this rule from Internet Explorer 6 */ body>div#jumplist {position: fixed; height: 93%;} div#jumplist a {display: block; color: white; text-decoration: none; text-indent: -2em; padding-left: 2em; padding-top: 5px; padding-bottom: 5px; padding-right: 5px;} div#jumplist a em {font-family: Verdana, Arial, Helvetica, sans-serif; font-style: normal; text-decoration: underline;} div#jumplist a:visited {color: white; text-decoration: none} div#jumplist a:hover {color: black; text-decoration: none; background: transparent url(parch-light.jpg) repeat-x;} div#jumplist a i {font-family: Verdana, Arial, Helvetica, sans-serif;} div#jumplist h1 {font-size: x-small;} div.levone {margin-left: 1em; display: block;} div#content {position: absolute; top: 10px; left: 225px; right: 10px; height: auto; background: white url(parch-light.jpg) fixed; border: solid thin black; padding: 20px;} span.note {display: none; border: solid 1px #B8860B; padding-left: 1em; padding-right: 1em; font-size: small; text-indent: 0;} span.chnum {font-weight: normal;} div.alertbox {position: relative; left: 0; top: 0; border: solid medium red; padding: 0 1em; margin: 1em 0; height: auto; width: auto; background-image: url(parch.jpg);} div.bqhdr {font-weight: bold; margin-bottom: 1em;} div#copyright {border-top: solid thin black} xgridfit/docs/i-no-dot.png0000644000175000017500000001214310672600255015006 0ustar peterpeterPNG  IHDRyubKGD pHYs  tIME 6!$IDATxhwקvY:m6v.QjAQ۰n(M+!(&PmT7DN;8 ,B'\6mKr[k˽ ; @8 p@88 p@g#E1c28G{(d%Gj9PDQSÝHTbZvG?x,J6Ӊ#xQ#"3yb`:Gi` FQ!=3,(jwi+QjSιk7Vш]aybgި@NL+MӆqWGq"{ѭ+pV8(bQaOg.Yy ^EA7#p9N8ۃ`J^=v-phԮ^\k9NOkZtţ6ǨMc&cqW"n#88joq950 A~ 6M#푌tєStL8Y*QtoXX;j6MfJ)l "* ;""JeSruqO, T}rEv޻oFԝ)¹ȶ ®ڙYԋ;J!Fp:zdw.. &lޅ+6Gynb6\a#p66\ pa})FB qc7j 6Ga#paC;4]Od_3;}k.'|mԦEFkcMxQdm_bYկ1Rdu7F&?rQdԹ];a:\f1e">5}ݦwszFD L\o$ψ(1~+JF65lyi˅F,JyTzbXu>=9F<\¢nW pr_áо#yՎ덦uGE^AkG|!xI5mӷFqL˦s~J:VnE}mGp@@>nzc8 p@W^%*u00Çӟtnڴ)/|[ޒo~3O>mC 5M.\_ox7o p w޼o~ss==Ɗc='?8=KޞzꩌsֻX|Ȉx 7+Qa[[SF/})S/8oDD#ڒ&[ V頣O|CPO|7)F23b8F֭[gΜ7MSqEx4Zw1+Hn5:.8qD}~yر<|?>^|~w}w^sɏ7am٭ĸEsEQӟ4;Pӿe<jw+;G'?IOݻcӦM]tQ\s5}׾_:[thj۶mŶmۺ` 1c_3ƉWсEȅ8r9.rA"G1#p@Fq8 p8Q7A p@#p@Fq8 p@ p@W/W8 p@A4 m8 p]:PnKwxQdf}f8 p@޵x .[9E2[k,zo3T~#8 p@ p@8 p@A88 p@8 p8 p@8 p@ p@8 p@88 p@8 p@ p@8 p@A8 p@8 p8 p@8 p@ p@8 p@A88 p@8 p8 p@8 p@ p@8 p@A88 p@8 pV((8 p@=?я;uu]v[Yzܾ}{^~ӓ}}}|W7wL[-"rm͚5y}b]uxݻcq<~xW>.{ַGɗ^z .믿O?t~_εk5k򩧞JyСigt+꫋+""8"j2<qUW9_ ^xᅈؾ}{}eg?x=c188؍0ӷ*#"}رcyWN>:-j?=e_7'O_>#"<_g?Ƀ/pB?~j,㸚퇞11z#O֭xgٳř3ggy&?A7W^ٱ˞#H>#9մmFD^zYT|J/ ޏr78~xnܸ;єJ9U#㈈ؿ Rs8qDǡCԩSkV&"[QZ4Ku!,زׯ_ǎKqx'O 64<6nX4[FD?wD={"";Nwr(9'oBՅsM7T޽;Μ97tS}sbll,}7xcvKrr.8EMΞ=vuٟ5{OweN80EUOED~7MzqFOOOƖ-[n#G8ߦ4r- 7?c۶mwW_=N>ùuց-E+;yDkm8 ޷o_Gn:B}%l޼ӟwqGlڴ)zzz+;vā\.yLZ|Na9b$r<&ߗyb9|WZ1 /5wв)H1~(LS圆yi}VxX|ce@1ζskCnu[wzM}fW)p1]ZԫG%q D-ْi}m#Q{13R9\&K9`@zR'/+2Dj=O _ug/}."sb_oJJ" hzNۚ5'pXWn|MDޒ{m28 p@X&p> IENDB`xgridfit/docs/round.html0000644000175000017500000003413110736451601014670 0ustar peterpeter Xgridfit

Rounding

The Round State

<move>, Xgridfit's primary point-moving element, allows you to round the distance a point is to be positioned from a reference point or the grid origin. You can also use the <round> element to round any number that represents a distance: for example, it is a good idea to round some of the most commonly used control values in the <pre-program>, and you can do this very simply:

     <round value="control-value-id"/>

More often than not, you will use rounding to ensure that the point you are moving lands on a grid line. The kind of rounding needed for that task is straightforward--a matter of rounding a fixed-point number to the nearest integer. But the TrueType engine offers several kinds of rounding, which Xgridfit labels as follows:

  • to-grid: Rounds to the nearest integer
  • to-half-grid: Rounds to the nearest half-number (for example, 1.45 is rounded to 1.5)
  • to-double-grid: Rounds to an integer or half-number, whichever is nearer
  • up-to-grid: Always rounds to the higher integer (for example, 1.1 is rounded to 2.0)
  • down-to-grid: Always rounds to the lower integer (for example, 1.9 is rounded to 1.0)

The kind of rounding performed is determined by the current setting of the round state. You can change the round state (or turn off rounding altogether) with the <set-round-state> or the <with-round-state> element. You can specify a round state for a single <move> element by passing one of the values listed above via the round attribute, or you can use the value "yes" to round according to the current round state.

Custom Round States

TrueType's standard round states are sufficient most of the time; but it is also possible to create custom round-states by directly controlling the three variables that control rounding:

  • period: the distance between rounded positions (the default is 1.0)
  • phase: where the rounded positions fall (the default is 0, meaning that they fall on integer boundaries)
  • threshold: the point at which the direction of rounding changes (0.5 by default): if the number is less than this the direction of rounding is down; if equal or greater, the direction is up

The available documentation on how rounding works is far from clear, but the Apple specification offers a useful walk-through of the rounding operation. If the distance we need to round is n:

  1. add engine compensation to n
  2. subtract the phase from n
  3. add the threshold to n
  4. truncate n to the next lowest periodic value (ignore the phase)
  5. add the phase back to n
  6. if rounding caused a positive number to become negative, set n to the positive round value closest to 0
  7. if rounding caused a negative number to become positive, set n to the negative round value closest to 0

Let's walk through a few examples, an easy one first. When the round state is in its default value ("to-grid"), the period is one, the phase zero, and the threshold one half of the period. Suppose that n is 1.3 after "engine compensation" has been added (a complication which we need not address).

  1. subtract phase: 1.3 - 0 = 1.3
  2. add threshold: 1.3 + 0.5 = 1.8
  3. truncate: floor(1.8) = 1.0
  4. add phase: 1.0 + 0 = 1.0

Try it with n = 1.6:

  1. subtract phase: 1.6 - 0 = 1.6
  2. add threshold: 1.6 + 0.5 = 2.1
  3. truncate: floor(2.1) = 2.0
  4. add phase: 2.0 + 0 = 2.0

The round state "to-half-grid" is like "to-grid" but with a phase of one half of the period. Let's try it with n = 1.6 again:

  1. subtract phase: 1.6 - 0.5 = 1.1
  2. add threshold: 1.1 + 0.5 = 1.6
  3. truncate: floor(1.6) = 1.0
  4. add phase: 1.0 + 0.5 = 1.5

Now let us concoct a custom round state: period one, phase one quarter, threshold seven eighths (0.875), and try it with n = 1.6

  1. subtract phase: 1.6 - 0.25 = 1.35
  2. add threshold: 1.35 + 0.875 = 2.225
  3. truncate: floor(2.225) = 2.0
  4. add phase: 2.0 + 0.25 = 2.25

Notice that the low threshold has forced the engine to round upwards even though the distance from 1.6 to the next rounded point, 2.25, is more than 0.5. Finally, since the threshold can be negative, let's look at the effect of a negative threshold. Now our custom round state is period one, phase 0, threshold minus one eighth (-0.125); and n = 1.1:

  1. subtract phase: 1.1 - 0 = 1.1
  2. add threshold: 1.1 - 0.125 = 0.975
  3. truncate: floor(0.975) = 0.0
  4. add phase: 0.0 + 0 = 0.0

So a negative threshold can force a number to round to the rounding-point below the next lowest rounding-point (though it need not do so--and would not with n = 1.6).

A custom round state is defined with the <round-state> element, which can only come in the top of the Xgridfit file, as a child of <xgridfit>. Then one can set the round state to this value simply by passing its name to any element that takes a round attribute.

Rounded Numbers and Distance on the Grid

A number with no fractional part always represents a distance equal to a multiple of the width or height of one pixel. A point that is positioned a rounded distance from the grid origin at 0,0 must always fall on one of the grid lines that runs between pixels: this is because 0,0 itself is always positioned on such a grid line. Thus this sequence:

     <with-vectors axis="y">
       <move distance="lc-x-height">
         <point num="top"/>
       </move>
     </with-vectors>

will place point "top" on a grid line if the round state is "to-grid" (the default), for the <move> element uses rounding by default.

However, rounding "to-grid" with the <move> element does not guarantee that the point moved lands on a grid line: that happens only if you plan properly. For example, the following code

     <with-vectors axis="y">
       <move distance="lc-rnd-horz-stem">
         <reference>
           <point num="a"/>
         </reference>
         <point num="b"/>
       </move>
     </with-vectors>

positions point b a rounded distance from point a. If point a has not yet been rounded to the grid, you get the undesirable result on the left. If point a has already been rounded, you get the much better result on the right.

point a not rounded point a rounded

And when the projection vector is not set to the x or the y axis, rounding generally will not position points on grid lines. Indeed, it is usually best to turn rounding off when instructing diagonal stems.

Instructions Relating to Rounding

These also include the <round> and <no-round> elements, described in the chapter on arithmetic. You should also be aware of the round operator, used in expressions.

<round-state>

Declares a custom round state whose name can be passed to <set-round-state>, <with-round-state>, or any element that takes a round attribute. For an explanation of the period, phase and threshold attribute, see above. Note that only a limited number of values is permitted for each of these attributes. This element is permitted only in top level of the program, as a child of <xgridfit>.

<set-round-state>
<with-round-state>

Sets the round state. If the round attribute matches the name of a <round-state> element, that round state is used. If not, one of TrueType's prefabricated round states may be used:

  • to-grid
  • to-half-grid
  • to-double-grid
  • up-to-grid
  • down-to-grid

If the round attribute is not one of these, and not one of the custom round-states, Xgridfit tries to resolve it as a number, constant, variable or function parameter and use that as an argument to SROUND. You had better know what you're doing if you intend to use a raw number in this way; it is safer, more intelligible and just as effective to supply a custom <round-state> element.

The distinction between the element beginning with "set" and the one beginning with "with" is the same as it is for the vector-setting elements: briefly, the round state set by the "set" element affects the instructions that follow it; the round state set by the "with" instruction affects only the instructions that it contains.

Xgridfit generates instructions that keep track of the round state (since the TrueType engine provides no way to read it), but it may lose track if Xgridfit instructions are not used exclusively.

xgridfit/docs/o-bold.png0000644000175000017500000001061310643720040014525 0ustar peterpeterPNG  IHDR&bKGD pHYs  tIME ) ~,IDATxq8FAQ(ʀd&0L?`c1!J"n}ڒ5^ \s >VO KB%` !XBB,!KB%` !Ko`m:V`wj͊IHs ݈_*=W13Iy$a -{Qzq ~ ґsS8;%<~$ ɗFIfw`1,!D,!K$wHF7_iJ/F? i-_$Lnwi8W 5'jsG>pUXA?g'kNf?Q&N', ic6\|IUnT,B]U`v@`o(~fPPr8]LYzu 7^S*z@8N5Zm~Sq) y^kKN+PO*HIFzcpM HsŸBpRq>SrH:uιx?+Ƌ[ؙn5tDt )9Nu,&H_RZ 38I $\r Y4Dw埆&;A! ժsMJ:I,iZuF8_$3$S3ihh$xe1{&񝬫B_:'ۭ l4<Ӎo$NIɱ>S' gC~ĎXIHBPq׋!Cʔé+{<8#%I>H6rҹڝ?tvjz9*Yb"Hꖱ⋞FKs"||I9{bT(qo쏲E/"cu#?!C@q*=j+GQO=) 2t@oE)Gh=wK=FEBv7c zu+%PҺ)(!G_pB}xXs2EMTA7{TFK%7/?8:ĨGti_3pJ[@9!%tX,)R(yl u`,b[-1ޑ  1s"XB| U,XJ&aAGr 11ϷOXP9SmDK,0gPX\_B}KNv2S ,!$B,!KB(?KC,!TPZsB%`-N (!XB*"kc 4%fIo D_tzIy>O6Kt㮗[` #|T Kzq *$ 7Er$ \ZR K4;`I-nIu&}r4:翂ENƌ U ({u-wV&U8ٌ<}8\~i65ɧTrWr{P8xS)SUY3!ZI6蝼GNɿ([sJ/eY2. ֔k *ȝ x{p;(\䡽LBĕO&ɔ TK>c(N)S*%85r::w^@v,I13f%R~dڄo rJ'bTGzV nwJN%,*Wq`.xԸZ>A2m 'itd4gCkOiT~ANIlRΚNkekE,HFԹ;q0Sk딞Ou ?[#ğ7MNf8.F Cߓ;Ifq@: /*jg%\+Y1K~$< z^uD<jݍqTdTW+v=DNɌiY -_hy"$uoӒ[}c!gA%I形omVåf6;Śe_ WLZ2e1 xE,NPM1^\23hOyȗ^AHi6u8Y%=)?IW&^aLK H;0]p6ǍdT/-լذO6?:\nWAdu?o3Ѕ/Oޗl /ꈻ^#,T 8*`{.M jS2ʕ 2L좟6pi|IO<:S$/ZH5xƒ8 8=>64n_-aINByabw64_HJ)fLt^JK$AmZ Tüo"qďpGT_J,D5w]ćS|t>l=V@%TSA%3]R,-f UF@jrSHmdVjYh$#y?sQL_Of%=@j5 !*@$33fuDk 5m{ m96 .K8%{%'NϗzXbFJB H=KB[c 8 ՞KYp:UH WS獔},A|?)m3:gbRHĞIZ-0Ȇ0E575ތ`gpWq&J gdB/ӣP[cAGnMUW#{fZH9p 3j5`N4B+ d0ZS&y^wMد݇Kh M\~"vB+yBDN>8@+O<[2Μ6l6lU{ BsZ3\ЈqqVQ`"uCJy%ټV,aЏm{R-ݛCjCju#M t]4U:lŽU%`vd &(7 ]6yDMޅcs yhh#=>9Kyhb 6\U ꫱_ ӂš❴!G]NĴ)Aj:Nr:t{sW9%z op$?y4fh:iAqk L [q7UM@"<9% g@oD(V؉e*.A#xM/.8=cprr1Q|b܈A%QEGۈG{,V{U#V8NщM]:|W'<,2>"t"6@I8Ҁ={~ N A⣅bt讧|E0BE^81))lڏ=M{ncFL̉>$mIHw02uX~-;E!Zi:2S0F1I>/\2\vʹFg ȴ%k6,܌}-{qwpN:@G>CcY$p<9@jAg@(N}<8M;a`X{i m&ҵ԰_2KN>Tdle)WߕAF6sZ{qx_}^4/z>J;J땃l/Dw":%`ŒI0A7潽'#9=~kd1. rG0ټh;#[Kp-бpټh;#UǡYa80 ka;H8,&@g@܈ H! fdQ|k^ hiX0-om8r̓Ç^1={3\Yro_&LhX\JX樮эb媿zʭZmTڂȝrӱJsfY3,aMn iG%etH;5Mkh_/c'-E@aZ8vNpajj፜}lZn%7+ؒ9e+ #B~X]4\MV@wu&#ۯ0cNt#cXlǏ1+&4V8Pu,s-idS *ؤ6/ᡖh)C'Hdf:I<%e:th%t*:-MD,QQ(וkhYsLWi )C0܄햏ݧ "# 3TၰO] cx"ڧ0iV0S}3PMBن.G8 @ p/ $Ud>G'*y*y#0ټAټh lࠊllE6opPE6sZ{"78"9=#"0 $C 0 X# q^3=cqx061YsF69نn$C pkdd2lAFa #[pm98ddl> #sr4H8 @ ̂l!BD_=/p* @ D D#B4Ѳ$HG!Q$h8 !~ddSh7yDa3.¸BHE){:A9t fYg/QP 3>\#tԻ! g} '5K(Z|!#۬p8{Ss͚P\pH姠n''aT[=)/߀8qb͠hi݋/Ʀ}J4|6 ̈;acQݛ㦟F\o`96ۍc<8dTTl--KsRܑ}^*)T>xt|G22qzʰm<B% JK-MQռ <}I8ŮsHZ3fxy 4m[:Nq`l#p\:3o_h~ &av߷/Hw`y0s5N3 9rQl)Ǝ U█[R Wdƽ׍8pUW㻎u0 F0hcPHNdgƽⴌsLF!‡w7#Moc|Vv""4@ЀG¿ґ!@1iV}{&>/c'o8v_E%* ,r8>^/z';NT_32ǨXg)xx#xp}i|h90l!w V|^߷CI+ϢF!1cqaE둗H8`งu՗}.p^Spߘ' eVшb.FZj:ka &8`V $q,d)"S6)PrA~f'xՒ;BEb \y%.?ctt PQq㑫EvpqTydAK0a 0 ,֟SO8/¢spi3R;ӑN|DK|: ֽpL} [52Qb,o9OKz["D 1ѳ1qSc7*Zv)݈B0H~@j,uoV8NX'{G3X/ko>)ᑭ(+>O_O">ي}tpJY;> 75k&{ʣ}o!!@#Sgm8xц}qɃLNB*5!_WnռWPŪsպ/نqL(O#b=#9ý$1cf&o"U G)|2L&pQ\|- gpQ M&i-6.7!k B`*98h;< gyAL8:*A}A$d3Ҡb mg5]wj'9oD*k{}IJF6p}s6F4='IJP!&Esy%#0rC[*Kt`aYҼyr?3k9WJ%VY\^"0rP]sNj1G)QyFNjvtN>>mA#TswrZkbo֜O=U##qRŌ|r&CÚӽ#F"'2WZ&Щ(4d"(C#m2 Qp=6m 3U>AC`8C@@!Y,4d"G$Z-L凌l'i?c)FwBʱQ`l^0aFW_ʧؼVs>  ^3_WUU'Zh6*:+Lģia5rQ( lǮEC`ItVC D!$M"3 ⃠G8dd>+.wBM"Z%'K\W*ffJF6pR‰ CP7,95bqяpe2iUmwA} (\QlҜdd,ҥ]KS@ AL^"0r <r'L=d9)/߀ Xt}SL^Vẃ)+IyN̢#=ǵpBa0 Òoב;}ު"Myl01 N,OAS$Kp0RF!(\ ~Oh~'瀂c8@jY4দ|D^hF|WŜ^3p& T>L *ND,fl4! x)5L! %D,N8!$pHshwСݱn hiEѡ۟C=$BDyac"c 5Pj"c{pvg ?ymn{ƿ$)L32 !Ǖŷ8S( L#&2бÚ׆ ~FChU fFW_U{[bf,gg6G$!M77~oz 9!|IbB|& gbRd$k񵟌:?¬9,##ȳAp$ ^;_:;w`N\T16<pL$m2>ZfnڅY e IDAT ZD;Uٚxm.މb2*Q3 T_S6q3?Jc.6؉qLNY }⯆1.F8F{}A+j_eC[mm* *;W[qG^-`#$2TaTPal'31=Y o׼bR$zK{sLĴDZI\2%>bcJM%89~dds=XV9W+V*e/r@VX[ 9Y<>ɉ+_u@aD29NP +"`sF c8 'H5 Ȑd"C铜|ӴRNL2I囮-[Q+JEЩHkIiČuo5ٵ)-c z[;pY:9iwcU;Q8ph c{8Njн޽BޭGYtszrĉ{k܀ :op wʫV~gRlnGR{g9HͲ :(Z;>9҅83yN ˢbj|ڰquCBTdk(<*oC ˶#)Q | 8mM 74!35 Tdk>ZQ;;qHrkd_hǝ 1lql+`sRgկi|Wf9Ue wwkjZwJ%x.VރP.tix#.de +ޖp;rb-ܥ)/!Ib.s@hHԱ <J<w+E7o3XpT;O#ytŸ~5T0'{yц[aSg*II{X 圕PKu;ą0xRnͽ e]7(z wg%.ՍC|P”aڌ[ J%~+ Ýʻ*IY;UrKVDĹ #gg!BghjpԶ CB&Q`@4!\d1^K|^//}8s2w4<۶Q C|_4|BC!jl!HD*\V$$-\`E#@n﷮(DDMط߳2c Bx, d[fƄ U3;PJ:xm߃c.$U2,N3ʫS` -DZ^ V, _D\iF~<窟cO`z -վ/?];P5rgLve!#C35pD_}oSI"OТn؆5/㹔1N;> @HB!X^3S)pw콘<OU?_@:7:6Ɔ验8rjC4<,{{ {,_bf O~ڀH&T=B*E3 bd*s=8v dVuN3+Nщ?%g5aG`p͓9>~W:ё6tFdx%U}G JNGH_6amoE:zV! e"?,T= `t#'"HNL|d͸=.ܓpLׯpX1Uɰu]Ru>dۡ.䳱p+]v+H:vL tj*j2: hdIVar!~_Ldd,A~[|q$nj/ZnNrC@Ŧ"\zrďcycOUdg:u*<{4 z+bW%cZtܑthCP_5yP<\U ƶv\7HSK Y (/߀\Bm/ zo; pc?nKC^V#[JV(`[[V{JƔ)33iCqo9~NIH ಪ6D#GvbfENk7 EvQوzE=uhP4 B%K[u0=F1$cdwdcb$g^A+!z7.Zj$<i497RSfHC%A 8%N89'R;R'p..Sى;Pr:hcg L$ w3<#z#M@aP!Rd$> GG)xm|"m0J(QTY&Y:2 RPB.! *AD30Gœaurf(bdjaǥ᳓XQLs^CvXΰ181'#ipK ܒ'8 @ $aD ߜy1#5'~%69FjN!q1s¼89R"H͉8@MZ& @ $YBYiIENDB`xgridfit/docs/bw.css0000644000175000017500000001135110643720040013765 0ustar peterpeter/* The big containers */ html {margin: 0; padding: 0;} body {margin: 0; padding: 0; height: 100%; font-family: Junicode, gentium, caslon roman, serif; font-size: large; line-height: 125%; background-color: black;} /* Basic HTML elements */ h1 {line-height: 125%; font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold;} h1 span.chnum {font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: normal;} h3 {font-weight: normal; font-style: italic;} h4 {font-weight: normal; font-style: italic;} hr {background-color: red; color: red;} p {line-height: 125%; text-indent: 1em;} blockquote p {margin-top: 0; margin-bottom: 0;} li {line-height: 125%;} dt {font-weight: bold;} table {font-family: Junicode, gentium, caslon roman, serif;} th {background-color: black; color: white; line-height: 125%; padding: 0 10px; border: solid thin #888;} td {padding-left: 10px; padding-right: 10px; background-color: transparent; border: solid thin #888; font-size: large;} img {border-style: none;} /* Anything we want to say only to old browsers */ .hideme {display: none;} /* Our versions of the elements */ p.first {text-indent: 0;} p.continued {text-indent: 0;} ul.detnote {font-size: medium; line-height: 125%;} table.std {margin-top: 10px; margin-bottom: 10px; padding: 1px; background-color: transparent; border: solid thin #888;} td.blank {background-color: black;} td.blankhdr {background-color: black; line-height: 125%; border: solid thin #888;} td.plain {vertical-align: top; background-color: transparent; border-style: none; line-height: 125%} td.hw {vertical-align: top; background-color: transparent; border-style: none; line-height: 125%; font-weight: bold;} /* For poetic extracts that start in mid-line */ div.bigindent {text-indent: 7em;} div.bigindbqtr {text-indent: 7em;} /* Bad name: actually the side menu */ div#jumplist {position: absolute; left: 5px; top: 3em; width: 195px; height: auto; font-size: 12px; color: white; line-height: 115%; overflow: auto;} div#jumplist a {font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold;} /* Hide this rule from Internet Explorer 6 */ body>div#jumplist {position: fixed; height: 93%;} div#jumplist a {display: block; text-indent: -2em; color: white; text-decoration: none; padding-left: 2em; padding-top: 5px; padding-bottom: 5px; padding-right: 5px;} div#jumplist a i {font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold;} div#jumplist a em {font-family: Verdana, Arial, Helvetica, sans-serif; font-style: normal; text-decoration: underline;} div#jumplist a:visited {color: white; text-decoration: none} div#jumplist a:hover {color: black; text-decoration: none; background-color: white;} div#jumplist h1 {font-size: small;} div.levone {margin-left: 1em; display: block;} div#content {position: absolute; top: 10px; left: 200px; right: 10px; height: auto; background-color: white; border: solid thin black; padding: 20px;} span.note {display: none; border: solid 1px #B8860B; padding-left: 1em; padding-right: 1em; font-size: medium; text-indent: 0;} span.chnum {font-weight: normal;} div.alertbox {position: relative; left: 0; top: 0; border: solid medium red; padding: 0 1em; margin: 1em 0; height: auto; width: auto; background-color: #EEE;} div.bqhdr {font-weight: bold; margin-bottom: 1em;} div#copyright {border-top: solid thin black} xgridfit/docs/graphics.html0000644000175000017500000004421111313431130015324 0ustar peterpeter xgridfit

The Graphics State and Xgridfit Defaults

The graphics state is a collection of variables that control the behavior of TrueType instructions. These include the round state, vectors, control-value cut-in, minimum distance, single width, auto flip, dropout control, delta shift, delta base, and enable/disable instructions. The graphics state also includes the reference pointers and zone pointers, but it is not recommended that you set these directly in Xgridfit. The uses of the graphics variables are described elsewhere in this documentation: this section describes how the graphics variables are controlled in Xgridfit.

Reading and Writing the Graphics State

The most important graphics variables can be accessed in any of three ways: they can be set via a "set" instruction or a "with" block, and they can be read or set via a special variable.

A "set" instruction simply sets the graphics variable, which remains as set until the end of the glyph program, or until set by another instruction. These are the "set" instructions in Xgridfit:

A "with" block is a block of code enclosed by an element whose name begins "with-": a graphics variable is set before the code in the "with" block is executed, and afterwards is restored to its former state. Example:

    <with-minimum-distance value="0.55">
       <diagonal-stem round="no">
         <line ref="line1"/>
         <line ref="line2"/>
       </diagonal-stem>
    </with-minimum-distance>
  

These are the "with" elements in Xgridfit (note that a few "set" elements do not have corresponding "with" elements):

A graphics variable can be read by any instruction that can read variables, and most of them can be written by any instruction that can write to variables. Here is an example of how a graphics variable might be read:

    <with-minimum-distance value="minimum-distance * 0.66">
       <diagonal-stem round="no">
         <line ref="line1"/>
         <line ref="line2"/>
       </diagonal-stem>
    </with-minimum-distance>
  

And here is an example of how a graphics variable might be written to:

    <set-equal target="minimum-distance" source="minimum-distance * 0.66"/>
  

The code above has the same effect as this:

    <set-minimum-distance value="minimum-distance * 0.66"/>
  

These graphics variables can be both read and written to:

  • minimum-distance
  • control-value-cut-in
  • single-width
  • single-width-cut-in
  • delta-base
  • delta-shift

Each of these variables has a "default" variant, e.g. minimum-distance-default, which records the default value, that is, the value the variable has at the beginning of each glyph program. These may be written to only in the <pre-program> (where writing to them sets the default value); but they may be used elsewhere to restore a default value:

    <set-minimum-distance value="minimum-distance-default"/>
  

There are two graphics variables that relate to the round state: round-state and custom-round-state. These are both read-only: the round state can be set only via <set-round-state> and <with-round-state>. The value of round-state can be tested against these constants:

  • to-grid
  • to-half-grid
  • to-double-grid
  • down-to-grid
  • up-to-grid
  • no
  • custom

When round-state = custom, the value of the period, phase and threshold is stored in custom-round-state. The three values are not separated here, as they are in the <round-state> element; rather, the three values are ANDed into a single number, which is more suitable for storage and retrieval than for analysis.

There are two other read-only values in the graphics state: pixels-per-em and point-size. Of these, pixels-per-em tends to be the more useful, and it is often used to decide when to alter the outline at low resolution:

    <if test="pixels-per-em &lt; 20">
      . . .
    </if>
  

Setting Defaults

A default value for a graphics variable is the value it has at the beginning of each glyph program. There are two ways to set defaults in Xgridfit: one is simply to place a "set" element anywhere in the <pre-program>. The second, and recommended, method is to include a <default> element in the top level of your program file, thus:

    <default type="minimum-distance" value="0.9">
  

That is, in the <default> element, the type attribute identifies the graphics default to set, and the value attribute is the value. These types are available for use in <default> elements:

  • minimum-distance
  • control-value-cut-in
  • single-width
  • single-width-cut-in
  • delta-base
  • delta-shift
  • round-state

To reset any of these to the default value you have set (or to the TrueType default if you have not set one yourself), pass one of these types to <restore-default>, thus:

    <restore-default name="delta-shift"/>
  

If you want the TrueType engine to reject all attempts to set defaults (that is, if you want to use only the defaults that are standard for TrueType), include this:

    <default type="use-truetype-defaults" value="yes"/>
  

The result will be that "set" instructions encountered in the <pre-program> will not set defaults, and <default> elements that set the graphics state will be ignored.

Getting Information about the Engine and Glyph

You can get a limited amount of information about the TrueType engine. These read-only values are available for use in such contexts as <if> elements and expressions:

  • engine-version: returns a number that corresponds to a specific version of the TrueType engine (or "scaler"). (This is different from a version number such as "Xgridfit version 1.6."). The result can be tested against any of these constants:
    • engine-mac-6-init (1)
    • engine-mac-7 (2)
    • engine-windows-3-1 (3)
    • engine-freetype-1 (3)
    • engine-kanjitalk-6-1 (4)
    • engine-ms-1-5 (33)
    • engine-ms-1-6 (34)
    • engine-ms-1-6-plus (36)
    • engine-ms-1-7 (35)
    • engine-freetype-2 (35)
    • engine-ms-1-8 (37)
    • engine-ms-1-9 (38)
    Here's a snippet of code to illustrate:
    	<if test="engine-version = engine-freetype-2">
    	  <!-- code here -->
    	</if>
  • is-cleartype-enabled. This value will be true (non-zero) if Microsoft's ClearType system is enabled.
  • is-compatible-width-enabled. This value will be true if "compatible-width" ClearType is enabled. In this system, the engine makes sure that use of ClearType does not change the text layout.
  • is-symmetrical-smoothing-enabled. True if "symmetrical smoothing" ClearType is enabled. If you have a use for this, you presumably know what "symmetrical smoothing" is.
  • is-BGR-order. According to the Microsoft specification, this is true if "ClearType is processing the LCD stripes in BGR (Blue, Green, Red) order."

You can also get information about the current glyph, which may influence whether or how to write instructions:

  • is-glyph-rotated. True (non-zero) if the current glyph has been rotated.
  • is-glyph-stretched. True if the current glyph has been stretched.
  • is-glyph-grayscale. True if the current glyph has been rasterized for grayscale.
  • is-glyph-transformed. True if one or more of the above three transformations has been performed.

The Graphics State and the Storage Area

Most TrueType graphics variables are write-only; that is, the TrueType engine provides no instructions for determining their current values. Xgridfit tracks the values of graphics variables by using several reserved locations in the TrueType storage area--the same area that is used to store variables. In order to make sure that this system functions correctly, you should take the following precautions:

  • If your program file contains legacy code, set <default type="legacy-storage"/> so that Xgridfit and the legacy code will not be writing to the same storage locations. The easiest way to determine the correct value for legacy-storage is to copy the maxStorage value from the maxp table. Xgridfit's conversion utility ttx2xgf does this for you automatically. (N.B. Merge-mode manages the storage area for you automatically.)
  • Avoid using low-level <command> elements to set graphics variables, except in legacy code. This instruction:
    	<command name="SMD" value="54"/>
    will set the minimum distance, but subsequent attempts to read the minimum-distance graphics variable will yield mistaken results, and the <with-minimum-distance> element will restore the wrong value at the end of the block.

Other Defaults

Several important defaults other than those relating to the graphics state are also controlled with <default> elements in the top level of your program file. These set values in the TrueType maxp table or control aspects of the Xgridfit compiler's behavior:

  • max-twilight-points. Sets the number of points available in the twilight zone.
  • max-storage. Sets the number of locations available in the TrueType storage area. The default value is 64, which allows for 24 reserved locations used by Xgridfit and 40 variables defined by your programming. Increase or decrease this value depending on the number of variables that are likely to be in use at one time in your programs.
  • max-stack. Sets the size of the run-time stack. The default is 256, which is usually large enough for Xgridfit's purposes; but if your font includes legacy programming it may have to be bigger.
  • legacy-storage. As explained above, the amount of storage to be reserved for the use of legacy programming. This is determined automatically when an older font is converted for use with Xgridfit.
  • function-base tells Xgridfit where to start numbering functions. Use this if you have declared some functions with the num attribute (to support legacy code) and you are not satisfied with Xgridfit's standard way of handling that situation (starting the numbering after the highest numbered function).
  • init-graphics tells Xgridfit whether or not to initialize variables that will help it to track the graphics state. Usually this is necessary, so the default is "yes"; but if this value is "no," it is not done. This setting may be overridden by including the init-graphics attribute on any <glyph> element.
  • color is the "color" used for those elements that can perform rounding (chiefly <move>, but also <mirp>, <mdrp>, <round> and <no-round>; also the round() operator) when no other color is specified. Possible values are "black," "white" and "gray"; the default is "gray."
  • auto-instr tells the compiler (running in merge-mode) to generate code that makes FontForge auto-instruct a font.
  • auto-hint tells the compiler (running in merge-mode) to generate code that makes FontForge auto-hint a font before auto-instructing it. This has no effect except when auto-instr is "yes," and then its default value is "yes."
  • combine-prep tells the compiler (running in merge-mode) to append the <pre-program> generated by Xgridfit to the one that is already in the font or that is generated by the FontForge auto-instructor. The default value is "yes."
  • delete-all tells the compiler to delete all TrueType programming and data before installing Xgridfit code in a font. It is always "yes" if auto-instr is "yes."
  • cv-num-in-compile-if tells the Xgridfit compiler (running in merge-mode) to resolve any control-value index as a number rather than as a symbol for use in the test attribute of the <compile-if> element and in the compile-if attribute on various elements. The default value is "no."
xgridfit/docs/convert.html0000644000175000017500000002270511311436615015223 0ustar peterpeter Xgridfit

Converting Existing Instructions

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

It is possible to use Xgridfit to add instructions to fonts containing instructions added "by hand" or by other programs. Using a simple utility included with Xgridfit, you can extract from a font all existing control values, functions, pre-program, glyph programs, and such maxp entries as relate to instructions, and make these the basis of a new Xgridfit file. In this new file, existing functions are sequestered in a <legacy-functions> element, and any functions, control values and variables that you add to the file are automatically indexed so as not to conflict with existing ones.

To create the new Xgridfit file, you must first install TTX, a utility in the FontTools package: this program converts a TrueType font to XML. Get the latest version here and follow the installation instructions (it requires the Python programming language). You also need version 1.0 or later of Xgridfit. Make a directory and copy into it the font you are working with (this must be the TrueType font file, not a FontForge SFD file). Run TTX on the font file:

    $ ttx DejaVuSerif.ttf

This creates a TTX file named DejaVuSerif.ttx. Now run ttx2xgf, thus:

    $ ttx2xgf DejaVuSerif.ttx
      or
    $ ttx2xgf DejaVuSerif

The output of either command is an Xgridfit file named DejaVuSerif.xgf (if you want a differently named file, just supply the name as a second argument). Before you use the new file, you should check the <legacy-functions> element for correctness, as explained in the next few paragraphs. This check ensures that Xgridfit will correctly number its predefined functions and functions you define. (Note, however, that if the font you are working with was hinted by the FontForge auto-instructor, this check is unnecessary. You can be sure that your new Xgridfit program is correct.)

Open the new Xgridfit file with a text editor and locate the <legacy-functions> element. Take note of the attribute max-function-defs. This number, taken from the font's maxp table, must be one greater than the highest function number (for in TrueType fonts functions are numbered, not named).

Very likely the function numbers are assigned in one of two ways. Some fonts push all the function numbers onto the stack before defining any functions. In that case, the first lines of the <legacy-functions> element will look something like this:

    <push>6 5 4 3 2 1 0</push>
    <command name="FDEF"/>

Alternatively, the function number may be pushed just before each function is defined, thus:

    <push>0</push>
    <command name="FDEF"/>

In the former case the correct value for max-function-defs is one greater than the highest number in the list (here 6, so max-function-defs should be 7). In the latter case you must scan the PUSH instructions that precede each FDEF instruction to find the highest number. Please note, in case this seems esoteric, that the max-function-defs attribute will already be correct if the font you are converting was correctly made.

Notice that the new Xgridfit file can be run against a FontForge (SFD) file even though it was extracted from a font file. You may either open FontForge and run the script you have generated from within the GUI, or add <infile> and <outfile> elements so that you can run the script from the command line, for example:

      <infile>DejaVuSerif.sfd</infile>
      <outfile>DejaVuSerif.ttf</outfile>

Now you are ready to test the new file. It should produce a font that is functionally identical to the one you started with. You may delete the TTX file if you have no further use for it.

Notes and Cautions

ttx2xgf breaks up very long PUSH instructions. This can prevent problems later on, when running a generated script in FontForge. However, it may cause problems in a very narrow set of circumstances. Specifically, it can change the offset needed by a nearby JMPR, JROF or JROT instruction. This is unlikely; but if the font you are converting uses JMPR, JROF or JROT, you should make sure that one of these instructions is not trying to jump over a long PUSH instruction that has been broken up.

At the end of the list of <control-value> elements, ttx2xgf inserts a comment warning that <control-value> elements should not be added to or deleted from the preceding list, and their order should not be changed. Any change of this kind will change the indexing of control values, with serious consequences. New control values may be added to the list only after the comment.

The name attributes of existing <control-value> elements can and often should be edited, so that legacy control values can more easily be reused. For example, in DejaVu Regular, it takes only a little research to discover that a standard vertical stem for a lower-case letter is regulated with control value 39, for which the generated name is cv-39. It makes sense to change this name to "lc-vertical-stem" or the like, and use it in writing instructions for other lower-case letters with vertical stems. However, it would be unwise to change the value of this <control-value>, and catastrophic to move the element from its original location in the list.

Xgridfit has an older method for handling legacy functions--namely, adding a num attribute to some functions to force the use of a particular number identifier. This method is not compatible with the use of <legacy-functions>, and you should not attempt to use both in the same file.

ttx2xgf also generates several useful constants:

      <constant name="left-sidebearing" value="last + 1"/>
      <constant name="right-sidebearing" value="last + 2"/>
      <constant name="vertical" value="0"/>
      <constant name="horizontal" value="1"/>
      <constant name="true" value="1"/>
      <constant name="false" value="0"/>

If you include a constant "last" with the number of the last outline point at the beginning of each glyph program, then left-sidebearing and right-sidebearing will always point correctly to the left and right sidebearing points, and can be accessed from any glyph program. The values vertical and horizontal are used by the TrueType vector setting instructions and may be useful in various contexts. The true and false values can be used to set variables to boolean values or evaluate boolean expressions, and they are boolean expressions themselves.

Non-Linux systems

The ttx2xgf utility is a Bash script for Linux, which invokes two programs: one an XSLT script and the other a Sed script. It should also work perfectly well under Mac OS X. If you are using a system other than Linux or OS X, you may reproduce the functionality of ttx2xgf by running these scripts yourself. First use your favorite XSLT processor to run the script convert-ttx.xsl against the TTX file you generated with the cross-platform TTX utility. Next use Sed (also available for various systems) to run the script convert-asm.sed against the file generated in the first step. The result of these two simple steps should be a valid Xgridfit file.

xgridfit/docs/o-bottom-rounded.png0000644000175000017500000000371110643720040016550 0ustar peterpeterPNG  IHDR߯#bKGD pHYs  tIME" jVIDATxAhekF[QTQWwhPv]o^e)eʒQrR H[ ^DOZVuaAaU6&DPxh?ik'{|<3L:G@sy,rY((Oy3]#D""@D@D " "4="o&$Z*E?R.3qܬlMߥ9H9Qi$@D "@D "D"D"1|$$gќr<'@D@D " "DD"uF䝓v٤DPQkVS9i8cnVfs6qƦt9WJ#9Se3:v)"D"bk#.# #ZIZZq*F"T\yo9 kIшXz_Dj-5KgV,_rQt-a酹sÈfMQk`U^`n~97aވ` 3yDª08]ۨ/F$aZD싈#soZI}>*a7>K V-;I.G4uD#{}N/Ƹ6Eޙw.VX)rciESlLrc@f8E&Ng'ܱ}zŋgS699BwuW{ }9 (a8UO! $D "@D "D"D"@Dn/ rs.ӟIfUzy;0]3T#*K&r.Qǔ˜vN"D"D"@D "@D "SFk]xf1(0Ks9D"D"@D "@D "kyr.ӟIfUzy;ŷ0]3T#*K9irR(OeNLF'D""@D@D " "DXYYYLarӌۥ9D""@D@D " "DQ4aNLF'TԚU#ÜvόS,aNgFsbD9|S.se3:@D "Z q嗟s}}yp@ŏ?{ر6$bL?ϯzгo> =|w8G'"}­>G1ގmGDoݫ<7hn[??gOFD}fDĘkk{ٳnt?v϶T Ag}||r_wO?qi~w_<O޾b4l[עh]zcq/D.~/@`P9VlXt^XN N|9D""@D@D " "DT7}eftAEY^NJ0]f6㴏Y9Kss/;r.ӟI"@D@D " "Dv/SQIENDB`xgridfit/docs/o-top-500-n.gif0000644000175000017500000001477410643720040015141 0ustar peterpeterGIF89a^   p "# !!##%%##%%#3))**''++++%5..)<0044.B::4L>>AAFFFFKKQQVVWWXXYY____``aaTzccddffffhhiillmmnnhhrriiarrjjssjjttcllvvwwnnxxxxpprr||}}~~lwwnxxpq}}~~~~ƀă}~~‰‰ȿк޳!Created with The GIMP! ,^; H*\ȰÇ#JHE2jǏ?r )2#ɒ'ETYRʑ-]8F7kI=i)t(PFT4iPOYt*TFjjS0ժXgђj6ɕ)U[']w΅;.߻~m{ ˸.‚#'8oߪ-WÛ;nYd9Cok&6Aij]vvuToy'xo/}3΢?c71ګ3.:xwl?z]e؀h `"^ QLE(VY: ( آ(c3Zءq<@BD(Gh#WC޸$6IDƈH^aUd9&ardLw}Źarw|^|q6u|s"Zw2j'LMgsEVqᨩsUjzrAip~**ݨJ*_h( 쮓>J^E~i+6K-V뫚EZ܊ng9`zbv.BY&hNo[NI/]ˮl?4/ 0Rpg.41 {q( m{ƬmB۫2}V+'[nJka3u֠~jj"w:]r3 7n tw#pr'NJkL?8>.%[nǘS n\y蓷ꬷ q~:颗ߞ靣{I[;ɽo>z.<+//Ncc)&@ W?"-߈;^a#02#D 8 o35 n AEh5 L}- lRX5A7D2)Gxk& X9-˒後L؈ ;4 D놷p3g(B# 7ؑbZ$ѺiNHJЈ4" ؈ArXvWG%2\zׅ {NpQrd$fIDdkHعr`x,YRv" JR.8;f#*G2s)^&7I Ю@5Ӝ璽*Sк>!)< YaV^oL9?K̵+s)B.fnM5&nΠ7nq|`o85qABк.x續jOSpuPORטӶů8k70.p+bVLpk7Txe}0+2{ XӪLx0$bNְU [%fqj_·AoW|n~1r4qJdhFןӽ<+ނ^Wvyc&/hs`4~d 7Y3u|Ň64MVaϘ3g)'iH?]#hDӛ>m/ԨFXAbDkՊl  {:Ҵ1sDOֆRg0Lg89s>rPuv3{bvU-n4W+]tsso~rz?2leWٛe}KS:ᝎ5#^f/c EVpS< 2M%?]qX4dzߛ{-=7}'t7@4[?r]~w]@3]ނ>~X=Hז{YiYvrL\9}iȆFْkCY!J9),Y&I+yI铗9”KșԘٔhٙX{~ɗVx[)_G9(giuiىp 9{w{ٝO}XوINٓ)빚 )LyyG9ٟ񉟉{!< %|fi ɜ8l1 bfu١Y ~Z{7;|JVڦ*ȠO:Ze:Y[ZZ&ê)֥Z}`jsg*h1xCjqxzighnٜW]SIrZ} .أzʭگꯜڬ ڪjɰɫʬ+i+:l*qkk!Ŋ# %px[+;.K0K2k 99ʨ@+׉zB{Ӫت x9;X[ڭ 'k+ Kc+c+Ɋw7Y({$K,zKb lwY+=T v긘zBYAL{K Z:j˯\;y%; z;ir[~K*ۼ;k-kjPk[ʳDޫ,?Z ++J +۵ێ/{۽kR) , ۶ kK ܷh-;nK\RIqʚ",!.0춽<,OR@$`Paq$pP..D&!0E p&1a0v+9AW oXq p[w/?0Zyo t*pp P0*p۫Ḫ0!< P24Lc N$6!1H` GKʩ{N7A ! `ǐpEh P DF=BP@2Lj[˿z<,AD٣4q~ M p``  Hc^N!"Qq1TP!FFvk;LqP  NDZ0V  l@pSKPNMPLp)|:VP@rm7WoЧ[ߜ]{g{.}K͟G^zݿ_|vwl?@/F:P, |A%&oA 1$p@Cykl.kB/StQżb< 3_D m1Hk,G4R;xgridfit/docs/xgridfit.gif0000644000175000017500000002227210643720041015157 0ustar peterpeterGIF89appp! ,x +&q[SrHn*f狦q͞g4=`'9\^LGp 9ViF$7f3Zޓupi~`Uwz]m_buntc%Ʊ̀ЊɆ_&᥿Xk|]: P^?DNSP†(1aAA:E#7zhF.SN s@le;w ʳ89U_IDI+: iϫ`rkYg @S7$jtQ (.\@kRash]|9ŀmE ج^ъ͚Vmf͟=yhШS[Ԣz.(lwClojJ7঴P[n1X>a2ȘOK_M::M_t۹c~92 #y$}ok!ˎ]Wݔ Aǀs8Ux]-Hw j݄>8yZ(aarH $h" Ȣ,(*8&c _;ȢX/&Gڸ$P d/>iXf\v`)dihV!pm`6ߜlGU6Uzz(t֧ 6vZWyv꠆3UnrY ~Ѻ腢jNi{k,B)ήO [)`mj-~["뭺k[[[⛯+NK-G)@v7n kr&,+_.(\2|/)|sPQy@-!\ tC?'E@Q'ǜ0ϜRk.{g5i?;_PBwAsMܕ.mYl\sn38 ]×;޸擃=W 褗5!@4K鬗.@BwDRLSyݐ\6?yy@\9w vT~W/\߷wLKE?c3G)B(/AfAh~ąnI|% KJP2XA0z [ '@zNzS[q<PκX] -{ pDov+nn)\*GQwR ' .q[Dĭ#m VE%7bg#cG6nS$0. iSAEcߒ1j -nh"LJP}!#Iv͕08KA)et/YpGR$bfg>lAH3M4*#Z&NUE*ʓـdrJ B6ؖjrȝ҂9Osv'0~Ӟh=GDM~˟v ތ ph>%*5QT"0tVLQ*QxQ鬏/az( %/u st)Pӌ4CEXQY˦-upTgTf*VTVGҧQ SˬJMؖ,bըr\W5`v+^-aaP@|Y7Vlf?z\*#+D:PJW섥AWkVrv Y-pC{,S-lnbuҺ`_bK9z6dWnWnv{+ֶ-Ŵ'9azQh}coj/\􎗼-m`ump7ǽ5"*v~6a-\mԕg0W^ &.n7]Xx j;OMO7!ҁC|-@s~EnKر8f}w}q37-n`y}sa-8%6Qk7w]9m.nS靹 [^m/L.oe4v$f*ؘ[:w.W90wX f+'lv/>b;2v'f˺{x{yRG >o`|q~_^}g=uk4Y3)1c~䮽ϑ/ɻ1'~ )x}{'owW g~-(To|?>~~~~8P}'jr4cC@wr'V'؁h~ h%f7)MAb 3Uw~32bIy2@OG'Js0DE`T?LH8Ln%XJԄB5AWAVTV"B]W`u@EzÇTRKWXU8s~5XtxUx({W$TmOO{uQGXNuOt$QPP8PxPOP8OhN ŊUВ e(؊H*AUAxq<canIp|۸8Ԩs؍u(X@Tvwe7ETP~H(zHȅ׸9 k)h)]9 |5Hfg a ) <-!,ֵ9|0]z+)|.9/ik5yk %w![SՌْ7ɒ|w঒8Hٔ"x->ycaW!\ ɔHuE9I9G\锸7PhI004~JّaiK9th`3W6k`hiHӱ0i{Ic^bY2xi2!xg4Iٗ@ذnǎQIwqyu4HW9UG!s٘9y ɗ@ C'@B:);9w˙i牗̩О9YVDZJ#8ֳٟ ڠ:ZzڡC)e$gTrRc)љein1sٜ.s9#'9VF-jG ) :k/Nꁽɥ" SyO@SUBA(h[ڤa4rZ_vJfyY K*eyj{j@+Y乨0J虨Y\f!UJ 4֕zH)j-V#jڥqUfg=@ʧʤsz*X_k( ZuJx=T*5Њ<mfOD8yhT sueϸ=c5uKjlK k ,ێ[Q 4؞¹P@^e5ȳCKJˉO;MQۋ|XX5VX۵\cKȞWdX_gr[Pү/k K(.K7{89)۲63۸'5F+^ۇ ˄ ytZDz*ZJc!ZhʙPA7Z{[ʬkъK%@IVtj˓ڭ k W\U{ϗ1˿R [Nh۾++Z1fDlڿ;LKZBUL3Kiٻ*<_s7"k <⧾5eEl;<=lP|^ )źJ1C8 ,oڙ[\,zzJ>Y$}<Ȅ\Ȇ|ȈȊȌȎ먅 Nr`LYl*+|qJMwؑH YGI!]$MGmu Zi," I%4#B,>5ʹ -FM-@6N2U09.NUN Eo7|Ѕ ?A>7/{`q>1-7crpLX;g@" lC}-@~uN^fn蕎V.ꗞ~葮'Ы̥m,~NDgZ}Sh hN鼞^>^R | ~؞ھޡ;CE盞B<jhBj>nN~u> j^ꧾΎ~+9^n2e$S?< #@1Mt5ymm'q J) /ξ@7oG%&..,:RMkh__^;O9O{Hb/o?L鲎~q:cMOtнznUb>i~O ɵ4̢Fӓ(оѳ-OO7v 1R-PJG= WѢu>OŐ-eGlekUIy._ hF&W+jt(KKFu*LM$4$Hh'wUbTk-WmL;(ܷv՛tYnMH®^4Ҹ{*r_ʖ1_̹3k3{WRusx,@wIxڶ)=6nڹ'=7hHVMpk?FË^]oޑ% R!yǃ??~}x\}u77b'w6PScUށr8_ *!w"~X"H(`\0{\#26j+'#AId>9DB7PF)TVi%\ieZNe`edihlp)tiv㠐@#d&2`@2衋BK6yn|N8{& A7*j!ƷN$*kjZkHJkz^:#~Jl*iJb)&BCF kʫ:Z.fknت螋nr;lo\,"lҋ+޻/&c%4,K˰ګp')[0/ !4$I|%.&<Ж+74G IC6C#aGP;1KÜ-Ȏp84@l6|uD?]v\?<7 6k]r?:KO췽@+ bd@J@)N*؅1PDA2`Є L` I8Cư/\ [Cj5OXڒeA)4 x^%}ԷPIҁ!G{QT>Pͥ@~dED1O[4v',S'-)PюUd]Uj֤S%*)1b,yݤjȢWQUm-A:Vu>[1)%gd"dNeiQ\26mYAJVFl},XUP+6/ #[¦fs,lQ{" fJ;z]2]7K`45Bt]OX{cͯ~QLt.-Ll*:bVc gq< c 22i| $;סM`~5Umz;S>]۸VC5mt,tYnWvtWhх;߬.JAgoXvMqr˶:J'!=!+~q,oo%ǻ($8y~pvW/䪞aNskĂXCb"» 㕑3a_vj}ہ71G@3$! c+'cul>y!h#+9ID~Q' zէ$cE2J궆'wߐӞ '{ ȏ~ Mv=8Gs{"/ze/}la߭` /+ByQ@ gi2D*TDXDȀ4$6CDHB0d >~"| # D*&-HCYcmw`|@LJjdvIn?y@zc (|v|DE}gW{٧~WH{[HG`h~b؅'z"RJvc>tul nuImy R{?rc797a|H^X$W_wY舖8׈LWNY#fcdvNU`m2ZaVd(f;lpX GuSs{guU'h*ag)Wg9wQ1&d#cY茏Vg!Xs5xkh|׎0WQ&ocPa&iwmzY 锍H}ꔋhmoxZ(kq2&rkcg5QvhNv8lwm)56 't7xIu1iw9ruEx5ܵ /4?~WgI<ِ5wR рF 6~x+'WM)/u5wXyn IWCsRHu9"?7^WQh8)o)qYWwIW8atBtưEhRNg9jI7i)(i1 qX  $))9i AHwNiٖ1gUhJ*( ')ʙs额}@Hk9oUgr6 ʗw[:9iJ ڠ|D:Zzڡ ":$Z&z(*,:0}&s2d|mנ<:6 |IyK yy7`W{{w2̰ 0ZvǤY}QOjlIg9y27#>A`yyXz&ʧS(HHs*MZpq:`p[Fx秘ڦI8Ryi"opqxGZ*-W[ Pj jsӊ+w:P:jT# ;xgridfit/docs/A2.gif0000644000175000017500000000571610643720037013612 0ustar peterpeterGIF89aF ###&&&'''((()))***---222:::AAAMMMpUUUXXXbbbcccppqqquuu! ,44¤àݶ}r7-`,yS`nqdx+&hKElSalGX%)7D!Q`V*ɮ1ph7ny)&u j( jkXJڕWYOa}}%PkMuۊw̕XټR_d0 20^ȂMX-MmWY,ńa{:-s 롱==v¡dG^x?fmaM Hsꃌ';+V .ךN&2rnxPoト\""BU -AZDV3x;q,U[\ ,eWڌܢʏ6n {]̸#5x@ `d\y_׃0BY gr8BsW<9saN~IebO|j3zKB ҠW;iFhG;UX΍nAulZV hOBdGJԡ@7@f]$MR `ERTU+pP0 DΪxTFX ha3ֺN,pO0k\9WxtU~EBQO4A=_-Bl٨Cq:VU3ς7kz®­-:) ~K?N nj!:Q -OԤFuT͍vUBwXUtzrNy WeoNj^㚶x/[&ixS(`#NaG$Y/yBކf~{}z`þƷlRɗ垗Qzη~>O.܀6ứ҂ \YHN[Ȍ).|6wzna Avy G >oͣzs]w2{lrc5Nݳ2sma`wyϙ u/T֟ס|%/tGGeߺs^_<۽~kr{ݫ}wŞ#=Jo>wg<߻}xN'^ ګyBB/3~3>Bq;/9]bNl~K#.9|`>=N;ڛO>~Y͛շOgkҫ?}K_O?-~w'?Om?Gxw#yu|Wxu7zy?W~wGg4|7~gWyއ~"(~ 5 H)/(~1h3HBLǃjBW.ՄNPbQ ;xgridfit/docs/schema.html0000644000175000017500000003321611354363674015015 0ustar peterpeter xgridfit

Using the Schema

Programmers expect compilers to check the validity of their programs and provide helpful error messages and warnings. Xgridfit splits this function between the compiler itself and a schema--a file that describes the structure of an XML document and can be used to check its correctness--that is, to validate it. It is a good idea not to rely solely on the error-checking done by the Xgridfit compiler; and there are various ways to use the schema.

The division of labor between the Xgridfit compiler and schema is roughly as follows: the schema checks that required elements and attributes are present and that elements and attributes that are not allowed (for example, those you have mistyped) are not present. Where the order of elements is significant, the schema checks that they are in the right order. The schema enforces naming conventions, making sure, for example, that glyph names are valid and that the names of control values and variables are in the correct form. The schema validates attribute values when it can: for example, when an integer within a certain range is required, the schema knows about that.

There are certain important tasks that a schema cannot do. It cannot validate complex expressions (like "(a + b) / 2"), and it cannot check to make sure that a named value matches the name of a <constant>, <control-value> or <variable>. It cannot make sure that there are <function> definitions to match <call-function> elements. These and a variety of other tasks are for the compiler.

There is a certain amount of overlap between the checks performed by the schema and those performed by the compiler; this redundancy is partly due to historical factors (the schema did not acquire its present abilities all at once), and partly because some checks are so easy for the compiler that it seems absurd to omit them. But the schema adds considerable value to what the compiler can do.

Limitations of the compiler

The Xgridfit compiler is (perhaps uniquely among compilers) written in XSLT, an XML-based transformation language. It is basic to the working of XSLT that it responds to the elements it expects to find and ignores those that it does not expect. If you were to write this,

    <move>
      <point num="a"/>
      <myelement>
        Here's my very own element!
      </myelement>
    </move>

the Xgridfit compiler would not complain; it would not notice the presence of <myelement> at all.

Ordinarily this is not a problem. Xgridfit does complain, after all, when it fails to find what it requires. For example, if you were to type this:

    <move>
      <poit num="a"/>
    </move>

The compiler would report the lack of a <point> element as an error, since a <point> is the only required child of <move>. Note, however, that it does not detect that "point" is misspelled or even that an extraneous element is present; rather, it fails to see the <poit> element entirely and notes the absence of <point>. In a case like the following, on the other hand, the compiler would report no error:

    <move>
      <refernce>
        <point num="r"/>
      </refernce>
      <point num="a"/>
    </move>

The compiler ignores the misspelled <refernce> element and produces a MDAP instruction, as it does when no <reference> element is present, rather than MDRP. The resulting bug is likely to be subtle and hard to diagnose.

The compiler could be taught to spot elements and attributes that don't belong, but only by writing expensive code that forces XSLT to perform jobs it is not designed for. The schema, however, is very good at detecting such elements and attributes; it would flag both <poit> and <refernce> as errors.

RELAX NG

Since its first release in 2006, Xgridfit has been packaged with a variety of schemas: with a classic DTD (Document Type Definition), with an XML Schema, and with RELAX NG schemas. These different schema languages have very different capabilities. At present, the only schema packaged with Xgridfit is RELAX NG, as this is the only one that comes close to describing the constraints and requirements of an Xgridfit program.

For example, consider the <delta-set> element. When it is the child of a <delta> element, it may contain a <point>, but not if it is the child of <control-value-delta>. The <point> may be omitted if the first element of the <delta> is a <point> or if the <delta> is a child of <move>; but otherwise it must be present. These complex constraints can be expressed with RELAX NG and with an XML Schema, but not with a DTD.

Here are some other oddities:

  • In <store-projection-vector>, the y-component and x-component attributes may both be omitted, but if one is present the other must be as well. This cannot be handled by either a DTD or an XML Schema.
  • The <line> element must contain either a ref attribute or two <point> elements. This also can be handled only by RELAX NG.
  • In <move>, the distance and pixel-distance attributes are mutually exclusive: if one is present, the other cannot be used. This can be handled only by RELAX NG and the XML Schema.

There are many features of an Xgridfit program file that a DTD cannot check; there are enough that an XML Schema cannot check to make RELAX NG an obvious choice.

RELAX NG comes in two flavors: an XML syntax and a compact syntax. Since it is possible to convert automatically from one to the other, both are provided with Xgridfit. The compact schema is named xgridfit.rnc; the XML schema is xgridfit.rng.

Using the schema: validation

Xgridfit validates all program files before compilation. To skip this step, include the --skip-validation option on the command-line:

    $ xgridfit --skip-validation myfont.xgf

By default the xgridfit executable uses xmllint (part of the libxml package) to validate program files. Error messages from xmllint can sometimes be a little puzzling. For example, if a <point> element is omitted from <move-point-to-intersection>, the output looks something like the following:

myfont.xgf:740: element line: Relax-NG validity error :
                    Expecting element point, got line
myfont.xgf:734: element move-point-to-intersection: Relax-NG validity error :
                    Element move-point-to-intersection failed to validate content
myfont.xgf:691: element function: Relax-NG validity error :
                    Expecting element variant, got param
myfont.xgf:692: element param: Relax-NG validity error :
                    Element function has extra content: param
Relax-NG validity error : Extra element function in interleave
myfont.xgf:691: element function: Relax-NG validity error :
                    Element xgridfit failed to validate content
myfont.xgf fails to validate

The first message pinpoints the source of the error: xmllint was expecting a <point> element as a child of <move-point-to-intersection>, but it found something else instead. The following messages are superfluous, as each ancestor of <move-point-to-intersection> is marked as invalid and causes its own error message. The lesson here is that the first error message generated by xmllint is very likely the only one you need to pay attention to. This is all the more true in that xmllint exits on finding a single error, without validating the rest of the file.

It is simple to use other validators. James Clark's Jing continues to validate even after it has found an error, and its error messages can be more intelligible than those of xmllint (though not always!). The message for the same error as the one caught by xmllint above is terse, lacking the unhelpful clutter, but it is also a little less informative:

/path/to/myfont.xgf:744:34: error: unfinished element

You can use xgfconfig (with the --validators or -V option) to make Xgridfit use the Jing processor; you must specify both its name and the location of its jar file. For example:

    $ xgfconfig -V jing#~/jing/bin/jing.jar

MSV (the Sun Multi-Schema XML Validator, released under the Apache Software License) is also highly usable. Its output is verbose but helpful:

start parsing a grammar.
validating Junicode-Italic.xgf
Error at line:744, column:34 of file:///path/to/myfont.xgf
  uncompleted content model. expecting: <point>

the document is NOT valid.

To make Xgridfit use MSV, invoke xgfconfig as follows:

    $ xgfconfig -V msv#/path/to/msv.jar

The RNV validator is fast and claims to provide intelligible error messges. Run xgfconfig with the option -V rnv. Here is the output for our sample error:

myfont.xgf
myfont.xgf:744:4: error: unfinished content of element ^move-point-to-intersection
required:
	element ^point
error: some documents are invalid

You can use the xgridfit executable to quickly validate a file: just suppress compilation with the -x option:

    $ xgridfit -x myfont.xgf
  • Note that Mac OS X version 10.5 ("Leopard") has a version of xmllint that does not accept the Xgridfit schema; users of this OS should choose one of the other validators instead. "Snow Leopard" does not have this problem.

Using the schema: guided editing

Some editors can validate XML documents in the background, while you edit. Among these the most commonly used are Emacs with nxml-mode (Free Software) and </oXygen> (inexpensive for individuals). Emacs and nxml-mode are both in the major Linux repositories, making them simple to install. After installation, find the nxml-mode schema directory (in Ubuntu it is /usr/share/emacs/site-lisp/nxml-mode/schema/), copy xgridfit.rnc there, and edit the file schemas.xml, adding the following line:

    <documentElement localName="xgridfit" uri="xgridfit.rnc"/>

Then, after you have loaded an Xgridfit program file into Emacs, type Alt-x (or Meta-x), followed by nxml-mode and Return. (The mode can be loaded automatically if you know how to edit the .emacs configuration file.)

Now your editor will validate on the fly, and if you type Ctrl-Return in a variety of contexts, it will either complete the tag or attribute you are typing or offer you a list of possible completions. Errors are underlined in red, and error messages (displayed at the bottom of the editing window) are mostly clear and informative.

Guided editing with </oXygen> (see the editor's documentation to get started) is similarly straightforward, relying more on context menus than on keyboard shortcuts. Either of these packages can save you a great deal of typing (and therefore a good bit of time).

xgridfit/docs/points.html0000644000175000017500000003553310737044553015071 0ustar peterpeter Xgridfit

Points and Collections of Points

The points that define outlines in TrueType are numbered sequentially from zero, as illustrated in the figure below, which shows both on-line points (those that a line must pass through), and off-line points (those that determine the curvature of a line):

boldface o

"Raw" TrueType instructions refer to points only by number. For example, the following code positions point 20 in the o relative to point 12:

PUSHB_1[ ]
12
SRP0[ ]
PUSHB_2[ ]
20 5
MIRP[01101]

Code of this kind, with references to points scattered through as number literals, is very hard to maintain: even a small change in the outline (the addition or deletion of a point) would require that one tediously search through the glyph program locating and revising all the point numbers.

Xgridfit, on the other hand, encourages the programmer to name key points in the glyph and store the names in <constant> elements at the top of the glyph program. Here is a set of names for the o illustrated above:

  <constant name="left-sidebearing" value="32"/>
  <constant name="bottom" value="4"/>
  <constant name="bottom-inside" value="28"/>
  <constant name="top" value="12"/>
  <constant name="top-inside" value="20"/>
  <constant name="left-stem-left" value="8"/>
  <constant name="left-stem-right" value="24"/>
  <constant name="right-stem-right" value="0"/>
  <constant name="right-stem-left" value="16"/>
      

Then all instructions that change or refer to points do so by including <point> elements with num attributes that can use these names (though they can also use number literals, variables or function parameters). Unnamed points can be referred to by naming a nearby point and adding or subtracting an offset. For example, these elements refer to the top point of the o and the off-line point immediately to the left of it:

<point num="top"/>
<point num="top - 1"/>

An alternative to this syntax is to use the offset attribute of the <point> element:

<point num="top"/>
<point num="top" offset="-1"/>

However, this attribute is deprecated, and an addition or subtraction expression in the num attribute should be preferred.

The Xgridfit equivalent of the TrueType instructions that moved point 20 looks like this (lc-horz-thin-curve is a reference to the control value table):

<move distance="lc-horz-thin-curve">
  <reference>
    <point num="top"/>
  </reference>
  <point num="top-inside"/>
</move>

If the outline changes slightly this code will need no revision; only the constants will have to be edited.

Xgridfit defines various collections of points. A <line>, defined by two points, is often used to set vectors. A <range> is a collection of contiguous points defined by two end-points. A <set> is an arbitrary collection of points. The <line>, <range> and <set> can be defined in one place and then referred to by name; thus collections that define complex features need be defined only once, even if they are used several times.

A glyph consists of one or more contours numbered sequentially (the one with the lowest-numbered points is 0). One TrueType instruction operates on contours, and accordingly Xgridfit has a <contour> element for this instruction. Xgridfit also contains a <zone> element for an instruction that operates on an entire zone.

<point>

The <point> element defines a point. It is used in all instructions that manipulate or refer to points.

Attributes

num
Required. The number of a point. This may be a number literal, the name of a <constant>, a variable, or a function parameter. To refer to a point in a glyph other than the one whose glyph program is currently running (as you may have occasion to do when instructing composite glyphs), use the syntax "g/p", where g is the ps-name of the glyph, and p is the point being referred to (it should be the name of a <constant>).
offset
Number (can be positive or negative) to add to the point identified in num. If num is a variable or function parameter, Xgridfit will generate code to add it at run time. Otherwise Xgridfit will add it at compile time. Offset must be a number literal or a <constant>. It may, like num, refer to a <constant> declared in another glyph via "g/p" syntax. This element is deprecated. You should ins tead use an addition or subtraction expression in the num attribute.
zone
The zone that contains this point. Instructions will take note of this attribute, when present, and adjust the zone pointers appropriately. The glyph zone is always the default zone. When a point is in the glyph zone it is generally redundant to include an attribute zone="glyph," and doing so may also cause unnecessary (though harmless) code to be generated. N.B. For instructions that deal with lists of points, include the zone attribute only in the first.

<line>

A <line> is defined by its two end-points. These points need not be adjacent. For example, in the W illustrated here,

Capital W

it is perfectly all right for points a and b to be the end-points of a line:

<line>
  <point num="b"/>
  <point num="a"/>
</line>

Points c and d can be aligned so that they are on the line defined by those two points:

<with-projection-vector to-line="orthogonal"/>
  <line>
    <point num="b"/>
    <point num="a"/>
  </line>
  <align>
    <reference>
      <point num="b"/>
    </reference>
    <point num="c"/>
    <point num="d"/>
  </align>
</with-projection-vector>

When a <line> has a name attribute, another <line> may refer to it by name. You may name the <line> the first time you use it or declare it by placing a <line> element among the declarations at the beginning of the <glyph> element. For example, if you declare the line thus:

<line name="line-2b">
  <point num="b"/>
  <point num="a"/>
</line>

then you can use an abbreviated form whenever you need it:

<set-freedom-vector>
  <line ref="line-2b"/>
</set-freedom-vector>

If both points that define a <line> are in the same zone, you may use the optional zone attribute on the <line> to indicate this. Most instructions that take a <line> as an argument allow one point to be in one zone and the other point in the other: in such cases place the zone attributes on the <point>s. The exception is the <move-point-to-intersection> instruction, which requires that each of the two lines it takes as arguments be entirely in a zone. For this instruction, place the zone attributes on the <line>s, never on the <point>s.

<range>

A <range> is a collection of contiguous points defined by its end-points. It can be used in any instruction that operates on more than one point: <shift>, <align>, <interpolate>, <shift-absolute>, <toggle-points>. The order of points in the <range> is not significant. Example:

<align>
  <reference>
    <point num="bottom"/>
  </reference>
  <range>
    <point num="bottom - 2"/>
    <point num="bottom + 2"/>
  </range>
</align>

If "bottom" is point 17, the <range> begins with 15 and ends with 19. But any reference point in the parent element of the <range> is excluded from the <range>, so this <range> actually represents points 15, 16, 18 and 19. The same is true of implicit reference points supplied by a <move> element that is the parent of the parent of the <range>:

<move>
  <point num="bottom"/>
  <align>
    <range>
      <point num="bottom - 2"/>
      <point num="bottom + 2"/>
    </range>
  </align>
</move>

Here the points in the <range> are aligned with "bottom" after it has been moved by the <move> instruction; but "bottom" itself is not part of the <range>. The code above is functionally identical to this:

<move>
  <point num="bottom"/>
  <align>
    <point num="bottom - 2"/>
    <point num="bottom - 1"/>
    <point num="bottom + 1"/>
    <point num="bottom + 2"/>
  </align>
</move>

The latter generates more efficient code than the example with the <range>, but the <range> is more flexible, since its endpoints, its size, and the points to be excluded need not be known until run-time. This makes the <range> ideal for use in functions.

All the points in a <range> must be in the same zone, determined by the optional zone attribute on the <range> element. Any zone attributes on the <point>s within the <range> are ignored.

As with <line>, you may declare a <range> in one place with points and a name attribute and then refer to that with a <range> element containing a ref attribute:

<range ref="r"/>

<set>

A <set> is an arbitrary collection of points, which can be used by all elements that can operate on more than one point. Like a <line> and a <range>, the <set> can be defined in one place and invoked by name elsewhere.

As with the <range>, points in the <set> are excluded when they match the reference point(s) for the instructions that use them.

The <set> has several limitations. It is available only for elements in the <glyph> program, and in macros. All points in the <set> must be defined by constants or number literals: variables are not permitted. Similarly, reference points must be defined by constants or number literals, or they will not be excluded.

A <set> used in a <macro> may refer to a <set> defined in a <glyph> program when the name of the <set> is passed to the <macro> as a parameter. This set, defined in a <glyph>

<set name="bottom-points">
  <point num="bottom-a"/>
  <point num="bottom-b"/>
</set>
      

can be passed to this macro

<macro id="align-to-baseline">
  <param name="pt"/>
  <param name="al" value="0"/>
  <move distance="baseline" round="no" cut-in="no">
    <point num="pt"/>
    <align compile-if="nan(al)">
      <set ref="al"/>
    </align>
  </move>
</macro>
      

with this call:

<call-macro macro-id="align-to-baseline">
  <with-param name="pt" value="bottom"/>
  <with-param name="al" value="bottom-points"/>
</call-macro>
      

Notice that the compile-if attribute (on the <align> element in the macro) tests whether the "al" parameter has been passed by determining whether it is a number using the nan (not a number) operator, which returns true if the operator is not a number and false if it is. The name of a set is never a number, but the default value for the "al" param is the number zero.

<contour>

Specifies a contour to be shifted by a <shift> instruction.

Attributes

num
The number of this contour or a name associated with it via a constant.
zone
The zone that contains this contour. As a rule, you do not need this attribute when the contour is in the glyph zone. In fact, it must be very rare indeed that a whole contour is in the twilight zone.

<zone>

A zone to be shifted by a <shift> instruction.

xgridfit/docs/q-no-delta.png0000644000175000017500000001023610643720040015313 0ustar peterpeterPNG  IHDRTbKGD pHYs  tIME,-SR+IDATx]ϫ,GI"$y H$䍙| .\#hZVr]BEDEj6FuQ! Apr"jYD b0r1]tWU>s}Ouϩ_2A= *dpK,@Hi* IJy` maOu߮}E$A A2@$AȒÈ-ߘ"U[VD mkM׷$QAjlf]ҖړE<}꾱L".$-A&MPJ%dnw[|$z&@9EQA 2DUrꢏ&EJC j tm'H'H=UȚ$DH0Ƈu& H# |nfLɶX:~/uϪvg3Zii4OKIbm=;9o\|}]x۪Cui1OlEXC#2I_ʀu*l k3_0fg'瘗ޅM$t$Z6I5K!2!\~u_We ϱpuB$-%IS7t/eC.r`Ud`6h  <І$ͺkghZKIgkgklJ"hg'IIֶ|3n]3xsf0A%ASL0dYI')+˚3os.Lwoa:m˳ 4qH t-铴%aN[hm]%!M_?GO|Lja '="K挢-"k K(Lі!D#޶$l.ۛVx%c.9H88SI@"$C("0; h٧I^8Uvզ61m ل,>ɴ"ĐTV'ڵuim~I OfooeZ ѱσC= ,lUmH ^o`܋d y|H4+\.Wݚ2IHRL73 Ș޺GbdpS!<]F(`7dm2QH "(٧WVhڮe|(j}koj(d{ڬLEB|ZVu,ZdH$Y|ї=ֱlwE>H7:/˚,@>#$q!hR2<>Fypuj8aʞC ffD]:€%jCwI :1+#CAK" jLk9 93CD"~wC:3EjsdmWcx-jL~G|-/@fjн>u,pYnRSZg,< uLZN5z# 8^nb t}Nz.Y$y9w<kz0+47w#89TϟV^p=]˟O>1F"=Z2 IYRm/t3Ȗh¦Е|o3a"Ugevyd( #SyVH0dn֤uօ>=$)f( x) ފYn$K<->s?e=vxBه/g9X>oW-亰券g>[&QЏ ZrzϭVՒD H @$A !m%L$>}7fA'(Z[6I7y4v٧L|AKߢ} ,#ó Q?uI5,@69N쳝\d Ӥ6Yz-4CװS7b(2t: m ^&w 1١Vz w,5pCh౼SM2Ͷ>~Nq4]vvLbD=Tu@{gH98} ]G~~g͒&zpn P{tG߲>4cڻVD(~$g}e& HcoB0M0QgPUo&KdlIejuB(G)ʤ&HmǴ%5ЖD Lvv.0O:[>ѷKsɗMFdIw}#enHl$ѷK6Dѷd@}dGZ&9e76z]#UQ$3fz= FGwQ.Wb`A efrTd%?"bJ% `Ji1 ,sq)/4rqN4uUa,gmod*L k&2ѴBVX7UlOgS%G;v{X`%s ]H23!3 !"a℘k!@BTdg2$_< Sd1BRY% -5>Wfza_eQ쳊.nT7=!\OR 03bK7)[9RO$rdLctمRruwRʒRͩ>GP/_MsSC d|ы7 6oWVJڣ3u;RXds̓vϬ"02Bxe _R$d)aYOus/0,>[[ mXvPY7q I~m ̡z 4MϤiZufi 9H׽7;\ٷKӴ2οאLR-q}KO5Z/ Qy EB?T'/ tC伋O$r\2= <О> R%iu~j$%4p|IWO"*pC%t,3 qA[2rk}~[@SOczGo|3ƪo=7羀yxg|'#Pޏpo>~EUo "hpo؛ H d  HG@ bb쓾yۣ}N7> "4&C13@$A A2@sӓ ( 7P2 H d  H ӷ:PM5h2PgL@ 4A܁8RߖubLKRd fեqI S(,CW=55uB$!)+H?7gj'$QwQ[m5M]h۵ c@okZ=v[yr9cmSK>SIŞn\j*at= A2Lnݺ(v ` (ozZ]')Ք}Jڣ3Nm)iv32ߤfLBDQo:RM Xgridfit

Expressions and Formulas

The TrueType engine is capable of performing simple arithmetical operations, and it is easy to combine these to perform more complex operations. You must always remember, however, that TrueType arithmetic operates on F26dot6 fixed-point numbers, and all operations return the same kind of fixed-point numbers. There is no way to obtain results with higher precision. Thus certain kinds of calculations are impossible in TrueType, and you must always be careful, when combining the operations that TrueType can do, to consider the limited precision of the intermediate results that get passed from operation to operation.

There are two ways to combine operations in Xgridfit. One is to write expressions rather like the expressions used in other programming languages (though fewer operators are available); the other is to use <formula> elements, within which operations can be chained.

Expressions

Expressions in Xgridfit resemble expressions in other programming languages: they consist of numbers and identifiers coordinated with operators; they can be simple (e.g. "bottom-pt + 1") or complex; Xgridfit parses them according to certain rules of precedence which are worth knowing; and the rules of precedence may be overridden by using parentheses, which can be nested.

There is little point in describing the syntax of expressions in detail, since they are so familiar to everyone who has done any programming; instead this section will list the operators, note a few peculiarities, and present some examples

Operators
First precedence
andLogical and. Example: pixels-per-em &gt; 10 and pixels-per-em &lt; 20
orLogical or. Example: pixels-per-em &lt; 10 or pixels-per-em &gt; 20
Second precedence
=Equals. Example: pixels-per-em = 15
&gt;Greater than. Example: control-value(lc-vert-stem) &gt; 1p
&lt;Less than. Example: control-value(lc-vert-stem) &lt; 1p
&gt;=Greater than or equal. Example (where v has previously been declared as a variable): v &gt;= 0.35
&lt;=Less than or equal. Example: v &lt;= 0.35
!=Not equal. Example: round(control-value(left-side)) != control-value(left-side)
Third precedence
+Addition. Example: top-point + 1
-Subtraction. Example: top-point - 1
*Multiplication. Example: lc-vert-stem * 1.2
/Division. Example: lc-vert-stem / 2.0
Fourth precedence
-- Treats the arguments on both sides of the operator as point numbers and returns the current distance (in pixels) between them, as measured on the projection vector. Ordinarily the argument on the left-hand side of the operator should be the point on the left or bottom; reverse the numbers to change the sign of the result.
Example: round(stem-left -- stem-right)
--- Like --, but returns the distance between points in the original outline.
Example: absolute((stem-left --- stem-right) - (stem-left -- stem-right))
Fifth precedence
oddTrue if the argument is odd. Example: odd(v)
evenTrue if the argument is even. Example: even v
notReverses the boolean value of the argument. Example: not(v &gt; 4.0)
floorThe greatest integer value less than the argument. Example: floor(control-value(lc-vert-stem))
ceilingThe smallest integer value greater than the argument. Example: ceiling(control-value(lc-vert-stem) / 2)
absoluteThe absolute value of the argument. Example: absolute(control-value(lc-vert-stem))
negativeThe negation of the argument. Example: negative(v)
round The argument rounded according to the current round state. The "color" is the <default> set with type="color" (gray if not set). Example: round(control-value(lc-vert-stem))
round-gray The argument rounded according to the current round state. The "color" is gray. Example: round-gray(control-value(lc-vert-stem))
round-black The argument rounded according to the current round state. The "color" is black. Example: round-black(control-value(lc-vert-stem))
round-white The argument rounded according to the current round state. The "color" is white. Example: round-white(control-value(lc-vert-stem))
indexReturns an index of (pointer to) a control value or variable. Example: index(lc-vert-stem)
control-value The control value at the index represented by the argument. Example: control-value(lc-vert-stem)
coord The current coordinate (x or y depending on the projection vector) of a point. Example: coord(stem-left)
initial-coord Like coord, but returns the original coordinate of a point: that is, its coordinate at the beginning of the glyph program. Example: initial-coord(bottom-point + 1)
x-coord Like coord, but always returns the current coordinate of a point on the x axis. The setting of the projection vector is the same after the operation as before. coord is more efficient than this and the following three operators when the coordinate of a point on the current projection vector is needed.
y-coord Like coord, but always returns the current coordinate of a point on the y axis. The setting of the projection vector is the same after the operation as before.
initial-x-coord Like initial-coord, but always returns the original coordinate of a point on the x axis. The setting of the projection vector is the same after the operation as before.
initial-y-coord Like initial-coord, but always returns the original coordinate of a point on the y axis. The setting of the projection vector is the same after the operation as before.
variable Treats the argument as an index of (pointer to) a variable and returns its value. Example: variable(v)
nan Returns true (1) if the argument cannot be resolved to a number at compile-time (e.g. it is the name of a variable, or the name of a <range>). If the argument is a number, returns false (0). Example: nan(v)
point Causes the compiler to regard the argument as a point number. In a <glyph> program with an offset parameter, the offset is automatically added to the argument. Use this operator in contexts where the compiler does not automatically recognize a number as a point number. Do not use it in the num attribute of a <point> element, as this will cause the offset to be added twice. Example: point(a) -- point(b)

Here is an example of precedence:

     <if test="pixels-per-em &lt; 10 or pixels-per-em &gt; 20 and
          round-state = to-grid">

Xgridfit breaks the expression at the "or" (which has the same precedence as the "and" but occurs farther to the left); it evaluates first "pixels-per-em &lt; 10", second "pixels-per-em &gt; 20 and round-state = to-grid", and finally executes OR on the two values. If that is not what you want, you may use parentheses to alter the order in which constituents are evaluated:

    <if test="(pixels-per-em &lt; 10 or pixels-per-em &gt; 20) and
          round-state = to-grid">

Now Xgridfit breaks the expression at the "and" and evaluates everything to the left of it (inside the parentheses), then everything to the right of it, and finally executes AND.

Fifth-precedence operators are all unary: they operate on a single value. If this is a simple value it may be separated from the operator by a space; if it is an expression it must be enclosed in parentheses.

Binary operators (those that operate on two values) must always be surrounded by whitespace. This will not work:

     <point num="top+2"/>

It must be like this:

     <point num="top + 2"/>

However, the whitespace may be any number of spaces, tabs, a line break, and so on, for the spacing of an expression is always normalized before it is evaluated.

Note that when all of the values in an expression are number literals, constants or other identifiers that can be resolved to numbers at compile time, and the only operators are first- or second-precedence operators and the arithmetic operators "+" and "-", Xgridfit resolves the whole expression to a single number at compile time. This optimizes the most common cases, where a point number is expressed by addition to or subtraction from a constant.

Formulas

A <formula> is a list of arithmetical operations whose result can be assigned to a variable, a control value, or any of those graphics variables that can be written to. The format is like this:

     <formula result-to="minimum-distance">
       <divide dividend="minimum-distance" divisor="2.0"/>
       <add value1="0.5"/>
     </formula>

The <formula> may contain any of the arithmetic elements: <add>, <subtract>, <divide>, <multiply>, <absolute>, <negate>, <floor>, <ceiling>, <minimum>, <maximum>, <round>. These can also occur outside the <formula>, but they behave differently there. When one of these elements outside the formula lacks a result-to attribute, Xgridfit tries to write the result back to one of the operands; failing that, it leaves the result on the run-time stack and prints a warning. But within the <formula> no attempt is made to write the result to one of the operands, and no warning is printed when the result is left on the stack; instead, it is assumed that the next arithmetic element will take one or both of its operands from the stack.

In the example above, the current minimum distance is divided by two, and the result of that operation is passed to the <add> element, where 0.5 is added to this new value; then the sum is passed back to the <formula> element, which writes it to the minimum-distance graphics variable, thus setting a new minimum distance.

The <formula> element was added to Xgridfit before the expression feature, and it looks rather clunky in comparison. The same operation could be performed more tersely thus:

     <set-minimum-distance value="(minimum-distance / 2.0) + 0.5"/>

and the code generated by Xgridfit would be the same.

xgridfit/docs/fontforge-old.html0000644000175000017500000005420211311436615016305 0ustar peterpeter Xgridfit

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.

xgridfit/docs/A1.png0000644000175000017500000001324110643720037013620 0ustar peterpeterPNG  IHDR >%bKGD pHYs  tIME  %.IDATx{PT?V_,^( I:4PT9!)c?M31A2G%RFheINx D.xg"8xZvsv߯s}k?ehd$՜Q#AωH~F&d &1o?HUc3.C=E (r<@I AE-AiE-AQE-AEȠ@PAQdPApAQdPApTAQdPA%H /˗q t_֯_k׮iڷz͛X@=_V(=~9VVN>hVZ҂t ]+>J-_XXJDD}??͛79،_z}JǷX`rҤIE 5kŋ ~5CHHH$?SVkڜGqBXPȠݾO?YjK}}ވ 6=ztʔ)%%%555D/ʮ_~Y9r1V__oAsss(99d2%''Q^^[O0!??ٲeD>nܸ> 6XdơCƚ_ >daa!q?dڳgOii+W򩩩XPʠ$v[ZZ^^^ޡl۶|oqq1cرcDzju:]\\]O&?*>""7o2x5j[0nݺEDs,X?;{,q;wvY 1ED'NRیV((U1ޭ6o|[ߕOD;vPP]~~~nnnf_BPJ"zwc|ߖ3\]]}||@ףjt?CT;JED?~Qv7=[G@n\o1bDLLLNNΒ%Krrrf̘! o߶1^:c_zAT*ٳۿʮ"Zb𴨨<=Z4kkkjPYe }7xCJ:,۷ow+ZT=>5kVe-\P/++;wyfZZZ>__U믉(%%d2͙3rss{)hCC0`„ Jv[lٿmۄ h7nz^paȐ! =ۙ!!!jEUQQVCBBg1j0]\\ CgouAc'7Zl$c~Gxt֭j#F.F A{hLL8b)R1P=~˵#0yk׮AP9rwO8q˖-8s<ݯ'NXYYIAeSNFi-A!|kcǶʑD$Q*Z~ӦM8T|```@@Ν;q hu՜QAߗGymTv?#j3qBW$\|yРA|sb9cݻ ) mPvvϞT]~.\ AȀop"!LMTƵȑ]zƹr\,Y"Z 8j 3fDo-/|rT*S.]ZDHǍ', j{.11qƍGp@DD42\$0"B-Aeڗbyʑ2" i2BdZz / AeT{xx 6,::zڴi9998˅ QdPu ʌ]TNP3#Q*|9:O$ _!,0O*SG*퟊&o32XAQűי@IIq{:ShJ/PPD g'*}h?į ~fb)I~ M?^HAeOBPy7F(@jXF J}8> Aτns]{ Gp7QG)HMRA{D(IIIAAA<{xxORGJkkk}||6md2>yg@F#S4;n E/5D,ˇnevꔙ¥~~G";v;vVpUN^ݯ\tқobŊ~GMjR￯jW\o! 3ZR'ɦ޼yoꫯ;w~uԩ4 JHH5kVtttNNclڴiuSTݫ|Stt#G̷L6 Umo߮hO_Ii+Eݻ7))/wG-4u"S98}@}ii!CĀ {n;_i݇$<@=g4ʺ-U]}b1uu7zzZ!Z)1~螯_ݚZGkfjZ`d՜Tsuѣ%@=K=˩2Ϡ Ýiko/'{h#rSLv>łE쏙7D7v5B~*QHi2JsA3%:I oVʯn9[ȠrM%K*{G!%qRZs_Li] h588o(J˯+AeqZ:ʙil}>흣\ e9Cܿ۝8SCޞV/)R^nP:NFġ$)GӉ tA{9 As"<6쥗^vZKtڇЋ lnnxlҭ,[˫1 'N,[mPUsOMM`"1ck.]>@Lo R[nm㊊4^' Ja\__jju```ff[?SVkڜG IJJ;{G!7.O:]H22DW2d"cǚ ""bÆ G%dɔLDyyybVO2׷&99]Dž&iϞ=W\ $CYyG!ਕ+WnݺUR*>L̠ hUUUUUӧ ~J?Xx͛7cuuu<Ϗ5BPWtqqqӨ(":qℕ*\P+(˂[=k$8v {Avȑ#oܸ4x`&C0'<=====QH<)٭;!(蝝=x (Hys\Ct.^56dEqzgY@DǏg={㸝;w ,g26dE!(n$"Zv-_7&&F%ԩSgΜve~9|Q J飏>gW?#bbbrrr,Y3c q"Ln9@y9s渺vUto}ӧ-g tk~&dv${{{O<񄟟b~ݞs2)޾1|"ڸq^ϴ9'NK^=uZ+g(7~x+,C";!h.l0̫%"S8b,5#rsˬ~nHA#5Ӿc F@7M(u.^Gs+Z7}_52ŷOjyG߹B2(GRui> $3vUfwsyYK$qT`lgm?#S=饨dߋw3QA-?'<`,.#G*ݗ lv@޹S< ABP@PAAAA   -(Pv!~dP:Em@q$"~9/B(wN/Qn*zcďN@P (@P (@PA@PA@PAAAA FR">_m9FBuIl.IENDB`xgridfit/docs/n-hroz.png0000644000175000017500000004342510643720040014575 0ustar peterpeterPNG  IHDRTi6bKGD pHYs  tIME :'n IDATxu\UIAA\[U_uuuUX  UNRZZJvT s̙yy®dE@C (~@!?@ P@C (~@!?@ P䇃EcYg#@ PSD&^j'_vXME iX1xULkX>k}'I),O ;|rܱ~yw=il,~b֖W/ڭ`|oe_IHJ#\PeU a՚ea=WcC&dWTs5/[8˟ :k༙~* ߇8}x\lo$uکWJ d٣|xĤfӇa_-df\bJ7//\6}<^W9^\m٘f/v2*&Ϊ)?uK3ceE@h8d omQ1/NtʼnשQ1>ދ~ujo</wuwvp8YaD_,]hӚ}&*xHL,|7b0X"Q+ T[5@(~Qj?Gx'Q KW{[p/S̟5%xzm?{"l?8 y{#XXUBrҵ:;i ~A5BKD?yXIx%ESGɤ~YgOf90n;l/ ^s7Y_^sknOLNMZS0g> zT_0[}!X, Uh^붛@(dҦK_DBHN{2 :(eG**ai@<2fZ/ KCbzy/ KG"#^E$`i(mg"8 Z"bheu%T 赪jjb?SkKJ{Wp`umeuM-4zbrzLBrCc))IL5H$V.+HI`jsz/\dm5ۺc߷\~gu KԸ\f-^[wܼ4}?sitwo[d/P2}vw- 5Eꚺ.OJknni0;ks. S~]-$#-ebf;#MUptD SĔ { j(yw(ld1)V())kL< {/2tRE?kj&[pެI\GY/ Z[BaC#g.^+^SJᰢ8{q΍%GO^PQVrH"Ι:apvRlg|>竩(Y[%};7zNH$r߷Ўrn_BgMYlycӝijl\D]UY&B&N]}'y׳WI)PPmfd{zm06]JW{UQVSQV=m<˵03:;Hl۰L0J8-9( S3kWkjn`0j*|> r\.o˺/b$M)1-t뽤$%&8֣ &[[ <>B|ʶ.C9٠kbCqࣥ ˶<3~jy r~?NRjkgN7b 3T]S~9nݸP[PANE4:}F [2o jjq2'_@_wZ:W,)Znsn'(h{\Q{[Ku5_Ct$o"pۺI)g >/?0jPj/bX<?MuR̲05T^Nf (tum/X4ƝGEZ᰸y3'Y[ò{_\~{ڥClĪdW >sA0 Ǝ :&qR)+$)I CB}KˋKWmܵj㮳Ť 1ۏ`ZDBm}ÛrҒ*u 98VZJRWGbKIP?~~L|LfFopkKt&<2A@Uu4A͌LuC+ `þ/v?d#74/,ITWUΝ:q4Q131PQVHa0lʌbC(`001dsyVWդZZikEm̬̍Q` wt IcS3=6,]0ʼupg5"I #<@ ;HHP~#x<>_YQnS'&x2PG;WШ1uHmmT YEYZEYܸp5Ue3c5C# :eԌ.rvJIcg#\G"1Lmx]mƦD(7\/_OyCبGQT1 H '{N4Ay|>@AU;}>p(Q|D$v<~A=+WUKjSǡ!gJ'n顅&h:Pulgmfif(/w&~#IcCrC `iOUuȘWG֤P(Y"ğFy%q?O(ဆFbN#Y1{"ewE?_.+#ݧ܎FNKs7T> xx^kMD>`Gj&U(~#R3l٣+?  fO H>!*&.?Q! nH@_,;%'n!IefEڷctwN̮8S)ܛ:; FJ?9̓?_.'+_0gW";?I{BMcr FdMXߙHuMݎ}ǞY7cG,xb#GN&IȞ# -4ҼR)|~? 3t4}#, 6KN{3#`"A2Wf9'G:S]Ss߱_6po ;Eri}E <6pA?XFr/-_$[oʿ~AK6jwV,H .ؾ_m1KQ^S =^q VS331/밿Y3'$)IhMP_W}AQz:ZD"M[jEmgEi'4w}P@SsKIY_'&qO<>{x_twnrɋ_>yROnjn0eɼL:_]Stw߀u>uߗ rj*y~"^Qܜ_+%fHIJ EUD"fb{GwQWUڐen[}j.iյuiyz(~1Ƃ;p (,%]4ۋ_=.eB܆|/FP|EE'wwo&񀲇պL Xtwl_PM]- :xArU{ txnWxjp}HK-t[8.16;qT [ t=ws:ܗgpPl@8,IqwؾNeTP_FAWSb4[Ƹ-0pJxOMLu P{WoWyK06d|,c{(^AVF➟kpΡl[[0MM8ׅAƏq$\Ľ'ao}~P~R3IߓDd2 &I&şKnAe/ru =zlwCğG<| pwq|s釿 J9VP]d){C#y a4\Z^NGD(cHCI@zᮎѱP¸-}BWF:y D[s7_z(LF7mv!P?`dž@ P??{OB3*HOcen2붫,(~BMU@@C (^+'}(fƐRbWl@(e薻O$amA @ P?#@W/}G 8+)pamA /z>_A4Jr@8c=h| =/~ )EYQ@C (~)(:@ھ_ ~@!H? +3@M Yo>@C ~'/>d_Rs[e7 d_SS\ A @ P?3Lt{R(~{Ku&$,@C (~߳HPa3n@@C (~O?%a-B N4]OJ$J @2ҼF,,?@ PF }od_V"?_C_4P)(aXapn~@յiKa/2r*"O#Z=C P@C (Hp2cg{]ϣa?| P@J{(rZCEOXM$?@ Po )*ֈm{B̴7DX(~߻0J@(xL+r`/JjU?5@dexp_Dr拦}pp?_DX3S2`n?H$>G@F @[p71dg96t{7'z+ ,CAW]$"]Խ>O!P"b{"voYE*H?%O{b#M]Idr|>+ bt>.%'P!N@l#ċ2b' GFuذBҊJʌ t-͍;`22su uXGJ+cR$h榆D" ع9#b(nN/Y]vqIdߏwgu y)Yv-6xT`+-/4]m=9mh#Tb/Ho 붷nܕ|k2k佧9yx^EU A0<  x<>#+} `OC;?/*.3zBg0b1p8b1x{"#h=q; …F~BKxB`1  i) `0|Mck(0}BY$2`vܘذQYT>'-3PIA~(!QNUPTRZVBuuRML9uQn );sұSb )#+Eh`^%}|϶o,x# Y5֒WƬ+;vBHCIqifۢw1I'hj|41:6Թ!}G9uH~N1n[AQICcPAɞPzk|gT@V AM9byC?ҙ#J%>795EXٷ EQeEyyMbrT*Ep̼Yt4UL xcxX,3b0dgF!V`r<@R<܄tFĿI ay\:;1YlMuEL"\`Cy<~Ss T US޳xAT}M%,6DJ¢Ҝ,t?Ƿ4*"M"  J >Y̫??BoHKx8Ⱥe78Z~t Rҳ~uh߃;l,^fhHII:t'YlvuMݤq#̝*uj棰ȼ-UES.xJ t`sej(/^R%/,#9ZlU sP}.(bQasƚ/yB%U`3sİ0a))|K<ntޭYE%e3{_<|qy~" PR۳m<;W fO4mllp "'y?w">~u%'[w`3cWo wu;s⏽/Z#/^ @P>+Zhޒhc-ٜL3Cۨ']iEbJ:D3bX[E|>`>;gkeE%)@´]EQ~hˀ? $q8Õ!Pg=(jr;Y>'ogv`☖>QzX,PWS]ES]߷dzsq<# aAꪪ*J xq1 rřQ9"kjZZhX,F qj4:KʄQ-[}j_ʼ/‡ERϣF[55c~]_*|$bLu]=Mkz{u>'I{N:}c]ΜhK\BrtlҜi-0!7*pèCcӴ59T>gXYKN*A*y$!T gy"K=OJ}椱3'5KK>z74Jp8P)_q4@ f4޶ݡ{"o[Z :oۧ`0I$" ?a-(7>WN .] hgŴedcH~$M#o[df:foa2`0l6[EIk#0L>URWRlB&Sp<[+S -Ag0y\x|>q0dX,6@q]A 82sW-ڴhqTIeaKF?ZE\ T`X <`+MWG/)4vo /#1KaxGag4d}_P,'+fs^Mqc'CqEeѱt:L[Cd}Q؞m>hkCc0F=x0,rcD S#sKKIHg점IacyrQs#뷥dcyJ \W+q9t- ֮޴~Ny!63tȠ'ϣ]D?y1}hZfؽ@;rGsMؾ;e|s -Ubi_~-c=i)7ZY--?pmml-׭XHڲ/}2OJlѯ߼'%)`g9@/`O,Jg`PT<];Z1ҔdB yE$K \[K+fa+QUQ^QR*/'{b- AL3啸'5`n!7~ C7N,VfR/bϟ80͙?yUPTRx,]MQQN'gkͫ{fuCDP9o<_WZ1;qq#c<9bq؜**&qy&FA!7/\'4Q\:(/gdp1F-_G?4\FQ^;{#Ic~R$6ʝ|]z ,) u*:C!Q_?**qYws[')Փ.}]-΄-Ԣb)X,Z#9uorԅ: 5%g|l6'8֬245 EZol67},BSS^WUI&`g;ƂGQ$$]WOG&$(sOPk}tKidp-O4p8\ |O~OgEֽ<ݹ˲Ii$aMPkCBHW'DW'{A2|pEo.-L/:D$]ix<^A^@KIJΔYybt0 BqSƏpsZ]<}8mHD[gRd!B&ps>ud7AͣZ/~nm./h:{j3CA^2soZRU08W"WPwa_d}RB <6ys '-l}R\=wle~w9;y6{QCs%Ο5 EQT9t̙S茫~w&$< M|@y<`k+xID>E HEe~Ypm=|uDX˷]IDsj|!4u|AÖ5ݼ|UuM6CPyϚ\Y]CgM"|jyws?#ƥ!JK#X&hL2d"/ 8RX />zdMI{p^KP)ϣb G@!I$"GJdɑ %<~apoTWWU27$L&! H΃mQH!68 c4Cwx,`UHKW//w.Uwqq?x,@<^ fVV"nC~խ-Lh4z~a tz/ʜ,Jz6ueH|W(F@+k<onlVŪ(i VG ID"o}Ib0,CTۧY]SyA)I}'YO{'ʊ Ur]eeǏ;w*g08Y9R|u6[}eWExnW,Қ.Co$\.(_FZ(9-؀FJl6EDQB&|yƽZǺ;އԤ% u޼/(Ni&(@Yl'H Y9o,7x/XlT/,\.}/>5j{7o^b%$>Hh/#'#}Uy9Y s)H y AdQSPTr&څX%hkgGDZ6kR=5XY#PGu1ߔ&?x&"4ۏ$LdΔ^^3fKJPI$bjL&k++)6R޶˩=Mj&auրߙkUqѓpje5n7 ~u8"co?lromasWPT[/(*{[I‰DksfjfPGA0kBLpڙK2$":rGY3/eѓ#ݝ}X+.<Ď!>="#+Fr6P¶qꢬG`9V/><:dU񊒘B:s5hvE?`踤 7o/:ձgU~pwoqOLDTܕ깱>NjE&zN:ZhsrJdp8DDCJc=gX\.twGG{\.r-\UQU /rg7.d3.,;TEIQ8_NI .Yjbn:%=+8%sZD ek|SJcn;oAD/(*}WS[rg-nܓ }*R"`~u4=$&6tp J#^edkÆDdmt\ MJN71,s=[r =%3e6̯} p!6QGKTEYOX,dEu"c$̞s=x_PT8f/]-[6tp'/^-B*pOYE$v=+$%=z`ok)c%b|D eމ>}};5uY9mRJ) =,[OLTof?qIssۈ ( ϊ r+:p~(~yO;+[QK `)gً  WEIʬy>U{mjiFa_a_g]?J#^y^XluHxYYW휱' _REeurO}&X,)$&g=_9\gb} -3c_W4=tfoG ny!,DP"c()abf?A%xEݱ@m;I;* pk%H}aN@߯_X\6nmamwY"IDAT sF1|fumZm̍Y f6~S^\AZښꑯz^:ڦ)voHgGn\,bΪҺʂ Y$ڡgJ;aC"_%t([Fȋ)46!I/:xLKH71leꂧI019ݐ, -g Y^'/\Ca0 [FKJ:jbTJuϕZga#R}R }f-Sge9ˀ!u?*RX(B̟轤Tqre˽} uv(,]Q%F:{I&:PU*$tM´u#3lI+qcfi(s{q)mTwMSۺpFVfp2nd ?Hv/*6wzLN' w.CQK~<pϕI8uYQ7~oGWl{˟4;lKjr~pwU߿:T^;+'/^R`6ms`uUen2t_ZG͹ wc?my}{lgTUgPRKj8usZU\,T,=e϶o%MDw?U-ٞữru/fY&NPuw\.߳e,KqV:Jx6βM9`чj%l?نO* G twZtlRY+:6>YU=uWSVY.CuURTRERkAk3X[ _͘!L,HH#:w%uX:Թ+wA@v@ @!?@ P@C (~@!?@ P@C (~@LJ㢱%IENDB`xgridfit/docs/x-vec-a.png0000644000175000017500000000442010643720040014610 0ustar peterpeterPNG  IHDRcbKGD pHYs  tIME 5(nIDATx흿oZ}" (R70kc$B@ 6N20 Ѿ]ʂ*ĔKiQN T#R\4k8u|o\ؾV30| MU.ٔ16T*AX ^|@(lZuojJQYFzr{q ly^gZ'qIHl_]]8U?z߭}}Z$pCBefR.:9YfM̌RfڇU* ,`펞da״1oK~~ۨe~~~ =@pc?P+~?-Zv۞kS]X}$HOV;k;i$':c?kV]X(n/}_z/"PQK{}^=ؗ~-@f$ JDőBSY?_z-eRA`kt Z36w]~-,' # N0<ӡ8t>jKPEO~h ^GatG>r-쏣 .^ w/u']%R kJ?DuqT: C#~HM>`ꧼ,u7%?#U|h]hWw' %:Wχyv~#eV:stC=RQ^]BJ>̉g6m%uQsKƟ59,TP{ѽvZ3 vG?y-!̀OU^C3p:BsBIV0" ״N"S~:i~2}o}zDmlg&vv1bo}zX|3O4؟Fd?`?VjDW]V{lvW*':~~~~U%"{ ƓD1o!V{j?`ﶡno@kdG@~਷ߢH~\N"[펞?^^Hg&:13_ z*݇=PnCN`e~㉉\.766655h4IZ>z/^`'_|9[n?\D0P5U,>YR_DT\2nۉ$(r}Kb,Z ~qB$ "GFV+]L{3ѭޜyJC +NV%19\$H?pV ^ZR%8kg;+; ݡ{f_\4J%tz/"fqQ=`h?[{YaoځjnIJx$@^~>;~ ށoY= ~~~p~j3j? kd`01LLb #@k nIENDB`xgridfit/docs/x-vec-b.png0000644000175000017500000000741610643720041014622 0ustar peterpeterPNG  IHDRcbKGD pHYs  tIME .8j2IDATxolSUwƨJu:pq (3"ŃJ V q2'ñhO4Fy&D24^f1nk~?/w_9]~Fp1!(0~v9ݮҹ I/A^d!~`?~`?@p>jׯzIVXa4@}}}KKK㴴g^'!3r,3G}YuuO?sΎ8JfMɓ'a``ɓɫY"3F^H/ hD<11UYe[t]oٲ%//OO?vڎ;bFEOaL~?SIjDTXXPn';Th_T= cTEN=sB_ު*j0󛛛wu=!]YY˗ϛ7h4.^+jjj/^,bVVV,8rHIIh|衇=]yrɒ%Fq޼y>h]6M={X,[*#"7 sӦM ,gd!WT(SoYY٢EcHCN`w|||`` y 󎜫Jy-ˑ#Gb 2׿yyy,aO l޼Dzjx*Ð*--mhhoVV֢E***DQ|߰aCܯ/'W^y%f{'5LNy/]Yh{{tQOOLat6My{F6B]v]{W>qAjkkC4L?wʕ+FcYYم d^z>/^$v+W\zutttp8DTWW_544]SSSOYfhh׿ {j߷o[o(++7n(** {A{{{__7|sСW:u*ZK|GgΜYvm Ȱ{="?wu= ?K93**//6nxƍi# fggcG՜c`0 %KFz Ap\aG[fbd2=>/>`08p ZQD bZUUUr#ÖݻWlmmmzNNjGzCa|-[v~!77OWWa'(}K=yj\쟜d/7oNҜ^z> *>ottnժUG|&)^B0KL&jv:I:eM}^o;`EYH Naq2SرC2IfsJ6bnW<8ZN]T^tI4u) @c~? ij$ LW_C J<@"~?Å1!&79x^1p qގ=`? 1`?8~ uHa?d^ MZ|HO^k'X=-HOROZq/-D~`?t,fQ _G~`"<jg4!{~`??z!;К:,=@ƛtԯ=P֑7RlgLq/p[/{ru%3&|51Qo\ #{3g@냠3iϓk׮mݺ$;;d2UTT ]/IRQQ>66o߾gܹWvZAR֯[Ν;_JDD|Wr{zz0:67%MLL|Í999/_Eog}VRRRWWm۶u֝8q1t:o޼ϺuFFF{N'E,s_\%h:fȷz ,ժ?CM@92I}"<_/w>=nǫx&</>2 לzd?xC$D% Ǧ,bMaYJ9 [r z" >"bt$oI~X_tWc[Lt@F3<ȼ^֦DxS{`z[{d":_V_h#iv^o/fa`7`ily~7Կ~Zi?10L%o*oGzk 2~~`?~`?@?_5DIENDB`xgridfit/docs/A1.gif0000644000175000017500000001172310643720037013604 0ustar peterpeterGIF89a  ' !!!"""###""1$$$%%%&&&'''(((''8)))***,,,---...///00011122200E333444555666777888999:::;;;<<<f???@@@nAAA>>ZBBBDDDEEEFFFDDcHHHKKKMMMNNNOOOPPPQQQpRRRTTTUUUQQvWWWXXXTTyYYY\\\]]]^^^```bbbcccppeeefffhhhiiijjjkkklllggmmmoooqqqmmtttoouuuvvvwwwxxxyyyzzzvv|||ϗםڞܠޢ㥥ꪪ򱱱! ,o H \ȰÇ#JH!ȱǏ 7 I[&S\%˗0K82fJ6KI'ϟ0}rH"݉tҦPFjӦO^Eu*Ѯ^mV5,Y`LXls˺ve҄vnNyov*`~mr1㍅:^8/ Usw1 3ֶYz~ڮi;;^vSmecIC[yI^{uů L'z9M~{!G;|Qs_fͧ`ZB`o w?65aP5x҅RahwaHX\&"Q*G"@09ݘVtr|nPHdp҅ d94d``deGYf )9P_)t =`-Iw%tM9:Hg戧Fm*Є' )-XA0 b8w 0|'j}ABJX0 .Zct#a( A^% hdA H-NTPp38㛺NF)O @5'LmQiLءa R|o^] M񂵑UF#WQl p«3A%(% p 0"` G Б;w &>y?H+F4|j.wo9|48|rM#&T#8TÞ 7r?.J" ,IhGO'-Ԑ 70 t\ooM+53G O6@‘ TL_ 1C@Fy?F[6w>E7toȂ>`a>Ђ & -U HLx̀!t=C$+؂ n"IBo%#fLC@,ky\n#h+0Q`xHgBa/SLA!T[V@}ѧHM C8b1X".k|~9dY2jӬf @WYkYA2z+]dyY6c+Z2BY( qHBe7z e?;~pEkɦ*Vu¶#m*ե~0]r ndGn6P{Sz"V X!:(^][Vׯ.+s`",mP@LSzxdIÔ-.\;J @0omkݫ+@Ef WW)6, n.C\X`*Kb[)DP<.FaR=#108 :т1Uh~7>9]ix]u*-\BNrbf]Ad YJ>lLEwD& ռYv_[7њG:%M2$~v#m1ڼﺅͼAn/ n˾m^$7c~K_s]$\yaxG(~Dc.]c<,Oķq3)Orj67Nc[~ɭr ( Wgk|G# ?A::!9Utf3F0,)W=9:NEQk&z ȇ^{՞+^yL! 3`8YuX/\ xB ȡ%#^%aPo O{p? yrcvoN12,)=(DQgÌ iȂ~{{׷-CZnj@(~?B(P7~=;9δ8ucc;;1F=/0#ЊՖc 1| ,$=0@"T@!?N??KF#`>q&qwk6mU@ S>[C A!7${0#TB^t'-ǘjH_DGaG FMD TGr@F\4.(; )K`J41!Jt%JJչmqHOLԙKؤMM$N 1jNЃxq6uPy)QTQQQ0PI*RPlً)=uBoإ&! -d "iW٩<)>٘uZ٦7ؐQ귥oI~:'yx1)U}َ`1Yz//C\7/dWbP2'M5[]5{ 4f6j6iuڪy::3;s;;əD<:[ ?c?==?yjB/C4A4dCCH=4ư̪ IaFhFAnq4G[$"0cI$HJTJTvDMtMMNtL2zNB˧q(PLJQ`QQQ!5 p;GwKl{ 2(^~ޑQهfQjW~hKa;[{1};n{_"hgmq[˻ ū˵6hpۼ1l#{7%w{zk{\ o{k;sڨȿKܿiVl) | \nYl!<  L >7;u[x 4F s8콁@$|*ˊ7l9<Ċ{5ko ~++qť\~GlÇLy\„(`KEO2kƒȖqJm`¥\KɠɆɐɣl$ $CpUpI4ЖAMMQeppF!n3$$CpUpI4ЖAMMQeppF!n3$$Cp\&zY&ABP"BIS6¸q_,[vt|}'=V6ԩ wC xcӮjU;vLV~u57_k>z˖~imv>X&e[?jߴiWiWu+V:fV#Lmk#cZ&፹nl/Ob6t]أG>3}>gn|f/KH8^zcWO} O‡<$Dt 湪;V8pnD}6箿yK3܅pdfcXiGGCss/_rCsm(>Zuϗq}}" jyW]ظnݨoǍcs/]ڸnݨS.TTJ=@CFt_Zkx^Y"@&^r.i5x pW`7ɭ8*0hS&., 6 js~ aT" /c݄ljXx`fK+fUU=Cʢn d7:0թI`fn%:Ӿ@iN4-ޡ2cʧ߮㏠pUBXr)RR_]<@^SX`Q6WSh$%%MQ.*itlR&oդ(֙!{b·w[Bz/1iBhkozhڵ5;wӤ(5;v,{zhٚ5 9F.k5k8f¾}{7o_O֮5}}>F1s6l}C4zO+~%ZB!J}o۶o֮ʻ嫯[;7uokŊ ʎ/jlL+  s_{#pxM8*iS~{Q{vlٶmף4x ʾ=رUUN~9yےKc|[V6HhSN1w45vHGou6ֿ`e'OB2uv#KLٻ| U=WS7tuW"-ߔKi>yoW"-{f{B|dTg}S?Gb|{"9zY gx=cYu1'kognnpƑ'M+9o6>!D4*|>!>pcoS[;1uu7%r{9?-󪘹r|{'@_I%hK/W^4ztܽPBaÈ.{|qɳώĪ }Ŝ9GtG7&Li˖SS&^;lUՌÇek5|[ZZyE#|Y7v_9{ӦS<{Ӧ#Gjh~…vo;0Y7#?^u޽K}WyW;΄pf Bc5;w(bE>96DD4 uvҥuMy=[¹ͣO>_VqKGg^e#_<_Vھdљ37}+o "OB2~v sG9C^ o[xㄥ{.`pDMC1CG(pb&a$ bGy@ʸYzG½'V`f .9l EU{TἛ}r_$UgUpE Q o; >wDZ'z>3oSI*C̀V*LSVDՉJiNrU"!2)P~E@^ӟ$ܐ""1!Ǹ!k؎bJ"ưDS !Vj jYBh BM* h& Jb%]*C"3n@ $Da, 4 q bPep1I#, pbQ @S#z rŀ7F8D="eI ZIENDB`xgridfit/docs/Gentium_period_horz.png0000644000175000017500000001175510751522252017402 0ustar peterpeterPNG  IHDR5[GsRGBbKGD pHYs  tIME'jmIDATx흽oW߹0^va%.̏ Q$@Q Uօil(MA^HU&U)҅cSEvGnf ꌇ ?gsDMIgH>sΜW*۶m[L0f,&=/&ŤHYl m,bў0Rɾy5ߍ("Z*)'0ﱐ(NDehxeE,OcaJl+%LZ-yj9mR}AT={DDZ#cH No*Jk+@qSm\6J9( V1EMKZb655TBUnRyuXHj0X~\S9NRKc4LjnCǺ65i,8ٝc]'󞉹TdoX^ lyL3F*=xXXx1q8QLjcXRRکMNOR鴬䬱nm؋ruobu6c!۸BfR,?[Ȕ3>mH^i-]NjEGl$}=~>TR]ʱ k-.P mԤ"_@jyRs -n=oyMJ\I(bSBClH f8jvI%Q'$R -| RicÊ !5qDyɔS٨JzjI%8޼JSOOE4ıA?#I~|ĉrKZ-Gn^K=Hk5j$;Ze(I4kYhmYeJf~% !4uv^m!nS0 Un$r,R[!6& ocVLZny$5Seںu5 kg_O^{{P1ic e&;imV* 5mE}K4$6wW.AxK"5p܄ա 4[hr5)`C^[M)?!*% _l-i׶4K&$XVƯJhBFN-t~EBCjlZjݳ9 /ﭿ]sOR'm[;yM[i *4ć%JS{nIO$["Td&Rz$.ZmcpssOx=zj/""}e[x]_QC~X- "3~C+WnїӺcٲ&b5 kj1#Ju|"^{wŌۮ Plg'JpԠH:OJHl AvZTr{BCj:<3{Gl WJ>8D@YGl"bCjjWPIh%[R`cÈKOkh\['!ImCh1qZV(-ϗ891 5@?yy4\ҚްKyz%RFbqLk[gO5 M.uENe[ lϯRq]M2-Bl3Z C4Cl gRCh$5N^촦}mq>8)60Ol6b# 5v4'д3*jUYQr}z%^W6f,&g I-$$fPZ۳-fm< u걮 M=B;}pZd+;ǪǨ M=׽g3q|όFmZc9=dTg+=zH{Z[<ʁ8BYf %+Wn49_)۟ys,Lx$OpRġ70q(٧Yywa0Q0TR%%!m5o,GMNI-Bs4o, we]N~,e:<~q%6&JΒ뫫r}u 4>@JltT[sɧ뫫\ ר!ּ15TZ,NmEIH)I!zܥ' 5$Np38vwvDf{R`6ljCfFA:/R/N t mIJOy H b`4:)˭QS^~ѐZiV^d`%*G/&rQDV;/?O95Z S[XcF ^kt F}MkH EBғ`#Dpɞ8 1fӨQ/r&{F2켻#zCd/;prHjMV\DhH-U1كYé -6͒Ӄ@wM=BRCɔ3$P%'fP /ѝq{N[hvn)uzf=jnLzLk,JM @5J`\YqX.dݘ-1f{fZc OR[yʋЌm V{g,:/q{a,1i%6Lv%4n(?'-jM)|RChc>jH-)-TJ@j&4Hi c""EΜ(jr@9(P~F'4Gh&qRh8ԏ۱y -xv>N:"ChԦ ~B#Z4F M 6Zxi[n~;U ڈ("y͔آ(GJg"#RDDt8 'JfJn\2RCjk5grH |ڥKN:դ=`\ޖx#0rF䇷_7>lK#3C(Jv?F HlnU٢nh(-Bc-/uz۝<)>w ݹ!0^/eO)H D%ڜ8ImC١o :*u'5568ý1;rL B.E^lԉd؀-4g&5XRHjH ¤T*٦50Fj@R@jTb~λ'Çf5\6uXHj"c]zF˱zsd^g%RS0I[W)>L ]Mz1O襦8^LHi4֨ERLQCjR@jH R1+kԐ 58Vbۜy$.8{nT*)Rm۶ń cbbXtOX,:0YZ55@jH  5@jH  5Y[x 5 5Xo%*IENDB`xgridfit/docs/index.css0000644000175000017500000000061210643720040014462 0ustar peterpeterspan.smaller {font-size: 75%; font-weight: normal; font-style: italic;} span.bigger {font-size: 125%; line-height: 125%;} p {text-indent: 0; line-height: 125%;} #content a em {font-style: normal; font-weight: bold; color: #A52A2A; background-color: transparent; text-decoration: underline;} xgridfit/docs/parch.jpg0000644000175000017500000000677110736450467014474 0ustar peterpeterJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222")!1AQa"qSr ?0 Pu^(4a \&H*v -Yoɀ,lKkXM0tMۅh5tzqD#'ʶ$A,k*9)۱:HiVOy<˼ 1ƪ!ޅ5TU;bI[/Y#uI]{ΊJIP 鞥A$/%{^lo ;!Bb>k F0,Rkh`SVXňD|oJJ9CǬ_*l4PUJ9FRxHn 0) :ֻ2JIy6f aY tE;[r"7\ٙ&ӷ OY8W|m~Z6:X'p)1p!" 1">LJ/Q>xP[f֗ӀlX׎n9/gOikI5aRlW:VFT+G96\~s`BS" ^21yEza[W 7IUT*.2Shp-\vKO*" FǞ+!#`'mcQ4Ld\)+#)_J8]/ySibfUjVo@sf(R|{KRFbUD7O9?PjN/úMtjA{b 9G \}IkfROQck3/Ypkj!^kkxȲ)~KxߊU"xE{ͥM2ܵ]Wߜ+NuEt(Ϧ9N,>*)8}|t8-:0WFC|kiZYְwŞRuM]47!ARf[GY$wuZW wy͋v6}ce;a&? ne)kq;ѯsXlo1e$UN{,>1!)ot*{[(ZWwycIjq؇'e$RvR}+*Mq(ܵFU_yQk8RL>28a~<_S3g? -\F7A8{n+wu͍20-P0KEE.yJdlq"5h9Ȅ5ۘ-ڭX؀$8B|aҦM(m@WДXV]Qg@oˮ2Y\Ts5?Oy-K/RU}|2b%Q5rt\61[94y2ljm;(|QK\y3HYY {_rzL䲿';18r] -^1E^^hůml4q^%WXYU߼*7r2rb]W]8ħ+қN(U8V-Mwŭ2 KbRfl?"oIQ\aXb6cd \AHo߳J6P2QKYJ09ih1ֺFϬ Z^mr7L1Y*[:!qGϾJ 2[~Oߌ $1 p2˴:Tс@/=kK:}Lr/ [<} %^/\u#hp8mt^-WX"Y^%>^ ƪQ6scw~`Kmq$Ypۿ*xy}`]}$ZٺWvRp?$ t+Užr(qV;2#rs3л: lm^Je)eg6MPh,v!FWk\^svlK4\`BfڥJ*wwNV9#AW*H]ud=?IVQwT)6c_KWw81k7_l۳Yz߶BW*(RD 4׎ ٵVwPypn~1 k+"EZq}?8|+6tEY 9'GfwX+oz8 rW`d75k$DB1EQ@2q`gM.Z#рLMB~213#ہH3E~7IXǼ.+n Qyb4Y@=dIABGJ),qF]-!Y:`R/kI03sYۭ01-~Z'׸zEM%' `"GM_<>F~HFwqJDhZ5r$w,-w^->ٲ4}2̀G|^@_d򧖍qSgHn|g9bY]>؋ ε;x:”2(!!Etr@Dl4'}`oı߬Db4٬Dz(['&>258kvSW\O+o|^XVyW?c:[O!IG}OkVJ/ʙed`HQG?x?.Ra%eW$NE𱧋;/佧"{CO.hk9)α# /;j ֿHɵ!7|3aUlJ (W/ iU_E/U֨PWU σlAd4hfsRB"Iyo.aJ@Xj'_h5tNqE%'ʴ,>r>Nl̊^{p`````)S6Ƨ>=|"`A͚56m:sT*aÆN:666b788xر˗ :ԨQC$ 8_.f͚5́\. ppp਌F9z1c6mjoooeeekk:~իW9s&++OlmmEؘ& r9c4{{{u'[d޻v2fggwV(?L&VVV 6|Ύ-rVVֺuz%JbG׬Yݽپ59((hΜ9O>;wꫯ6lhoooccvڜWHH? >5)**Zti˖-bs-FaZMYnzlU}+fQ[#?99yСDYeeeϟ?_n+dsN>oH$-zRtW^1c1&w:̙3`0h̳gΞ=!$koj>|_ "p'Q%%%޽KJJuڵkk.;;9s Rvd2aРA:.))iD +NG/Eӽz|!jժyF.Sh4\!4j( euKӹmݺuȯ) ֭Qȑ#w}W=x <ꫯ8?!B^Бbmm=f h4&&&֮]^ڂ7"СCl$?~8=Vٳ'BhK-2 EÆ }}}-YyfXV^:~xeՙ:,*Iݻw'S6/ 6|ވm"C߿#yRR߼ycYBgJPiiivBttկ_???߲jΝ;C+W2=z4B())14$$I&S{nF|);33S( BB4W7//;;;---ǧdY-nT'''yي|>p&MغwoݺM6e)Sƃb1Bk׮ׯC pwwc'Or9D?P? C'Nj-̙3!ɓ'믿~i2X#,{Y &0{J;(;44͍"*޻w/!t)-[x&HH$ (N_xa0ޱc233~v+//PDB~~9Pr ,Zٺue&Y")>TQfOF͛7G>}zŌz- ^Pa0&ɱF5jԈ0cWf5Y- 2Nt`Yf͚!BCCJ&?gQ63ghZB-yp6۷o_|F27ϗJ{`ܶrל0DzøqxV&-JBlRjBd2>v#ՍSNX#/_^믿BW'e 1F+W ݻ}Zsrr2K}Rm4ȪYf&g?kǍcbG lbn=z^ =ʿcǎHeܹڴitovvvoQ6b&M@ UVVVcHxΝlgϞA&sǏI^z_aÆծ]ۤeKQvii)aX}ƘG%sRZjŭOF8p遻śЍ7ҥ(t9rRQ,7x6Q oXZYY=֭[tӑϖA(+VW7==]Ѽyfu{[BB܄L*Fquu2jÃ- qX X &۶R6I/\PΒ .OΟ?oew^^(l0AqJmB3.]j:ŏ 1מ2))C݀6lP6џ` |77_tɤ'lHd9e߾}!M>>)roBӦM#?$d#;v_RZsիWT&[zmB6;h>9(?_6`nI(޹:)h4N<2iZWwʃ=>y]ez Qs{{{T*D"c֭g͚cz999T`\ 1116`ѢE-e׬YBjYcCHHU0M6ы&u\MFx> έ:f*jݺu G8d:rVϟ? TN٩̔H$#;BbZj1e~Aڱcr'zY͍,9:- G5`T*Ν_(o)Ni]yR6cl$6jԈ"y-t_Phrjn>}` u LY&;}4D4+7Ng,C I;13ͬe BY]xQ KK.\H<<<'O*KJJBh۶m^qa =zv#f3"m`h߾=<샖[pF֯_Q.g:ug###aؐAB_0oԨQg̰K"t:ݠA޽{ =|*ټysVV+;;'NӧSAPvll, o|aaaRm4S=y&֭[њ5k-ܹsoݺ_UO!VY$zp-F 0%m9k׮"tCeJ^ fH^>d2aYeVZ*}MiWƬF O¨j^eIv6mTZZleebYqO/z$XKWrAL&ctaA?P rUp3(NaY->~zsוۣB(--d܁Z"ٿ?,uٴRZ۷JbS ~Gonœy l N@i)C˜F!\jm'Y2&&_d BRh5kU8EO?S +W1iZM3$EEEٳYĢ۽H$Ёeddz(;22Ҟ;wd7n_ʆ}YF֫"~^zEx޽{|Kd2„\J~~>x>ygeeCzz?ͪoj*u6i*b 2 XPNҥ kzo߂C*RBl:',r͛&トI")N9L琞r!XOT eٳN>dŋsFa\H$H8w>"y͚5/cb>\&ED8hRN&qi!oM-ZvS6m GVIIIp Q(^xgXjY51i1>{d!0[SNvӓۓ۷ᒐJ'&NFc\\HDzjbDh4s~!OJlBs;;;n/e/_r:4ʝ|vnK...''֭0R WDDDpԁ4˗/a!m@Dn9 Ws ݻN7o6>5d6&.Dd6 9|g␳ ]=Ǣ#|3AӁޞqACxF]Cǟ;wg8Npss~:crGi|RiBI':88ͩgΜr7cgΜ d2ڍi=zhٲ%?dZ#1ln߾};aKB)[T?C.55)CeΞ=jZB(,,|ц ?2dHrrUBtZjI3fܽ{WP #GEL< :իWu+KD߿? O"8AAA%%% :roɓ'ɖ+WLII!OK B,[[cǎ7^[l!"j'O@L8LѼxV ,xM"~3>|P(C zjiiN:qD>}Badd$ۊK.`3 '/\PXXT*SSS;ֻwo@ H~ӧObb"c5RSS;vz|-ѣGA9s[>|j߿ڬY3j ͛7 `sVpx( ^_XXxƍYfM22Jϟ?g4,iٲ%EM"C RB\.oРv>üyڶm( E"gPPЈ#6mDaL<݃L1d3ܺ8a܉'ƍפIV&yxx=z͚5O~)ee(T"o]}o^8Z>,På8A.//oѢHe]<܇1o޼ڵkݻ+Vѣvbݽk׮˖-㖙Yֶz_\qq+*0'SvII@9r$=!C+vǏÇaѸb \bggy#GГl0kk댌 z)R4##c:;;gggCGFEE}dj߶\.>ŋ:vXwA?Yf!,2G޽{7R(˗GիWUrrr9&6bg*Vf͒J ,͟?~$NF!TvmaͶF D999)J!X^^NjT:yd/J[C+++{e4;#t!XZiӦt;\\\:~_|j777\]e=vXOOOBirn <:w=S@em6Y5al2hׯ_G9rm'9ر#mF"׌KXL.]Jm۶u҅܈8O>i5h4FEED2Rŋ9Ν;0dgϞYֿClܸrGKVVD"矍Fu$ G+U ߤ~Ub1ecf7oˆ Ɩxܸȭ1IDATqvvvE4BoӦM)Aiܸh,))CgA5Vmٲ%Y٠A6 ׮]nAA/^ ],ϟ?1= ///ƞ={,R^z{„ 'NThl!`{{{2eW"lLؾ};dh4Ell,GY#""(Ao߾޽[޽ɕJ+2ݺu^^^u=6 $|@&޻wx|rɆ -0NLL:uѲfavvڵk1eWzzr+)S63>|۱cGzh>}M3!h?@\\=͛ABB=`0deeQ MXDrrH$B&LM_%''WJ5*Fk׮h]reĈb}֬Yl+}xsY[[5-XQFͭW^2BiӦnݺ9;;D"\ެY3|bgdd'O-[@>lVVV}ݻwL~)Sd2\|iHHH`[4oޜg"Lxt@vKHHhٲ%,&O+HfΜIg]֯_?ggg+++oo3fprrru떜\PP` X[[;991Nd.YiӦM4Y`y٦MxС@XɈСC͚5RiFO~yyzzV>eƁ'P fΜiOBͣ]z0'tuԡ/9MjZBW\mڴ6 bSZ@ٗ/_F >ڵK(&%%Q'%% ݻwWYT^zEDD$%%t"P,&{kҥK ݺu l߱NNN#GLII)//q󶳳ļqFڵvRT*uј7nl֬ى'U*UlllVD"oFF>ZBs0tP@x\BqaH" |}}}}}GzS,[l>|Pqqq[FO˯+WJR/_1GhL_i݊,Y"Hlll>ܪU'N(JF۲eYf%&&jڌ7ٵmۖ@|޽06lйsÇk4w֫Wm_|ٹI&'O,)))--=w\f^qqʕ+$'MkZJ_~IYY^ŻMP/Y~C3 k?¤qpp8p纒X/0͛7b!ԦM5kS2BM>rwbB5lؐm" oԨQP3^"@E_7EFF"VZEy_Y[[O62vJ%zD"s˖-۷/++#?jqΝ;!+;;;TP(xV-nݺ"oPu/K?3d,։!??? Sz.]8B2 BT*/^X?1+s0T*[߳W4___gθ/**U{qq1EEEQz,`ܸqB,!W'NdLV!eƍqဿ?B"G%<(!ڏٳgB{_>Lcǎ pѻwo0!QQQsΝ4iRdd+W WWח/_V;,ٳgC` <UBgϞwP`8x`>}oα~/شhl Y-|⬬,ooo8cj?~ܲeK?q_AA!ѣ9S6p(9``e,LFSw@J2ydH檔[t˓{ cΜ9`HQT1lllIE89UM٧N8Pmխ[e7idڵ}RSSU* [Cyn$YkϜ93))IV߽{A;v$|dee.])ʏ?^~}ĉW^tnܸT*??… Ǐ'|UDwݷoe61HO?pZw^k.MV={Cj} (::>)2vJqTp& JǏ'"'ٳg9 )vMQ۷׿䠽{RRɐ pMVZ;wlR$\cnJ/~ǏzGK ׯ}}}R֭[ FyƍUNpC͓{͸tz2i;_|I^h9rM`@ [ڵkS. "&P.5lST H$j՚0a,W/\!HZjư7/99]v]vݵkZVVl2 N|:wd@8***00P&IҐ¸~SL?wܽ{7""5$$dʕzr;Zf9~~~Y&Gn]ޫ0eKN^ᐇĖh4:::zyy9;;ADQrWSq7(** BzM0U$ݻw/c}o(y5kRN:>x(*zvp^߱cG8P> FP(+?!jU*UyyB(**{}RRŋSSS)$^F HkVY*~wrTxņ OIrrrn߾nݺǏGBUFrÇp4Qedeec|]S? Gݻwɓ')`j}=>|8.:aڵX sl&Ν:tի!$Hk]|sl O3gzK`*0S6i֚a Wy;79p!C~ث`0 "b*ALL !0ZsÀBSNeSiiӦ9880UDB\09C܌8lܸ133ˍ51cF=d2YyyyJJʕ+W._ Xgridfit

Tutorial 3: Working with FontForge auto-instructions

The easiest way to invoke the FontForge auto-instructor in the context of an Xgridfit program is with merge-mode. It is also possible to copy and revise instructions generated by the auto-instructor. Here is a practical example drawn from Junicode Regular, in which b is instructed "by hand," while uni0180 (bbar) has been auto-instructed.

Although the outlines of b and uni0180 are exactly the same except for the bar, the instructed versions of these glyphs look rather different at 20 ppem:

hand-instructed b bbar auto-instructed

There are various subtle differences here, but the obvious ones are that the top of the bowl is thicker and higher in uni0180 than in b and that uni0180 is narrower. If we can change these things, the two glyphs will match reasonably well.

The first step is to get a copy of the program for uni0180. The easiest way to do so is to run a little Xgridfit utility, getinstrs, against a .ttf or .sfd file containing the glyph with its instructions (the --xgridfit option ensures that we end up with a complete, valid Xgridfit file):

    getinstrs --xgridfit Junicode-Regular.ttf uni0180 > uni0180.xgf

Now we're ready to edit the instructions. Here is the program, in which we have identified the problem areas by running the FontForge TrueType debugger. We've inserted comments to mark the places:

<?xml version="1.0"?>
<xgridfit xmlns="http://xgridfit.sourceforge.net/Xgridfit2">
  <glyph ps-name="uni0180" xml:id="uni0180" init-graphics="no">
    <command name="SVTCA" modifier="y-axis"/>
    <push>3 1 0</push>
    <command name="CALL"/>
    <push>9</push>
    <command name="SHP" modifier="rp1"/>
    <push>60</push>
    <command name="MDRP" modifier="min,rnd,black"/>
    <push>27 3 0</push>
    <command name="CALL"/>
    <push>24</push>
    <command name="MDRP" modifier="min,rnd,black"/>
    <push>27 24 10</push>
    <command name="CALL"/>
    <push>64 27 31 9</push>
    <command name="CALL"/>
<!-- top of bowl -->
    <push>42 52 3 31 13</push>
    <command name="CALL"/>
    <push>42</push>
    <command name="MDRP" modifier="min,rnd,black"/>
    <push>42 52 10</push>
    <command name="CALL"/>
    <push>64 42 46 9</push>
    <command name="CALL"/>
<!-- end top of bowl -->
    <push>20 17 3 31 13</push>
    <command name="CALL"/>
    <push>38</push>
    <command name="SHP" modifier="rp1"/>
    <push>20</push>
    <command name="MDRP" modifier="min,rnd,black"/>
    <push>34</push>
    <command name="SHP" modifier="rp2"/>
    <command name="SVTCA" modifier="x-axis"/>
    <push>63</push>
    <command name="MDAP" modifier="rnd"/>
    <push>15</push>
    <command name="MDRP" modifier="rp0,rnd,white"/>
    <push>21</push>
    <command name="SHP" modifier="rp2"/>
    <push>57</push>
    <command name="MDRP" modifier="min,rnd,black"/>
    <push>32 39</push>
    <command name="SHP" modifier="rp2"/>
    <command name="SHP" modifier="rp2"/>
    <push>57 15 10</push>
    <command name="CALL"/>
    <push>64 57 37 9</push>
    <command name="CALL"/>
    <push>15 57 10</push>
    <command name="CALL"/>
    <push>64 15 26 9</push>
    <command name="CALL"/>
    <push>64 15 19 9</push>
    <command name="CALL"/>
<!-- width of character -->
    <push>57</push>
    <command name="SRP0"/>
    <push>49 1</push>
    <command name="CALL"/>
    <push>0</push>
    <command name="MDRP" modifier="min,rnd,black"/>
<!-- end width of character -->
    <push>64 1</push>
    <command name="CALL"/>
    <push>57 15</push>
    <command name="SRP1"/>
    <command name="SRP2"/>
    <push>7 10 30</push>
    <command name="IP"/>
    <command name="IP"/>
    <command name="IP"/>
    <push>49</push>
    <command name="SRP1"/>
    <push>6 3 46</push>
    <command name="IP"/>
    <command name="IP"/>
    <command name="IP"/>
    <command name="SVTCA" modifier="y-axis"/>
    <push>60 3</push>
    <command name="SRP1"/>
    <command name="SRP2"/>
    <push>6 13</push>
    <command name="IP"/>
    <command name="IP"/>
    <push>52</push>
    <command name="SRP1"/>
    <push>0</push>
    <command name="IP"/>
    <command name="IUP" modifier="y"/>
    <command name="IUP" modifier="x"/>
  </glyph>
</xgridfit>

The FontForge code looks a little obscure because it does much of its work by making calls to a library of functions, which the auto-instructor inserts into every font. (These well-crafted functions may also be of interest to Xgridfit programmers. You can get access to them via the macros defined in ff-functions.xgf, found in the utils subdirectory of the Xgridfit directory tree). However, it is not really necessary to understand the function calls to see in general terms what the auto-instructor is doing.

We'll start by defining some constants for point numbers: first the two points that define the top and inside top of the bowl, and next some key points for the straight stem on the left of the glyph and the round stem on the right:

    <constant name="bowl-top" value="46"/>
    <constant name="bowl-top-inside" value="52"/>
    <constant name="left-left" value="15"/>
    <constant name="left-right" value="57"/>
    <constant name="right-right" value="0"/>
    <constant name="right-left" value="49"/>
bbar auto-instructed

The next step is to notice how the Junicode b is instructed. There, bowl-top is positioned at the x-height with a control value (lc-x-height), and the distance between bowl-top and bowl-top-inside is regulated with another control value (lc-horz-thin-curve). We'll comment out the offending instructions and replace them with Xgridfit code that employs the same control values:

    <move distance="lc-x-height">
      <point num="bowl-top"/>
      <move distance="lc-horz-thin-curve">
	<point num="bowl-top-inside"/>
      </move>
    </move>
<!-- top of bowl
    <push>42 52 3 31 13</push>
    <command name="CALL"/>
    <push>42</push>
    <command name="MDRP" modifier="min,rnd,black"/>
    <push>42 52 10</push>
    <command name="CALL"/>
    <push>64 42 46 9</push>
    <command name="CALL"/>
-->

Next, the FontForge auto-instructor has instructed along the x-axis by first positioning left-left, then left-right relative to that, then right-left, then right-right. In other words, it has gone strictly left-to-right. The Junicode b is instructed in a different order: first the left stem is regulated, then the overall width of the glyph (left-left to right-right, with a control value), and finally the right stem. We can approximate this behavior in revising the FontForge instructions (we'll ignore the width of the left stem for now):

    <move distance="bpq-char-width">
      <reference>
	<point num="left-left"/>
      </reference>
      <point num="right-right"/>
      <move distance="lc-vert-curve">
	<point num="right-left"/>
      </move>
    </move>
<!-- width of character
    <push>57</push>
    <command name="SRP0"/>
    <push>49 1</push>
    <command name="CALL"/>
    <push>0</push>
    <command name="MDRP" modifier="min,rnd,black"/>
-->

We'll address two more details before testing the code. First, the FontForge auto-instructor regulates the left sidebearing with an MDRP instruction:

    <push>63</push>
    <command name="MDAP" modifier="rnd"/>
    <push>15</push>
    <command name="MDRP" modifier="rp0,rnd,white"/>

This is the equivalent of the following:

    <move>
      <point num="left-sidebearing"/>
      <move>
        <point num="left-left"/>
      </move>
    </move>

But Junicode uses a control value to regulate this distance. We can revise the code very simply, by adding the control value and changing MDRP to MIRP.

    <push>63</push>
    <command name="MDAP" modifier="rnd"/>
    <push>15 b-left-side</push>
    <command name="MIRP" modifier="rp0,rnd,white"/>

Or we could replace the code (omitting to touch the left-sidebearing point, since this is unnecessary):

    <move distance="b-left-side">
      <reference>
        <point num="left-sidebearing"/>
      <reference>
      <point num="left-left"/>
    </move>

Junicode also uses a control value to regulate standard vertical stems, and so we can make a similar change to the way the auto-instructor regulates the distance between left-left and left-right. We'll just change this:

    <push>57</push>
    <command name="MDRP" modifier="min,rnd,black"/>

to this:

    <push>57 lc-vert-stem</push>
    <command name="MIRP" modifier="min,rnd,black"/>

We'll just use XInclude to include the revised instructions in the font programming and compile (just b and uni0180, since we haven't got all day). Since we're feeling confident, we'll use the -f option to pipe Xgridfit's output to FontForge:

    $ xgridfit -g b+bbar -f Junicode-Regular.xgf

Here is the result from Junicode-Regular.ttf as viewed in FontForge, with b again for comparison:

hand-instructed b bbar auto-instructed

It might have been just as easy to copy the program for b and edit it; but editing an auto-instructed glyph will usually be quick and very often the easiest thing to do.

xgridfit/docs/parch-light.jpg0000644000175000017500000000652410736450467015575 0ustar peterpeterJFIFHHCreated with The GIMPC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222"&!1AQaq"R ?Pekw4cAj1[OT:kLD؂R8e$ 2%5hMnP ]q r|oTA\rmT+EbACJ|HdbeEUZ@Dk5T/(u2M)jln_)jԹIHX50ʓ%8N<\hsTQ hT.no[mOP?U[kMB&;Fm ԘZrJҙdE$ʜnN֎LPw/4(P(돚qqJ-dv5l..G& V;9ޡʀwƣCǩ|_6e*8)) Ԇ ih2SaEǓ`ZoP ^mԐ!.wsTSƱoɭ47OԹN+++[`\K=kܸۤU:3g5-@<H[lɉS_2k\~@shPG36R|rhr7O'`,|ˎY:ѫۯԊ.?6rP ޥ46kd IE-e`uW^>$E\9nޣKMC7vQqƯ/+4#V]׸Ҧ$2띱U}#Jӯy0.9Y N ^efrDq_WFC|^V֠j,SI5J'M]47(hPT"::Cw_,AY#(SۙqnϩѲۣQ[Rh ktZ5RcpblAqW|i1U(NTW[ܕREuw{ǹ-2(6X'rֽĘ*ܭ_pVU.Xyk^۽J%YeU$4_&J>!IL|7FP)(3Yr[yhMS|R "'s@7j_ł(.ۭ|MjPq"bZ(tW0 {JW%9"53vQшtȆTAUi- E@hwSbj:ЍlJ뿸g܀&ߗ\Ko er2;Oqz5\mӢ@)x_oܖ9"S$k=@:0*briNd\m+4w!lm2+@Q9BHmJ)N[*eɺ t- (o+.`ZٳYY26(ʨS6k3^.ޤ-? q$Z\uMT L{^Fn FWz߶!E4%EU.Y(Yk~Iͯ:2:KK5.BU7 UbrxTz]tP[}B^ BS}eЮD٭G]EECŠ㊑ʚ,h@9McK|#~#v̵+񿨤V+\dƗ*PRjޏ{2KHT"hgrSt|~#oɗ.m_u\,h_u.8oNfP(4ZMbVF9# R[uK0ެ~9 \q!oXȩMhJة<>2Gwe?JDhZ50Z\d]|=Z}Dcbr7WO- U6|VȽvs.!E*,]>|PE ε6u(k$d(A[8r}@-cQi9Pe{D .5_6~MmL8V%j򲷾.\O+d| M^*s4QGEkXoeT8߫&JeSZH7?$[՗˹O<vRPp_ du'W**ke)WESrWjQ+27tV@dʌX6RcoRC, \DK:xgridfit/docs/functions.html0000644000175000017500000007711011353711523015553 0ustar peterpeter xgridfit

Functions, Macros and Glyph Programs

Functions and macros are blocks of code that you write once and invoke wherever they are needed. The compiled code for a function is stored separately from other code in a font; the function is "called" at run time. The compiled code for a macro is inserted in the program stream at the place where it is called: after compilation there is nothing to distinguish the macro code from any other code in a glyph program. Both the function and the macro can take parameters--that is, values passed to the function or macro from the code that calls it and then consulted or operated upon by the function or macro.

A <glyph> program can be called from another <glyph> program, very much as a macro is called. This feature is useful for hinting accented glyphs if you prefer not to use TrueType components. Like a macro, a <glyph> program can take parameters.

Functions

In most programming languages, the great value of a function is that it can act upon information that is not known until passed in one or more parameters at run time, and it can operate on a value and return it transformed. And yet there is no standard way to pass parameters to a TrueType function, and no way to return a value from it. In TrueType, functions are numbered rather than named as in most programming languages. Xgridfit overcomes these limitations, providing for the naming of functions, enabling the passing of parameters, and providing a mechanism for returning values.

Defining functions

Each function for a font is defined in a <function> element. Each <function> is identified by a name attribute. If the function takes parameters, these must be defined in <param> elements, which come first in the function:

    <function name="my-function">
      <param name="first-param"/>
      <param name="second-param"/>
      . . .
    </function>

A function parameter is a read-only value: it can be referenced in any instruction element that reads values:

    <function name="my-function">
      <param name="ref-point"/>
      <param name="move-point"/>
      <move>
        <reference>
          <point num="ref-point"/>
        </reference>
        <point num="move-point"/>
      </move>
    </function>

A parameter may have a default value, used if the parameter is not specified when the function is called. The value may be a number literal or a global constant. Specify the default value with the value attribute (e.g. value="0").

A function may return one value (and that value, like all others in Xgridfit, must be a number). A function that returns a value must have the attribute return="yes". Then, within, the function, assign a value to "return," e.g.

    <set-equal target="return" source="control-value(stem-width) / 2"/>

For a way around the one-value return limitation, see "Passing parameters by reference" below.

Calling functions

A function may be called (its code executed) from a glyph program, the pre-program, or another function. To call a function, use the <call-function> element, which may contain one or more <with-param> elements, one for each of the function's parameters:

    <call-function name="cap-half-standard-serif">
      <with-param name="base" value="bottom"/>
      <with-param name="near-base" value="bottom-serif-bottom"/>
      <with-param name="opposite-base" value="bottom-serif-top"/>
    </call-function>
  

It frequently makes sense to call a function repeatedly, once for each instance of some visible feature (such as a serif). In that case the content of <call-function> may be several <param-set> elements, each containing one or more <with-param> elements specifing the parameters for one running of the function:

    <call-function name="auto-cap-vert-serif">
      <param-set>
        <with-param name="base" value="top-right"/>
      </param-set>
      <param-set>
        <with-param name="base" value="top-left"/>
      </param-set>
      <param-set>
        <with-param name="base" value="bottom-right"/>
      </param-set>
      <param-set>
        <with-param name="base" value="bottom-left"/>
      </param-set>
    </call-function>
  

The function is called once for each <param-set> using TrueType's efficient LOOPCALL instruction.

The list of parameters for each call to the function must be complete, except for any parameters with default values. Omitting a parameter generates a fatal compile error. The order of parameters in a call is not significant.

A parameter value can be any value or expression, as long as it can be resolved to a number at run time. It cannot be a more complex structure--a <line>, <range> or <set>. Variables are by default passed to functions by value, while control values are passed by reference. This may seem like an inconsistency, but it is the behavior that is most often wanted. It can easily be overridden, as the next section explains.

Global constants and variables are visible from a function; and the function can contain its own variables, defined in <variable> elements just after the <param> elements.

A <call-function> element for a function that returns a value should ordinarily have a result-to attribute specifying a variable, control value, or a graphics variable that can be written to. If this element is missing, the Xgridfit compiler issues a warning and the value is left on the stack.

Function Variants

Function variants are alternative versions of a function to be used at different sizes or resolutions. Define function variants by including one or more <variant> elements at the end of a function definition, thus:

    <function name="myfunc">
      <param name="myparam"/>
      <!-- default function programming -->
      <variant test="pixels-per-em &lt; 20">
        <!-- programming to be used at less than 20 pixels per em. -->
      </variant>
      <variant test="pixels-per-em &gt; 100">
        <!-- programming to be used at greater than 100 pixels per em. -->
      </variant>
    </function>
  

Though you define functions with variants along with other functions (those that lack variants), the TrueType engine actually defines them when the <pre-program> is run. Thus the test attribute of the <variant> element, which determines whether a particular variant is to be used, may be based on whatever is known at that time--typically size and resolution information.

A function variant cannot have its own <param> or <variable> definitions; it always uses those of the function in which it is embedded. In the example above, the myparam parameter is visible inside the <variant> elements just as it is in the default programming (that which is not inside a <variant> element and which is used if none of the test attribute evaluate as true at run-time).

If you have defined more than one <variant> for a function, the test attributes should be exclusive: that is, no more than one should evaluate as true at any given time. If you do the following:

    <function name="myfunc">
      . . .
      <variant test="pixels-per-em &lt; 20">
        . . .
      </variant>
      <variant test="pixels-per-em &lt;= 10">
        . . .
      </variant>
    </function>
  

then at 10 pixels-per-em the TrueType engine will first define the first function variant and then overwrite it with the second. This should not produce an error, but it certainly is an inefficient way of doing things. This is far better:

    <function name="myfunc">
      . . .
      <variant test="pixels-per-em &lt; 20 and pixels-per-em &gt; 10">
        . . .
      </variant>
      <variant test="pixels-per-em &lt;= 10">
        . . .
      </variant>
    </function>
  

The advantage of using function variants over using <if> elements within functions to produce different behavior depending on size or resolution is that in the former case the decision which programming to use is made just once, when the <pre-program> is run, while in the latter case the decision is made over and over again, whenever the function is called.

Passing parameters by reference

Suppose you want to write a function that returns a vector. The function can return only a single number, but a vector is a structure consisting of two numbers: x and y coordinates. The limitation on the return from a function can be overcome by passing two variables to the function by reference so that the function can store the vector in those variables. Use the index() operator to do so:

    <variable name="vector-x"/>
    <variable name="vector-y"/>
    . . .
    <call-function name="get-vector-from-line">
      <with-param name="line-a" value="a"/>
      <with-param name="line-b" value="b"/>
      <with-param name="x" value="index(vector-x)"/>
      <with-param name="y" value="index(vector-y)"/>
    </call-function>

Since a number in TrueType carries no type information with it, the code inside your function must recognize that the parameters x and y are references to variables instead of the values of variables, and that they can be written to. Use the variable() operator for this purpose.

    <function name="get-vector-from-line">
      <param name="line-a"/>
      <param name="line-b"/>
      <param name="x"/>
      <param name="y"/>
      <with-projection-vector to-line="parallel">
        <line>
          <point num="line-a"/>
          <point num="line-b"/>
        </line>
        <store-projection-vector x-component="variable(x)"
                                 y-component="variable(y)"/>
      </with-projection-vector>
    </function>

After the function returns the vector will be stored in variables vector-x and vector-y.

Macros

A macro is a good way to regulate features (such as serifs) that occur frequently and yet do not require large or complex stretches of code. Using a macro can save the overhead of a function call and bypass the somewhat bulky code required to read function parameters. The downside of macros is that, since the compiled code is inserted repeatedly into the font, they can increase the font's size significantly. Macros, then, are most useful for features that are very frequent but also fairly simple.

Each macro is defined in a <macro> element. Here is a macro definition that regulates a standard vertical stem with attached serif when one point on the stem is anchored to another point:

      <macro name="lc-vert-stem-serif-anchor-dist">
        <param name="anchor"/>
        <param name="distance-from-anchor"/>
        <param name="stem-a"/>
        <param name="serif-a"/>
        <param name="stem-b"/>
        <param name="serif-b"/>
        <move distance="distance-from-anchor">
          <reference>
            <point num="anchor"/>
          </reference>
          <point num="stem-a"/>
          <move distance="lc-serif-width">
            <point num="serif-a"/>
          </move>
          <move distance="lc-vert-stroke">
            <point num="stem-b"/>
            <move distance="lc-serif-width">
              <point num="serif-b"/>
            </move>
          </move>
        </move>
      </macro>
  

Here is a call to that macro:

    <call-macro name="lc-vert-stem-serif-anchor-dist">
      <with-param name="anchor" value="left-left"/>
      <with-param name="distance-from-anchor" value="hn-width"/>
      <with-param name="stem-a" value="right-right"/>
      <with-param name="serif-a" value="right-serif-right"/>
      <with-param name="stem-b" value="right-left"/>
      <with-param name="serif-b" value="right-serif-left"/>
    </call-macro>

The compiled code, once inserted in the font, is twenty-four bytes in length.

Like a function, a macro can take parameters (and the <param> element can contain a value attribute with a default value). The value of the <param> or <with-param> element is substituted at compile time rather than passed at run time. The <call-macro> element may contain <with-param> elements, if the macro code is to be compiled and inserted just once where the <call-macro> element occurs. Alternatively, the <call-macro> element may contain any number of <param-set> elements, each containing a complete set of <with-param> elements, and the macro code is inserted for each one.

Macro parameters

Though macro parameters look like function parameters, they are much more flexible. The Xgridfit compiler substitutes the value in the <with-param> element for the identifier that references the <param> inside the macro; then it proceeds to resolve the value as it would any other value. Thus the value passed as a parameter may be any kind of expression. The name of a <line>, <range> or <set> can also be passed, and referenced by a ref inside the macro.

You may not only pass a <line>, <range> or <set> by name, but also declare it as the content of a <with-param> element. This is a convenience when you do not need to use the structure elsewhere in the glyph program:

    <with-param name="s">
      <set>
        <point num="p1"/>
        <point num="p2"/>
        <point num="p3"/>
      </set>
    </with-param>
  

When <with-param> has content the value attribute is optional: assign it some arbitrary value if your macro code tests for the presence of a parameter.

Macros and conditional compilation

You can make macros more flexible by using conditional compilation. Any stretch of code may be compiled conditionally by enclosing it in a <compile-if> element, and a <move>, <align>, <interpolate>, <shift> or <delta> element can be compiled conditionally by including the compile-if attribute. The test attribute of <compile-if> and the compile-if attribute may contain only expressions that can be evaluated at compile time. But since point numbers in Xgridfit are usually constants, and thus known at compile time, it is usually possible to base conditional compilation on point numbers. For example, the following macro takes eleven parameters, of which six are optional: it can control a visual structure that is either more or less complex:

    <macro name="lc-vertical-stem-with-serif-anchor">
      <param name="anchor"/>
      <param name="distance-from-anchor" value="-1"/>
      <param name="stem-a"/>
      <param name="stem-a1" value="-1"/>
      <param name="stem-a2" value="-1"/>
      <param name="serif-a"/>
      <param name="stem-b"/>
      <param name="stem-b1" value="-1"/>
      <param name="stem-b2" value="-1"/>
      <param name="serif-b"/>
      <param name="serif-top" value="-1"/>
      <compile-if test="distance-from-anchor &gt;= 0">
        <move distance="distance-from-anchor">
          <reference>
            <point num="anchor"/>
          </reference>
          <point num="stem-a"/>
          <move distance="lc-serif-width">
            <point num="serif-a"/>
          </move>
        </move>
        <else>
          <move>
            <reference>
              <point num="anchor"/>
            </reference>
            <point num="stem-a"/>
            <move distance="lc-serif-width">
              <point num="serif-a"/>
            </move>
          </move>
        </else>
      </compile-if>
      <align compile-if="stem-a1 &gt;= 0 and stem-a2 &lt; 0">
        <point num="stem-a1"/>
      </align>
      <align compile-if="stem-a1 &gt;= 0 and stem-a2 &gt;= 0">
        <point num="stem-a1"/>
        <point num="stem-a2"/>
      </align>
      <move distance="lc-vert-stroke">
        <reference>
          <point num="stem-a"/>
        </reference>
        <point num="stem-b"/>
        <align compile-if="stem-b1 &gt;= 0 and stem-b2 &lt; 0">
          <point num="stem-b1"/>
        </align>
        <align compile-if="stem-b1 &gt;= 0 and stem-b2 &gt;= 0">
          <point num="stem-b1"/>
          <point num="stem-b2"/>
        </align>
        <move distance="lc-serif-width">
          <point num="serif-b"/>
        </move>
      </move>
      <compile-if test="serif-top &gt;= 0">
        <move distance="ascender-serif-x-width">
          <reference>
            <point num="stem-a"/>
          </reference>
          <point num="serif-top"/>
        </move>
      </compile-if>
    </macro>
  

This macro can control the points of a simple structure like this one

l

with this call:

    <call-macro name="lc-vertical-stem-with-serif-anchor">
      <with-param name="anchor" value="an"/>
      <with-param name="stem-a" value="a"/>
      <with-param name="stem-b" value="b"/>
      <with-param name="serif-a" value="c"/>
      <with-param name="serif-b" value="d"/>
    </call-macro>
  

If points must be aligned with "stem-a" or "stem-b," they can be passed via parameters "stem-a1," "stem-b1," and so on. If there is a top serif, as on a lower-case i, the end point for that serif can also be passed to the macro, and the appropriate code will be compiled:

l
    <call-macro name="lc-vertical-stem-with-serif-anchor">
      <with-param name="anchor" value="an"/>
      <with-param name="stem-a" value="a"/>
      <with-param name="stem-b" value="b"/>
      <with-param name="serif-a" value="c"/>
      <with-param name="serif-b" value="d"/>
      <with-param name="serif-top" value="e"/>
    </call-macro>
  

Glyph Programs

A glyph program may stand by itself and also be called from within another glyph program. It is a simple matter to prepare a glyph program to play such a dual role, and equally simple to call the program. It is handy to be able to call a glyph program if, like a number of font makers, you prefer to avoid using the TrueType component mechanism to make accented glyphs. If you are adding instructions to, say, eacute, then as long as the outlines that constitute the e and the acute portions of the glyph are identical to those of the e and acute glyphs, it makes sense to call the glyph programs for e and acute to instruct the composite. The resulting glyph program might look something like this:

    <glyph ps-name="eacute">
      <constant name="last" value="89"/>
      <call-glyph ps-name="e">
        <with-param name="interpolate" value="0"/>
        <with-param name="left-sidebearing" value="last + 1"/>
        <with-param name="right-sidebearing" value="last + 2"/>
      </call-glyph>
      <call-glyph ps-name="acute" variables="no">
        <with-param name="offset" value="66"/>
        <with-param name="left-sidebearing" value="last + 1"/>
      </call-glyph>
    </glyph>
  

The first elements in the <glyph> program being called must be <param> elements; these are exactly like the <param> elements in functions and macros. Because a <glyph> program must be able to run by itself as well as be called, the value attribute, which supplies a default value for the <param>, is usually obligatory.

The glyph program may take one special parameter, named offset. If the offset parameter is present, then its value is automatically added to all point numbers. The sensible default value for offset will usually be zero. With the offset parameter, the beginning of the glyph program for acute might look like this:

  <glyph ps-name="acute">
    <param name="offset" value="0"/>
    <param name="left-sidebearing" value="last + 1"/>
    <constant name="last" value="17"/>
    <constant name="bottom" value="3"/>
    <constant name="top" value="10"/>
    . . .
  

Note that the Xgridfit compiler cannot always recognize which numbers are point numbers. It will always handle <point> elements correctly, but when point numbers are passed as parameters to functions, macros, and other glyph programs, you must either add the offset value manually or (perhaps better) use the point operator to indicate to the compiler that the number is a point:

    <with-param name="p" value="pt + offset"/>
    <with-param name="p" value="point(pt)"/>
  

You must do the same in <push> elements and in all expressions that do not appear in <point> elements. To avoid complications, it might be best to arrange glyphs in such a way that offsets are not needed for the more complex features. In the glyph program for eacute, illustrated above, acute is less complex than e, so acute has the offset.

An important difference between a glyph program run by the TrueType engine and one called by another glyph program is that the TrueType engine sets the various graphics variables to their default values before running the program; it does not perform the same service for the called glyph program. If your program has changed the graphics state, you should set the variables you've changed to their default values before calling a glyph program. For most graphics variables (those whose state Xgridfit tracks), you may do this by calling <restore-default>, including the name attribute with one of the following values:

  • minimum-distance
  • control-value-cut-in
  • single-width
  • single-width-cut-in
  • delta-base
  • delta-shift
  • round-state
  • all

The all option sets all of the above graphics variables to the defaults set by your Xgridfit program, or the TrueType defaults if you have not explicitly set any defaults. It also sets several graphics variables that Xgridfit does not track (the freedom and projection vectors and the auto-flip toggle) to their TrueType defaults. The all option is an expensive one, of course; it is best to be aware of the condition in which your program so far has left the graphics state and call <restore-default> only for those graphics variables that must be reset.

Callable Parameters

A parameter to a macro or glyph program (but not a function) may contain code to be executed within the called code block. A call to a glyph program, for example, might look like this:

    <call-glyph ps-name="dieresis">
      <with-param name="offset" value="A/total"/>
      <with-param name="delta">
        <delta>
          <delta-set size="3" distance="4">
            <point num="dieresis/left-left + A/total"/>
          </delta-set>
        </delta>
      </with-param>
    </call-glyph>
  

Within the glyph program, the parameter is "called" with the <call-param> element:

    <call-param name="delta"/>
  

The parameter is declared at the top of the macro or glyph program. It is like other parameters, except that a value attribute, if present, is ignored, and that the <param> element can contain code to be executed if a <with-param> element of that name is not found in the call to the macro or glyph program. In the following <param> element, for example, the default code simply touches a point:

    <param name="delta">
      <move round="no">
        <point num="left-left"/>
      </move>
    </param>
  

It is an error if no <param> is found to match the <call-param> element. However, if there is no matching <with-param> element in the call to the macro or glyph program and the <param> contains no default code, that is not an error. In that case, the Xgridfit compiler issues a warning and does nothing.

The <call-param> element can pass no parameters to the called code: if it contains <with-param> elements, they are ignored. When writing code to be passed via a parameter to a macro or glyph program, it is important to take context into account. Constants, variables, and other elements declared within, say, a <glyph> element are not visible from outside of it. Thus, in the <call-glyph> example above, the left-left point in the called glyph must be referenced via glyph/constant syntax as dieresis/left-left. But for the <param> example this is not necessary, since the default code is declared within the glyph program itself.

Nesting and Recursion

A TrueType function can call another TrueType function, including itself. Before Xgridfit version 2.2 there were significant limitations on the ability of macros to call other macros and of called glyph programs to call macros. But in version 2.2 these limitations have been removed. Thus it is practical to construct a macro that does a complex job by calling several macros that do simple jobs. For example:

    <macro name="single-serif">
      <param name="base"/>
      <param name="serif-end"/>
      <move distance="serif-width">
        <reference>
          <point num="base"/>
        </reference>
        <point num="serif-end"/>
      </move>
    </macro>

    <macro name="double-serif">
      <param name="left-base"/>
      <param name="left-serif-end"/>
      <param name="right-base"/>
      <param name="right-serif-end"/>
      <call-macro name="single-serif">
        <with-param name="base" value="left-base"/>
        <with-param name="serif-end" value="left-serif-end"/>
      </call-macro>
      <call-macro name="single-serif">
        <with-param name="base" value="right-base"/>
        <with-param name="serif-end" value="right-serif-end"/>
      </call-macro>
    </macro>
  

It is also perfectly all right for a macro to call itself recursively; though it must be remembered that recursion, for a macro, is in the compilation, not in the execution. Thus this macro:

    <macro name="touch-points">
      <param name="first"/>
      <param name="last"/>
      <move round="no">
        <point num="first"/>
      </move>
      <compile-if test="first < last">
        <call-macro name="touch-points">
          <with-param name="first" value="first + 1"/>
          <with-param name="last" value="last"/>
        </call-macro>
      </compile-if>
    </macro>
  

if called like this:

    <call-macro name="touch-points">
      <with-param name="first" value="0"/>
      <with-param name="last" value="2"/>
    </call-macro>
  

will generate code that looks like this:

    PUSHB_1
    0
    MDAP[0]
    PUSHB_1
    1
    MDAP[0]
    PUSHB_1
    2
    MDAP[0]
  

which may or may not be what you want.

xgridfit/docs/q-delta.png0000644000175000017500000000667310643720040014713 0ustar peterpeterPNG  IHDRbKGD pHYs  tIME11Oc HIDATx흽r[&tx*9@ob*V3tn@A(`S9U[{m ~l5B(5AЃ$kAGNJAJa|y\n)i8BlY/(f`C `J77gĖklPzrl&bClV?Xl %Jilkؤf1;vo%%'zrR6wx~Aڥ/V h`n!}DwqH)؏- #jn|SJ'<拹86mf5R'oe^s|b>Ptχӿfڇ'nF=U묶xްeI8]4:gقT9qK2* '.n:>h?D+K=\/Ў׍8:w | v9S9ga p(8O|eq6&x9RXn;Fc/xnN7K2r2?:бgp}AVfܮ55gnl?G-#ukS:ZeGܸc[̫]uLYpYjC1BME^je^PFߦ=rR`on27ے g>Vd.s}ͭmfc'A6YKm<ñf`UNL夿4x{ 8g)mq@;'. yׁ8 a082]oH^j2x1˴tH \yop}#r\Ͼ{bY$`YJumcЂT R۹&z)f=efô6*jsA߅f{6O7}Gs+R$4YqȜE<,ERJ_+zVWδ] s*!ף]>pݾI<q+eI[xzz c ~=2p沝[^GdX-ydoi;;s8(Kot[hbֹsXl>`)ֺu1J;a9KOU6t'ɼ핼xr)'8Nye6@k " S /4XR)}fCYsa)BVVTVE(׮}p7g,F d'nf3WQxmm'#43>֘;QvQsK2j{5o sKA0e M!C2֘CeU)R,EK#YNR,EeDZf>5foe`Uh*#R Kƙ:! AYS@Ul{Ve5mR$|Kfᕨp3P@nwOYClihp:62pY 5#@qwݗRy?>vMZd͠2?4 𚖢%OED% jlk)25 mGNJ)d_Xq>rl? Aj`! AbV,EK`) !6X (Al;Kœ!C `Z[%,E3KmRA!C0`Z`Ŧv)68R`}̵x7G,\xK# /Or x₊To?rvW\=QsNeqlo91V*c0`(jUVEpJ (l,@euSak3% 850 ,Ekk@lm`)J01 P; f_mNՆJ)c7BDX&t aPgnGQ8K++"V7cxg7dPˁu4I6%bbfwͰRJ 1Ѡ! ͓R,EdaAdᮥk!!mw^)ezr6v=Ǜ~Ԙ-+)MR[R"_R# <^ ՝ ,`!bC Xgridfit

Deltas

A delta is an instruction that operates only at a specific resolution. There are two kinds of delta, invoked by two Xgridfit elements: a <delta> element moves points, and a <control-value-delta> element edits the Control Value Table.

Use delta instructions when the non-resolution-specific parts of your programming have failed for some reason. Here are some situations in which deltas typically make sense:

  • Rounding of a distance has produced an unattractive result. (If the distance was from the Control Value Table, consider using <control-value-delta>.)
  • A feature does not render well at particular sizes, and you wish to remove or modify it. (But programming can also be made to operate at a range of sizes using an <if> construction.)
  • Components of a composite glyph are poorly positioned relative to each other.

In addition, you may wish to use a delta to smooth a curve that has developed a kink, or to turn a pixel on or off. Before you use a delta, however, you should make sure that the problem you are correcting is not the result of your own careless programming: failure to use control values correctly, for example, or failure to think through the problems presented by a complex feature. It may well be less trouble to write a great many deltas than to think intensively about the intersection of two diagonals. But once you have written non-size-specific code that addresses a problem, it can easily be adapted to handle similar problems in the same or another font. The same can rarely be said of deltas. So think of the delta as a last resort or a finishing touch.

Another situation that may tempt you to use deltas arises when the original glyph outline contains small irregularities that show up only at certain low resolutions. When an o is not quite symmetrical, for example, it may appear lopsided at times. In this case you should consider whether the glyph's lack of symmetry is a feature you wish to preserve or an error you should correct. The best time to consider such issues as this is before you start writing the glyph program.

If you have used a graphical hinter like the one in FontLab, it may have left you in some confusion about where deltas can and should come in the sequence of a glyph program. Deltas may come anywhere, but they should generally be placed so as to correct any problems in the positioning of a point as early as possible. The letter q in the left-hand figure below illustrates. (The black lines show the original shape of the glyph and the green lines the grid-fitted shape; the brown squares show which pixels are on. The black vertical line shows the original right margin, and the green vertical line shows the grid-fitted one.)

q without delta q with delta

The q on the left is too wide, and it bumps into the right margin. The problem arises after the left-hand curve has been hinted; then the overall width of the glyph is regulated by positioning point b relative to point a:

  <move distance="bdpq-width">
    <reference>
      <point num="a"/>
    </reference>
    <point num="b"/>
  </move>

The problem is that the distance "bdpq-width" gets rounded up at 15 ppem when it would be better visually for it to be rounded down. If you waited till the end of the glyph program to address this problem, you would need deltas to correct the position not only of b, but also of c, d, and several other points not shown here--for example, those that control the horizonal positions of the serif ends. All of these points are positioned relative to point b, so if you correct the position of b immediately after the execution of the instruction above, thus:

  <delta>
    <delta-set size="6" distance="-8">
      <point num="b"/>
    </delta-set>
  </delta>

then the position of the others will automatically incorporate the correction, and the result will be the much better glyph on the right.

We can correct the problem even earlier than this, however. Notice that the <control-value> that controls the width of the q is named "bdpq-width": this is because that single entry controls the width of b, d and p as well as q. As the following figure demonstrates, the width of all four characters is wrong at 15 ppem:

b d p q with incorrect width

We can correct this problem most efficiently with a <control-value-delta> instruction in the <pre-program>. First we round the distance, then execute the delta instruction:

  <round value="bdpq-width"/>
  <control-value-delta>
    <delta-set cv="bdpq-width" size="6" distance="-8"/>
  </control-value-delta>

And now, as the figure below shows, the width of all four characters has been corrected without resorting to the use of delta instructions in the glyph programs themselves.

b d p q with correct width

Elements Relating to Deltas

In addition to the following elements, you should know about the delta-base and delta-shift graphics variables, which you may both read and write to.

<delta>

A delta instruction moves points at particular sizes. The <delta> element may contain any number of <delta-set> elements. When all of the <delta-set> elements in a <delta> move the same point, it may be convenient to make the first element a <point>. This is the default <point>, which every <delta-set> will move unless it contains its own <point>.

The direction of the move is determined by the current setting of the freedom vector. The available specifications are fuzzy as to the details. You will experience no surprises when the vectors are set to x or y; you may experiment with the vectors set at other angles.

<control-value-delta>

The <control-value-delta> element works like the <delta> element, but operates on the Control Value Table rather than on a point. Each <delta-set> inside a control-value-delta element must have cv, size and distance attributes, but it may not contain a point.

The setting of the vectors has no effect on the <control-value-delta>. Rather, the <delta-set> specifies an amount to add to or subtract from the value stored there.

<delta-set>

The <delta-set> element encapsulates the essential information about a single delta move or adjustment: the resolution at which to apply the delta, the magnitude of the adjustment, and the point or control value that will be affected.

The resolution is determined by the size attribute, which can be a number from 0 to 47. It is added to the value set by the <set-delta-base> or <with-delta-base> instruction to obtain the resolution (in pixels per em) at which the move should take place. The default delta base is 9; if you don't change it, a size of "0" means 9 ppem, "9" means 18 ppem, and so forth up to "47," which means 56 ppem.

The distance attribute is the distance to shift the point along the freedom vector, or the amount to add to or subtract from the control value. Legal values are from -8 to 8 (excluding 0). When moving points, negative numbers shift against the direction of the freedom vector (generally down or left) and positive numbers shift in the direction of the freedom vector.

The default unit by which pixels are moved and control values adjusted is 1/8 pixel. The unit is controlled by means of the <set-delta-shift> or the <with-delta-shift> instruction.

A <delta-set> that is the child of a <delta> will normally contain a single <point>. However, the <point> may be omitted in either of two circumstances: First, when the <delta> is the child of a <move> element, the <point>, when not specified, is implicitly the <point> that is the child of the parent <move>. Second, when the first child element of the <delta> is <point>, that point will be moved by any <delta-set> that lacks a child <point>. These two deltas are equivalent:

            <delta>
              <delta-set size="3" distance="4">
                <point num="p"/>
              </delta-set>
              <delta-set size="8" distance="-7">
                <point num="p"/>
              </delta-set>
            </delta>

            <delta>
              <point num="p"/>
              <delta-set size="3" distance="4"/>
              <delta-set size="8" distance="-7"/>
            </delta>
          

All attribute values in a <delta-set> and a child <point> must be capable of being resolved to numerical values at compile time. Variables and function parameters are not permitted.

<set-delta-base>
<with-delta-base>

Sets the number that is added to the "size" attribute of a <delta-set> element to get the resolutioni at which an adjustment should take place. The default value is 9, and that rarely needs to be changed.

<set-delta-shift>
<with-delta-shift>

The unit by which a delta instruction shifts a point. If the unit is "2," the smallest shift is half a pixel; if "4," it is a quarter of a pixel; if "8" (the default) it is one eighth, and so on.

xgridfit/docs/W.gif0000644000175000017500000000535410643720037013554 0ustar peterpeterGIF89aK^ ###$$$&&&'''((()))***---...///222888:::<<^!'pv[GLYCg뱿VX^\̺ Kk'?+zOO}:輲=^q#HEv_·įx̞"(Aٵ+TlGYD<CcqHX1Pf@b q2aaBgڡD!갉NęHFKa+z+2fc [1\4q16;ʱ/I(RxDZh"2aDD8b*D!@0@OId"<-+RcaoW R`~#0 Aq`qK pQSJ` GebK&W=`ZsD#ՉJv.ħO)V̥O9M mh? ш3 g5 :Rt=(H7рԣ *a)G>ZS+]]*mzS/'V72u-Uέ {@N\Ў:Կ=u{`z֝~6yEhiѶ6t\u#5]nɝl;CvSv-id4w,ơ[摿iWi8+tɲa$qhYbH wN|)W^Z>l6 &EE0 @ x؆/ˑ:-avX )񂶻pJxϻRn; J80xF<2!/c8'c?(>MG$ŪC=ST9֟~9CcgO ;xgridfit/docs/A2.png0000644000175000017500000000455710643720037013633 0ustar peterpeterPNG  IHDRUbKGD pHYs  tIME  -@!KIDATx?k]ϕ]y )RlaYYQch awB4fmBDf" Mta!EH$7ٹ3}R.O>;s6;*irVS]mX(搖h?\_D\SFOXI8!Q=wv((@9 8J9 { GGwv((@9 8J9 { GGp4ncwO28ss&LypKF׃3s-m?|9G(Q ((@9 8 PxGi@ݻw^bpvgϞZ8 LNPիWk:qͻw~Ǐ7na|daMI׏닋nv~DP=ڋRJD2뇣N"reGϟ?"͛۷o_xcfsΕ%G-6KEѴ''Q Q+LD$ 5]v6ҬmR PժUUjZηfVWED(m[ܜ5;!gNo N߫Kn__·(}=Di4 uuz MJ)9j:Z8j Gp(rMqGR"GM4Q4))x@͚(-^8ꄩkD)Q8ꀦG]Mq(U (z(Q'ԢMqpڏ)-Mٔ/}HSw)ep'0tRkwH%/ӖU_DN|dQaÇgff; >ŋo߾=}4jL4?}K߿"RTr<ֺD:'H"?h_~t:ۉz[K~ɓׯ_[ 9z(-v.--?~yycn3glmm}emmOmǏ333wyQZ}z~~~gg>3ٿs}hQ]i\oŌ?fnJd5hmY~*4Kmu%[M; jeArH׶UiVc[åjI^@9*xp0$GIn *15G&5]eɾoEV.I`TwހiI5%<GTv=RidtLx:c/8Zh2,EI/:* ES׃{^fskQZܼ<{r$2{'5glV[ F12qzMG-d漗 {^Ƒy͟eh:HzAq9|*eeD7Fd{4|fώ.Ϯӵn 'ns=2Ip:A8:8Rzj)G'=?X8 8 n Ͻ~rl8 8 8 8 8 8 8 8 8 8 PGDO28Ho䠸?([R?dmsGGpGGppGppGppGGpGGpGGppGpp0*4GEӦi ^4KULIENDB`xgridfit/docs/o-bold.gif0000644000175000017500000000604610643720040014513 0ustar peterpeterGIF89appp! ,x0I8ͻ`(dihlp,tmx|pH,Ȥrl:ШtJZجvzxL.C] ,n[@gEW5{zwNv2~rzI0 E6 Bu1pn1< ?|:C3}9Du=+ q,>$oG1vmX!܇` U Jly4nlA·'3dSRVXɲ'9 m;*@f071U"VBI͐BQ(L3S]n**V ȎdS_49tٳ0]{?~ /uO3U6La|5Qf3.mQjQn5VDKl{*m#ov;P+|)c^5F7qj*H{ߦW3~Kw}_!wCNٲ YsPW,hC1=DT#$ʍԓ*ˆ.tb CQH[8w%B5 ;ף CISdtAeo Y|u$4W"s@4:铗CiL9%C",rFCg SX,}:ɟ/0J^8jW @E*7^p:hYZcBz zGz*+m;JHīr2fT,2fEz>) *ΘEҊD&. [ż>mvoj/{p|$a1 74 E;lE@||:SA$#/sf6ÜC]9ы%S-R D'"A_ sY>mh\GH&"@-Ex5i3VN`K ZkY s_v#b1arqA1g2q݁0 Gnwʇ]8 d{xGfC/Z$]3E{zBwbN w[hmTϰ[?Xe҅<`{/ojhjχBs7~Bd`A:XjȸHЀ c7mtěAnر$(œP2XINs(|{Dh29 Ny z<0 '>0aH=#vPuˀ1e8dS>х̛AwC'0S8xQ0\faE3!Jl# 7&9,c 9C2yQ$pǚA#IKV %Z:SRP%HWFV%h [JTevx_B& 1cbFr9gGA3[fʹa~g&OAx xtrk & >Y}a<;j'}cP41t ̧AGPJXô|z tPTACNu~P(%?OTu$jt攝bH(>˹tEBj0̴M!4~txl&8?qRHd'z0B!Rtst:KD4&aBKJ2Ǖ4k_Ӱ6kjL"{HryEDjK1`me ";JhEV&|f h;]IMJ,ma&M (qD}c0mnlQ57d"`KI_NU qdܝ?-)[n~3'Ek0zs5QLV}б0GֻK?'AЍ:tl8S^1fM㲡[~ :h^oeиsE%* 0E,-7,^e'Px/&zdwwwz{ţloYeJ~`5VT\%e&oLhgAihٛUe3uy扥ԌNH`=`NcbL~b_FƬ) xJXehdx_Vg Fh&m%(_(#рt&Cw j@}0[;Vto)3r#KBD4rs50fb=RcMt."hA,(q;GM3?P*I$_otVx92JD/h>W!DsCrQ(7m=&l14"4yo؅3g(aҗe x)sFcb!n &+#EgkfV>gi"]+V( ъv4bwa$4牟85HCh8?(ጯW8TqVkB@਍dxHX*m(1a|eZ8Z؏HPJb v)n!!,- "9$Y&y(*,ْ.0294Y6y8:<ٓ>) ;xgridfit/docs/parchment.css0000644000175000017500000000003310643720040015331 0ustar peterpeter@import url(advanced.css); xgridfit/docs/variables.html0000644000175000017500000002101511046004770015502 0ustar peterpeter Xgridfit

Variables

In TrueType programming, most of the work you'd normally expect variables to do is handled by control values, which are great for storing and manipulating the fixed-point numbers that measure distance on the raster grid. If you need storage for some other kind of number, or temporary storage for a fixed-point number, you may wish to use an Xgridfit variable.

Variables are Xgridfit's way of providing access to the TrueType "Storage Area," which stores 32-bit numbers and no other data types (such as strings). Any of the number types known to TrueType can be stored there; but TrueType provides no way to store type information with these numbers, or to check types. Think of variables as handy places to store numbers temporarily, but don't expect the sorts of conveniences provided by the variables of general-purpose programming languages such as Java and Python.

All Xgridfit variables must be declared before they are used. You must assign a value to a variable before you can read it. In addition, you must initialize the storage area for your font by estimating the number of variables that are likely to be in use at any one time.

It is a simple matter to write to a variable. You can reference the variable by name in the target attribute of the <set-equal> element, or you can reference it in the result-to attribute of any of the elements that have it, including <round>, <measure-distance> and <get-coordinate>. When you call a function that returns a value, you may store the return value in a variable via the result-to attribute of the <call-function> element.

Once a variable has been written to, you can access the value by referencing the variable by name in almost any attribute that accepts a number value--for example, the num attribute of the <point> element. A variable can also be used anywhere in an expression.

Local Variables

Local variables are those which are visible only within the <pre-program>, glyph program, or function where they are declared. Local variables are temporary: a variable declared within a glyph program exists only while the glyph program is running, and afterwards the storage location it occupied is freed for other uses. The same is true of variables declared within functions and the <pre-program>.

Local variables must be declared in <variable> elements at the top of the <pre-program>, after the <param> elements element in a function, or with the <constant>, <range>, <set> and <line> elements at the beginning of a glyph program. You cannot declare variables within smaller scopes (such as if-blocks and with-blocks). The variable declarations for the asterisk in Junicode-Bold look like this:

  <variable name="up-x"/>
  <variable name="up-y"/>
  <variable name="down-x"/>
  <variable name="down-y"/>
  <variable name="half-min"/>

The TrueType engine stores no type information at all: The declaration merely signals to the engine how many spaces will be required in the Storage Area and associates names with spaces. It is possible to initialize a variable by including a value attribute in the declaration:

  <variable name="v" value="50"/>

Global Variables

A global variable is one that is visible anywhere that programming is allowed: in the <pre-program> and in any function or glyph program. It must be declared in top level of he program, as a child of <xgridfit>:

  <variable name="global-var"/>

A global variable should be initialized in the <pre-program>, and after that its value may be read by glyph programs and functions. It cannot be initialized with a value attribute. If a glyph program or function alters a global variable, or if you attempt to use a global variable to make one glyph program communicate with another, you are in terra incognita: the specifications are not informative about the way variables are handled in such situations. It seems a poor idea, in any case, to try to make glyph programs communicate with each other, since it is impossible to predict the order in which they will be run.

Graphics Variables

Several pre-declared variables can be used to query the graphics state or (usually) to set a graphics variable. These are detailed in the section of this documentation on the Graphics State.

Reserving Variable Space

Xgridfit reserves twenty-four spaces in the Storage Area for its own purposes. By default it reserves forty more spaces for variables. You may change this number with a <default> element:

  <default type="max-storage" value = "80"/>

In figuring the number of spaces you need to reserve, start with the 24 that Xgridfit requires, then add the number of global variables, the largest number of variables declared in any one glyph program, and the largest number of variables declared in any one function. If one function with variables calls another function with variables, you will have to increase the number accordingly.

xgridfit/docs/debug.html0000644000175000017500000001627511312435115014631 0ustar peterpeter Xgridfit

Debugging with FontForge

Xgridfit has no debugger, and it's pretty safe to predict that it never will. FontForge, however, has an excellent debugger, which you can use to step through the TrueType instructions for a glyph and watch the effect of each instruction on the outline.

You may have to compile FontForge from source to enable the debugger; and if so, you will need the source code for FreeType. We'll go through the procedure below; but first will discuss problems and solutions for debugging Xgridfit code.

For Xgridfit users, the trouble with the FontForge debugger is that it knows nothing about Xgridfit. It can be used to debug the raw TrueType instructions generated by Xgridfit, but it does not display the Xgridfit code in the debugger window. Without a pretty thorough knowledge of TrueType and how Xgridfit generates instructions, it can be difficult to identify an Xgridfit element that is causing problems.

The solution is the Xgridfit debug mode, which, instead of a FontForge or Python script, generates a file that shows exactly what TrueType instructions are generated by every Xgridfit element. If you are using the xgridfit command-line tool, simply include the -d parameter:

    $ xgridfit -d Junicode-Bold.xgf

Now, instead of generating a script Junicode-Bold.pe or Junicode-Bold.py, it generates a file Junicode-Bold.debug. This file always contains output for all functions and the <pre-program>. By default, it generates output for every <glyph> in your Xgridfit program. You can save time and generate a smaller file by using the -g (glyph-select) parameter, thus:

    $ xgridfit -d -g amacron Junicode-Bold.xgf

And now the only glyph Xgridfit generates output for is <glyph ps-name="amacron">.

The output of debug mode consists of the Xgridfit element (sometimes omitting child elements that do not generate code) enclosing the TrueType instructions generated from it. For example, this element:

    <move distance="baseline">
      <point num="bottom-a"/>
      <align>
	<point num="bottom-b"/>
      </align>
    </move>

generates this output:

    <move distance="baseline">
    <point num="bottom-a"/>
      PUSHB_2
      35
      0
      MIAP[rnd]
    <align>
    <point num="bottom-b"/>
      PUSHB_1
      9
      ALIGNRP
    </align>
    </move>

By comparing this output with the TrueType instructions in the FontForge debugger, one can quickly locate an Xgridfit element that is causing problems.

A couple of points. First, if you invoke Xgridfit directly using an XSLT engine rather than the xgridfit script, run in debug mode by using the XSLT script xgridfit-debug.xsl rather than xgridfit.xsl. Second, be aware that you will see some TrueType instructions in the output that do not belong to Xgridfit elements. This is because Xgridfit inserts code of its own, e.g. at the beginnings of glyph programs and at the beginnings and ends of functions.

Activating the FontForge debugger

There are general instructions for building FontForge from source and activating the debugger on the FontForge site. Here are some helpful pointers.

You will need the source code for FreeType2. Most Linux distributions provide a convenient way to obtain it. For example, in Debian or Ubuntu,

    $ apt-get source freetype2

should do it. Users of RPM-based distributions can easily obtain a source RPM for FreeType. Once you have unpacked the source, you need to find the file ftoption.h; it should be in include/freetype/config/ (assuming you are in the FreeType base directory). Open this file with a text editor and find a line that looks like this:

    /* #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER */

Uncomment the line by removing the /* and */ and save the file. Depending on your system configuration, you may or may not have to build FreeType from source and install this new version. On Ubuntu Linux you don't have to. On other systems it may be necessary. One way to find out is to build FontForge and see if the debugger works.

Note the location of the FreeType base directory (perhaps by typing pwd at the command line) and then go to the FontForge base directory. Run configure with a parameter pointing out the location of the FreeType source code, e.g.

    $ ./configure --with-freetype-src=/path-to-freetype

If you don't use the --with-freetype-src parameter, the configure script will probably find the FreeType source, but will hang for a long time while looking for it.

Now do make and, if the build finishes successfully, become root and run make install. If all has gone well, you will be able to use the debugger next time you start FontForge.

Note that Apple Computer Inc. owns several patents relating to the instructing of TrueType fonts. Strictly speaking, you should not enable the FreeType bytecode interpreter unless you have a license from Apple, you live in a country where the patent does not apply, or you are willing to risk a lawsuit. It is perhaps worth noting that Apple does not appear to have a history of suing Open Source font developers.

xgridfit/docs/x-vec-b.gif0000644000175000017500000001001710643720041014572 0ustar peterpeterGIF89a  !!!"""###""1&&&'''((()))***---...///00022255566677788877O:::;;;===>>>AAABBBCCCDDDFFFHHHJJJLLLMMMNNNOOOPPPQQQpSSSTTTUUUVVVXXXZZZVV|\\\]]]^^^```aaabbbcccpp``eeehhhjjjlllmmmpppqqqrrrssstttuuuvvvwwwxxxzzzuu{{{|||wwww}}}ء! , H*\ȰÇ#JHq iȱǏ = IE&SԈrK-_d͛8)3&O> *d͢HLZ(ӎNr*UѪXU.:+T_n*NJU-Y^e˔n]pji_xPÇ J8+b!+^181gLY媚m͹3mˎZ[IQ?mvҰ t7?eUk8F{9NIu7ݤwÇYcHȖ(PX -8M07z]`A?~G-a%MX`OWASM 4}i@}=VLoFI$&H?G6E&9Mi)*Mn@D Ud !BLpJ1p%F]~FP'@8P 4e~Q)MqaTQHMHyhd*Fj lѩj?!#@,lGLQ ܡQ2!2!PQ-t! EK j zQA-H?BX`EA&$*%DI@\H#e Bf22pFe1c0Fw0qC (K4ԧ%Q&l"8P!wzԼG{$aFivsq?f:tk>H־^"4]ԧh9$j% WQTOɕXa)G%B9ҪXhsR~Q8j|4-!hIkJ4nvzZP5QjJR>*EJԆnXjD%ӱ}aժ:rikN%jXU+JJyflJ؍br [%.3lf1;~d,iZl,툳'!J(H y eE۪def=~#mGۅZ3q *:za"6]OAmU7fxWrB5p K^7譫eMxb.u.U메7gٯ~[R>-Uk=a LJ a5 1⹂32N/Sl&}C,d#*?IOp26r2e.WfA$xɎ,O",E༈9!Uo$,g$/yeF3SaY D[ M޷~R$QN{FJ / fɦ]kw'kj!lxЯf2_Q-DךU5bj:%"l/rLj.zq6uyB2-U֤t.tKmdcֶ6K[e6OMiޔ]2jR3x7c͑pn|j܊.+AO7X,5]i nI^N߮ѽ]\|3>.hZ+J}r$9~>Ub9Gh~f4?>9O׫<-E{מ͢zԳ~}_W~9{Մ_r~c2'{U?~`eВEx+5-+BQX$Ar\nKEzV|]̣S/ ceIzj` wrȵ щW1mpFASkǜw*ŞE̳;9f>R inw͵ XC\HYzS1_'S׭zѯnWWV? zLJ6(ىhi &d:n_t:X p:xPv)҆ʚhŖv|;R p)r7g|Ք86749k3_D(5xEf|Wˬ !VsRT_=hō\ېN֍}K;9[S>O<^Yi"VmX[Q{ߑUf4Snp|o2sOA go*c?B@Xt:L:Vs bE;Lqi0vo0y܈f35_K?/JǍh5#>}N|D^,3ޣɽ(t^t~j `CI>8(IENDB`xgridfit/docs/o-bottom-unrounded.png0000644000175000017500000000401710643720040017113 0ustar peterpeterPNG  IHDR0mHbKGD pHYs  tIME%/AƐIDATxAg[Ammj ^{O*hΡ) CdHP0.S_"xP+E+TR[,ygy|@;ΦKIZӌ[{M@ @@ @@z@.زc ,j~%uNkЌCom*[s3}-AM@5j:F;@@@@ еIP%=fFs?C8p@@ @@ rL3ځ`e>]?oaNkЌCom*[s3}-AM@5j:F;@@(1IZt\?6\/%y$%גTf/ӝ.T'UGt)Z't+I~Y˲`K1A$)ɯ|C@ w[P=]%-i-ۙqfC~-{ sZvft572F;@@@@ ЭspIn_aqC8p@@ @@ cmx sZg&(|vk[Z3`͆ ZZ3C8)29e3ځ@@ `& _o޾t|&]~W676^2v ɓ|ԕ$럿vVF@o|Ο㏿ƅ %YK o~}:y_oYUj%\֌%xIns{~VJr'ӝ.[KKU>DK͟-ɟߖh5&鴻5AݎЎ8;[I~WI$?Or%*(8Lh"*9yOw:Lv3n}_Hh7﹚ШO";L]wWl{-G'ܪlNuvVh6=(fGQpp.)qYjR̰I49޻V6Ik_)?|&2]5畓P*PSuq_jTLuݤ#UPըZu1dH8/T5|&jeB5U'FʀHn-PWtԵs PRuXɏعW^Y>ދ&cP/O\)Pu)˲{<5>#jpAQ1}shz퓊qG,PZRoƔ몵fn^sYWn|:Vgu)wLnM-x1.> z{Lt`e9z7@ۖe뿺{+D˚;_$;4u|o֚lu3OQ- GlUXkr(McuWHEr(.jxr/ᄏf{̶Lt^q([Ys!*#yt;@T5Jџ%;ʕ1fLEÕ5MWu2( }ƷaH id;*uhM\t۶?#7ilJp7u>bu1Y78kdh۳6H*R-cOW[`5ꭘQ= Ex?M7O/^DF2f#sWU1eѲΟ??553;vΝ+rfffiiIDRu\ \UxNMu}D9 >|xݧfff<ѣ=&UfO#XjjF#UF]jŃdȬ. Ȧl51#UF] Ȩ=cd%Fd*.`Q#cdVE<eY]w3YbZY#{ 2ȌـF2d? c# S6cdVE< cK j$c=A dZ)[< c3 K j$cd `@V#cd62 cK%F`,1XbdE< c@IBXeȯ؄ă2ĠF2Ȭ.20 12'. cK%F̮{ ~ ُI"!@hgXbp2/A5R#cdVu-12ldvh= c,12F;X/1 1$dv2d?N2Ĩ2Ȭ.8q]gaAcѴ`dVaIŦ&` \Κ#c0*A K̰c@Lc)˲شt[D|6dD#/`,12Zweo_LYQ&$cČ%1i^.sH)yeV7/ c0jq~S%Fdvfd H\%c1 q &2lxwd M:}ٳgx1Ff;;~S1 q/+chq7x;ػwĄ'lKMh~re,/_<Ȏ;W_]pazz?ܽ{3V ׯ/toVVK=*㞰5J~=㴰ǀUfgw?B6%FCLB9 x<BXXXoiZY#q6 %{衇ѣׯ_%eMp.611~?oyycʰmf;ﯬJnǀU4V@ƀ'%&$c35.Xe͘ c@0[#c@d=2{ K%F@[ 1Xe*[#c@32 cA6!d ?~2 5. _KPl13?uX+=hReAu;X]!Kd VdvBHoBƀ.7߃@;7;uRhI#10D̬c= dLm;n3qm S c2Fu c1XeE],12d #c ޳O]< c FfM2L!!A ic1X//B(n:1U#sGbA@ms WKf  &Ǟ*c1Т;f 9G@\1ڄǴyLR c@Xe-&$c@TSs#c@T3ӝs#c1T͹d W#clmH]1 ٌm&$c1T3sbXb1Pa;& c2ỵι+pXb1PREeed1q8Ɉܾ %a`I˚`L̨ )`6fmل1VLmo9r-twܹ x"ؒc |嗏=ؽ;???55/޽{ݰe4@$0sO*z뭲,?쳃8A]XblBZq݀ydL{V9w׮]KKKK 2wСʕ+42 j^#6annn׮]?~zҥyW%xGn;t믿" ]2 !pȑΡYb岔 c]#chCꂌleBT<2kCꂌV1vr뢸2r_b2 cXb13/cro_#Q!c[b1U]L!c~AUWud $ 1TӾ'ڐ c a*=1,8Wƀnh x-1R骹52 2Z4wK 2ƠȬ2ha<-1 Qd n-12jDRd AƀxrŌ._Ơ%U5v25wK 2ƠhdVd dmjdA=A]1Ͱ܎nAT2 2Qd m[eچR_ 2t2Cw1O42 22%UF# c xH[b1.hp^Ӫ6EeaY]ǐ*aX]10aڰ. T1YfrѸǖ{ tB|3KWuA21tIoR!E+LG(lg!l.*)1eMJhdd ~^&BO̰.cʠ. cȂaY]1U^fXF]1 AƠA_#c421@vd?222 ꂌ2 cȼXe1T/3, 2 c ^fXE#cH~ɹy Xb@`dV1`XVd `C̰lAV1$ ˖d Ze 1 cُȬYe1%F#c*2̰lAd 2ò%2Vò c@ƐlXVd Qd T 2ꂌ2 cH-11$2Ffò c`Ξ={i2#s#aԩSǏwd 2HaCڽl 2W\y'''yEG=f^(CfO>>G]z'XZZr&#Ufw'z‰'.]8ڠ0!/21d=24,ws. ch˗/~G2#s5?Bv|O8p!PSn#뵳A}Eٳwə'O:H2FӜ-,,82d ̆eu!sV_tn滛u }tdnnnvvVXsy l- ]CZu14 .dP(_Um{ i~.ְ*.cH|bvŌ chM;C]Ȑ1$<-[D]h/D;C]@ c@ c1 c1'iIENDB`xgridfit/docs/bdpq-delta.png0000644000175000017500000000262110643720037015374 0ustar peterpeterPNG  IHDR|&H緸bKGD pHYs  tIME,=P'IDATx]ݚ0{雍}3d w]&z ?\@ ڏy#_At:AAmyY1Clq&D)@xD un>G-ǝDH DyAD1Emb+EvsmBģ|u܍込z<:MV%u]???o<­wϩ!<ϳ~6-eYu繠/GQ^C3eYv÷,q$J kv!r;t t|Kt:<ӑVDLGsϕhe]*WJkV/]}CV*a8I^NH6Ǵ٘% ڒEhiFt$hFub /m#D8[StzK_Yr@/)4}MuFt${d`սr-1n-_n*ᚚ;~22r$`(*f} 6y ZґmMyES(iK^_cxŏH,Eb;&FV2јKEz}tQj;ziX5IO< jD wr "79\GƵgAfa5Ogީ;2zeg;9I<^ [vxp5EʚoF tzUreL]8_{9}^z31MNY5ORMojY)u6ZS++'[{ qrsƊ,`e<_벦)yzX[o5$ַyZXj!r7g|- ;qlot/irfmαBnղ_lɭo%^:S}nY# bZ%M:VN%bKGD pHYs  tIME $+: ޑXIDATx휿k[ǟsIDC+tPu!$PDh ^:86).b;@@CqBGǦo~hsÛ'|}ID?vL4a\JLKl̪=)b9p_DhA!Â֬fHP@P JAA@dFP<i*$( (@Z J Ty AA2#(U/h0~M]ݿKP7#dJO }*?ݾ9'A! b$( (! $( (RMo߾zBPU˗ϟ?gAg_^~=߸qnr۷o߿[[[{{{,^ȅ2Ѕ;wHZXXظvGjN<*#"|CPlnnիWY<UT)"o޼{˗Y<I8w\>/KKK?D]OV:Q 5f AAGjW&kZԬ>-q5k5"Pޞ!c9 OK%.>;?YxP(ؠؿӘg?! ؃D'/Nt&_4A5`}юjUowNJ.lmBBCP (ca:!zpA'"eT;$ӔGPUGAҿ+(_7EPC*JBZMu[|H"GS@s]n2BIa&b Wy$hx %DQ AHӴjǏNMM[nm &DSŋ?|ŋϟ??{=('}-\tiqq]?}ZjHP=IMC7ussӧOv{wwWD Q⃬>EX\'O~ZɨHP/b.--]payy(HL8gΜN:۷/_ܼyL:7޽wޣG ښ\.푠٪XU-Z()˔4WCem6X@TTov+fHP#QwWSm23#)JeEGT6!kMO_rs2TX3od%ytkGטޛ6?MekS,eq'g}aΉEDq"2]&c4[02-"{$Mž|Bmk[$kͦ}\Amma{ؖF/^za[{$}Vms[$8eHI @$H" D$IO$'@$H" D$IXe#I$HL8f7T$իn|Xr\^/‹mi6K/QBoqNJ]V[NKXn" S:GH" D$I @$ KI`JJr_mnnHw-I" +DKri'HIj~<$ X3]*4yXMLk]y8)reɒIyͦvOEG1{r昤9m,Ma:[mac:cݾ$9jZd\v ~;Ͷ5AAIr4י۲JC㶘 FѶq4L=gcxv w\LuVgSݏŲIɓcGu[FMף.t=ۓoߞ8f{Sg3m7|;mlIKaB9k rN @bu6 (za@(,{D-V- F;Ddڒ;h/$ " ݩ$=b>1iH(A$8JRX]Bqc/hh䉛d4䥺ֻ%$Ƞ,I*ӧiyuGm_gL3]-o}GpHAYNe۽X&rr$$2 dor d]/eolYvIĤ/<189$9U2QI>ߞZ/*(A$1@w] !d $7p; ;~$5OK멖ߜ&D$U\ZJI%4=JIOrU/6utޱDr"Q/y2 'h1g956Ru*aGIj4z7ه8F6}q'xEj6*Iz=n]qxPk}sg^\;8$qT.*Vc&mat c2'ۇH5bn- #y=.\z''Hs\ ܞ:iQ\36>fz䢶e勠&Q=2 vQom˱Iaxgq s1majTyH`!&l)?>Li%&IHd$H>WreNwHU트mCU "y\%xID@J(2_GH t^@'nXjc1I" HHÝVId(;;:s$XjC RH $2 c?DV.#I$-dTUTUp,9$ q/ɴc rۓ r0=čš}BE%5`g<4I$2$I EpNpKm"DX!綎ʉ䒔k4O?ݸ+I:8),ᎃ<rRIj4ūW5ݼЉXͦb_{||/}.εlΕtvhH_.ջ pLH$L0M]jHb1)?"8\;GHZqP2E2IH"($I/"$(rN*ǍS" Ci^鯺woЯOeI&Rz@I74ή7_\OzySMrΑz[$)%6"WÚN~1]ݖ 3'5߼pSX ޮ1mYs"cw9 Lq4]-EBcfQr{ Kaj yo^DeX UWQo_K'JcmaXmv$Q߾$L \|I"rN`2Dұ)Z*W%g " X8EW$\b]`[ߏ)NL`y\ō1ꅑ@HzʍOdVi27OԀHѶ/K A$P*2MN)j1Ix+y$WYj*ϑdd\P5$HY^?}s,ā Ka/i(qrGGG1-GI ::;bgGG'h9w}o#A~7#6T5~?܊mYwtZ?G//^rq.~ߍQ—Lq.7X΃Nn:@JҨHI,1돾}55vrwq.. 2$= 帥Η5 ?[uPG0Ibrdr5w uQ2$BL돾;6Eښi4|A$1ƝΝ\N<=9嶉$#@$qP:NӜYjw4ji5ꏧMGI,$\gtRC9kq5En}%E+$ƆrLH"PJݟб=&A$X&&t|f$ "sws:8IQM kɼ롥$$LzJۛx ONcM drJф XZ W}iOܤM,pLߞgIQKk`" `jI @$%u/'պͶxq۫O_gl $ŚBO~1]ݖinoܖin_=|-n˚;(C\aj]]amr(>p}L(}YV۲s$0I" D$I @$ב$@$H" D$I=GH" D$X$h1,^͇}夒h883hqǢ~y->}^|WZ}̪+&m3II" D$I @$H@ O$'@$H" D$IiΑ4wVsIENDB`xgridfit/docs/o-bottom-rounded.gif0000644000175000017500000000362410643720040016534 0ustar peterpeterGIF89a p ! ,`$dihlp,gx| ',P܉P2ʜRQ[r//,֑>qwnf|^/6wujhe_\~WT|PMUJ[kkn˗pzcrNs{Q%G$E#x-!L0_Az . zàe&[I:y| !:q|2I !ѓ7I6Elz~: <`=jMSv\-uT6jL]u|(VY:^lذueItNK/XWrۨč(mLT徜1T [_HwҲɘ ׄ9ۦڴ>VӃȓ+_μУN:gسkνÇ?೅lꑂ"pv:26޽hU'6y8 78_O1E}w!ehHb!Z!D >!{%F"e2axBۄ0#33IDx(MR9e;8Вly%\^R>\VBGV%Vfo_馝w"Y78$p\$x(I}'2E:~B*h ꉌy)vi*Zkjk@Je^h)k+ڬʫVJõfvKæ{k6lj뺪,[o۠ko`S ;jÑ/ R1ڏkܦ訛ħꔗ88f^ʷn9@`'7G/WoMܛ}ÃϺb z$î/{cw1NW?ξ_g>s2x< HjtcqGςhK`8 ӿg&Da<蛠I0]aV#ް>,[B?" VhD1Q|zT#ҐW,O8@.^ЅYbC,fH]7Ap tT40j!h;zQ0D f"}#|I!8<%#; }G: K$IG1ReHOb @.2}!24$"LWX 1cVռSD5TӚ^6mԆ=f}v xgridfit

Managing large projects

XInclude

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="http://xgridfit.sourceforge.net/Xgridfit2"
              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="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                xpointer(/x:xgridfit/x:glyph)"/>

Here the href attribute (a URI) points to a file. The xpointer attribute points to the element or elements that we want to import into the current file; it is an XPointer (usually a simple XPath expression). In the present example, the XPointer expression pulls in all the <glyph> elements from the file Junicode-Regular-Basic.xgf.

It is necessary to specify the Xgridfit namespace for each <xi:include> element, and this makes the <xi:include> tag rather verbose; but much of this is boilerplate which can be copied from tag to tag. Indeed, the only variable part of the xpointer attribute is inside the final set of parentheses.

Several Xgridfit 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"/>

Notice that you do not need to worry about namespaces when you use the xml:id method.

Some XSLT engines can handle XInclude and others cannot. The XInclude capability in xsltproc (the engine invoked by the xgridfit shell script) is turned on by simply including the parameter --xinclude on the command line (this is done for you in the shell script). For some other engines, turning on XInclude capability is an arcane and difficult matter: you must check the documentation for your preferred engine. The xgridfit shell script uses xmllint when necessary to work around difficulties with XSLT engines and XML validators.

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 little besides <xi:include> elements:

    <?xml version="1.0"?>
    <xgridfit xmlns:xi="http://www.w3.org/2001/XInclude">
      <xi:include href="Junicode-Regular-common.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:infile)"/>
      <xi:include href="Junicode-Regular-common.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:outfile)"/>
      <xi:include href="Junicode-Regular-common.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:constant)"/>
      <xi:include href="Junicode-Regular-common.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(//x:control-value)"/>
      <xi:include href="Junicode-Regular-common.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(//x:function)"/>
      <xi:include href="Junicode-Regular-common.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(//x:macro)"/>
      <xi:include href="Junicode-Regular-common.xgf" xpointer="jun-reg-prep"/>
      <xi:include href="Junicode-Regular-Basic.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-Latin1.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-LatExtA.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-LatExtA-dotlessi.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-LatExtB.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-IPA.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-SpacMod.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-CombDiac.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                              xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-LatExtAdd.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-GenPunct.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-Greek.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-PUA.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x:glyph)"/>
      <xi:include href="Junicode-Regular-NoEncode.xgf"
                  xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                            xpointer(/x:xgridfit/x: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, just by way of illustration). The other files contain only <glyph> elements organized by Unicode range. These are included with a specific XPointer, /x:gridfit/x:glyph, rather than //x:glyph, to avoid pulling in <glyph> elements inside of <no-compile> elements. Each file validates against the Relax NG schema xgridfit.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 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.

Separate compilation of source files

Though an Xgridfit file is destined to be included in a master file, it can also be compiled separately. This may be convenient when writing instructions for a specific range of glyphs. To prepare a file for separate compilation, simply use XInclude to pull in global elements from the common file. For example, one of the Junicode source files containing only glyphs has these XIncludes:

  <xi:include href="Junicode-Regular-common.xgf"
	      xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
			xpointer(/x:xgridfit/x:constant)"/>
  <xi:include href="Junicode-Regular-common.xgf"
	      xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
			xpointer(//x:control-value)"/>
  <xi:include href="Junicode-Regular-common.xgf"
	      xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
			xpointer(//x:function)"/>
  <xi:include href="Junicode-Regular-common.xgf"
	      xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
			xpointer(//x:pre-program)"/>
  <xi:include href="Junicode-Regular-common.xgf"
	      xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
			xpointer(//x:macro)"/>

If any glyph program in the file needs to refer to a glyph program in another file, this can also be pulled in via XInclude. <xi:include> elements for this purpose should be placed in a <no-compile> element, which makes them visible to all the programming in the file but prevents their being compiled. This is from Junicode-Regular-Latin1.xgf:

  <no-compile>
    <xi:include href="Junicode-Regular-Basic.xgf"
                xpointer="xmlns(x=http://xgridfit.sourceforge.net/Xgridfit2)
                          xpointer(/x:xgridfit/x:glyph)"/>
    <xi:include href="Junicode-Regular-NoEncode.xgf" xpointer="CapAcute"/>
    <xi:include href="Junicode-Regular-NoEncode.xgf" xpointer="CapCircumflex"/>
    <xi:include href="Junicode-Regular-NoEncode.xgf" xpointer="CapDieresis"/>
    <xi:include href="Junicode-Regular-NoEncode.xgf" xpointer="CapGrave"/>
    <xi:include href="Junicode-Regular-NoEncode.xgf" xpointer="CapTilde"/>
    <xi:include href="Junicode-Regular-SpacMod.xgf" xpointer="circumflex"/>
    <xi:include href="Junicode-Regular-SpacMod.xgf" xpointer="tilde"/>
    <xi:include href="Junicode-Regular-LatExtA-dotlessi.xgf" xpointer="dotlessi"/>
  </no-compile>

Note that any of these included glyphs will be compiled if specified in a <glyph-select> element or with the -g command-line option.

Remember that you must either take care to avoid recursive XIncludes or comment out the XIncludes in a file before including elements from it it in another file.

Another strategy for speeding development is to create a quick-and-dirty Makefile for compiling and displaying a single file of glyph programs. The following example uses merge-mode, in which it is necessary first to compile the file containing the font's common elements (functions, control-values, etc.) and run that script. The Makefile compiles the common file only when it has changed.

FONTNAME = MyFont
RANGE = IPA

COMMON = $(FONTNAME)-common
COMMONSCRIPT = $(COMMON).py
COMMONXGF = $(COMMON).xgf

GLYPH = $(FONTNAME)-$(RANGE)
GLYPHSCRIPT = $(GLYPH).py
GLYPHXGF = $(GLYPH).xgf

SOURCEFONT = $(FONTNAME).sfd

OUTPUTFONT = $(FONTNAME).ttf

INTERMEDIATEFONT = temporary.sfd

$(COMMONSCRIPT) : $(COMMONXGF)
	xgridfit -m -D -c yes -O $(COMMONSCRIPT) -o $(INTERMEDIATEFONT) \
	    -i $(SOURCEFONT) $(COMMONXGF)

$(GLYPHSCRIPT) : $(GLYPHXGF)
	xgridfit -m -c no -O $(GLYPHSCRIPT) -o $(OUTPUTFONT) \
	    -i $(INTERMEDIATEFONT) $(GLYPHXGF)

$(INTERMEDIATEFONT) : $(COMMONSCRIPT) $(SOURCEFONT)
	fontforge -script $(COMMONSCRIPT)

$(OUTPUTFONT) : $(COMMONSCRIPT) $(GLYPHSCRIPT) $(INTERMEDIATEFONT)
	fontforge -script $(GLYPHSCRIPT)

When you type make MyFont.ttf, this Makefile does the following:

  • Compiles MyFont-common.xgf to make MyFont-common.py
  • Compiles MyFont-IPA.xgf to make MyFont-IPA.py
  • Runs the script MyFont-common.py against MyFont.sfd to create temporary.sfd
  • Runs the script MyFont-IPA.py against temporary.sfd to make MyFont.ttf

This font contains all the glyphs in MyFont.sfd, but TrueType instructions only for the glyphs in the IPA range. To do the same with a file containing glyphs for another range, you need only change the RANGE variable near the top of the file.

xgridfit/docs/trans-to-1.html0000644000175000017500000002576011311672227015455 0ustar peterpeter Xgridfit

Updating Xgridfit programs

With the introduction of Xgridfit 1.0, a number of elements and attributes were deprecated. Most continued to work, while a few had to be removed from programs. A utility, xgfupdate, was introduced, which automatically updated Xgridfit program files to use the newer, recommended syntax. A special schema, xgridfit-transitional.rnc, could be used to validate programs that retained deprecated but allowable features. More features were deprecated with the release of version 1.10, and xgfupdate was updated to substitute approved features for deprecated ones.

With the release of version 1.11, support for all deprecated features was removed from the Xgridfit compiler, and the transitional schema and the DTD based on it were both removed from the Xgridfit package. Therefore it is essential to run xgfupdate on older program files to bring them up to date.

By default, xgfupdate only does what is needed to update from version 2.0 to version 2.1: that is, it adds namespace declarations where needed (on <xgridfit> and in references in <xi:include> elements). Invoke it as follows:

    xgfupdate oldfile.xgf > newfile.xgf

If you have older program files that need to be updated for compatibility with Xgridfit 1.19, invoke xgfupdate as follows:

    xgfupdate -v 1 oldfile.xgf > newfile.xgf

Then run the program without the -v 1 attribute, if necessary.

These commands will convert a batch of Xgridfit files:

    mkdir new
    for f in *.xgf; do xgfupdate $f > new/$f; done

If you have XMLStarlet installed on your system, xgfupdate will format the new file attractively; otherwise it will leave you with a valid file which is messy in some places.

The following sections outline the changes to the language since version 1.0.

Namespace declaration needed (2.1)

The <xgridfit> element requires the namespace declaration xmlns="http://xgridfit.sourceforge.net/Xgridfit2". This change also requires revision of most <xi:include> elements: for details, see the XInclude section of this documentation.

Attributes count and highest replaced on <legacy-functions> (1.19)

There is now a single attribute, max-function-defs; this should be the same as the corresponding maxp entry in any font being converted for use with Xgridfit.

When generating Python script, use pyflags attribute on <outfile> (1.19)

When you wanted a script generated by an earlier version of Xgridfit to generate a font (rather than save an .sfd file), you could include an fmflags attribute on the <outfile> element: this was an integer to pass to FontForge's Generate() command.

With version 1.19, you should still use fmflags when generating a script in FontForge's native scripting language. But if you are generating a Python script, you should instead use pyflags, a list of values documented here. Actually, it is perfectly all right to have both attributes on the <outfile> element.

The offset attribute on <point> and <with-param> is not permitted (1.11)

The offset attribute has long been discouraged; use an expression instead, e.g.

    <point num="p + 1"/>

With version 1.11, the offset attribute is no longer permitted.

Use <push> instead of <to-stack> (1.11)

In versions before 1.11, <push> could be used only to place on the stack values that could be resolved to numbers at compile time. It can now be used with values that must be resolved at run time, and thus <to-stack> is no longer necessary.

Use -p (push-break) option instead of -b (delta-break) (1.11)

These options are meant to prevent Xgridfit from producing a command string so long that FontForge cannot process it. Xgridfit breaks up long PUSH instructions into shorter ones; these options determine how long those instructions can get before they must be broken. In versions before 1.11, the -b (delta-break) option applied only to deltas; in 1.11 and later both -b and -p (push-break) affect all lists of numbers to be pushed onto the stack. When -p is omitted but -b is present, -p is set to double the amount of -b (because deltas involve two numbers). When -p is present, -b, if present, is ignored. There is no plan to remove the -b option, but -p should be preferred.

value attribute on <param> element behaves differently for functions (1.11)

In versions before 1.11, the value attribute on <param> was evaluated with <function> as context, making the function's other <param> and <variable> elements visible. This behavior made no sense, as value was evaluated before execution of the function began. Now the active context when evaluating value is the <call-function> element. This means that name collisions with the <constant> and other elements of a <glyph> program are possible. However, access to such elements may at times be useful.

Use name attribute to name things (1.0)

Earlier versions of Xgridfit inconsistently used name and id attributes to name things. To refer to named elements, it used function-id in function calls, macro-id in macro calls, and param-id in passing parameters to functions and macros. In versions 1.0 and later you should use name everywhere, including these elements which formerly used other attributes:

    <function name="my-func">
    <macro name="my-macro">
    <control-value name="my-cv" value="235"/>
    <variable name="my-var"/>

    <call-function name="my-func">
      <with-param name="my-function-param"/>
    </call-function>

    <call-macro name="my=macro">
      <with-param name="my-macro-param"/>
    </call-macro>

<default type="max-instructions"> is not permitted (1.0)

This <default> type is used only by pre-1.0 versions of Xgridfit running in TTX mode. Since this mode is no longer supported, the <default> type has no function.

<asm> no longer permitted (1.0)

The <asm> element was used only in TTX mode, which is no longer supported. Therefore <asm> elements must be converted to <command> elements. To do this locate the sed script convert-asm.sed (Linux users will find it either in /usr/share/xml/xgridfit/utils/ or /usr/local/share/xml/xgridfit/utils/) and run it as follows:

    sed -f /usr/local/share/xml/xgridfit/utils/convert-asm.sed oldfile.xgf > newfile.xgf

The result will be an Xgridfit file that is valid for FontForge mode. This conversion is also done automatically by xgfupdate.

Use value instead of num attribute with <constant> (1.0)

For consistency with <control-value> and <param>, the num attribute on the <constant> element has been changed to value.

Container elements are not needed (1.0)

Older versions of Xgridfit required the use of certain elements whose only function was to contain other elements: <profile>, <control-values>, <functions>, <macros>, <declarations>, <variables>, <params>. These elements are no longer used. The elements they originally contained which are children of the <xgridfit> element can come in any order (in pre-1.0 versions Xgridfit was rather fussy about the order of these elements).

<param-set> not always needed (1.0)

<call-function> and <call-macro> elements formerly could contain only <param-set> elements, which could contain <with-param> elements. But <param-set> is a device for grouping parameters when a function is to be called repeatedly via LOOPCALL, or when macro code is to be inserted repeatedly. It is unnecessary when a function or macro is to be called just once. Starting with version 1.0, <param-set> is needed only when a single <call-function> or <call-macro> contains more than one set of parameters; otherwise <with-param> elements can be the children of <call-function> or <call-macro>.

Use min-distance instead of min-amount (1.0)

Before version 1.10, a min-amount attribute on <diagonal-stem> indicated that minimum distance should be used with a specified value. This was inconsistent with the usage of the <move> element. Beginning with version 1.0, and obligatorily with version 1.11, min-amount is not recognized; instead, specify a new minimum distance value with the min-distance attribute, which can take a number, or yes, or no.

xgridfit/docs/A4.gif0000644000175000017500000001607310643720037013612 0ustar peterpeterGIF89axp  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~!Created with The GIMP,xp H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8#/>{Ƀ:u̥cn|rx֡+'۶kԢ5 9vI=ϞD:օlXW01DM(gHBkZ"&.qfQ D9O?Ó;Lc .t !xFIcQ+ǀO>р<>d.lrI@ CpQ#hC;=A/pHh|aE@ #P4< ϒUCqL-8T4a8Ġh2 3Ô43QF0d! I iPlp9*08 2`.T D f `%@&Ѐ8 Є,!, ذ@-F ? cB%5h 60 tP(lD+a uxq ,8: _Ѕ.p! F HA fЃ#@ AE/EuP P,p d8 2X :h"0P$hA z`.a4Q"C #%D! aHD V0B J@,  Z@s<0%XA nЃ!$ E܁ Q 0@<A T X9Ε a c &1Yxrb$@:a vD+16jH+&.;P"p p$P hS#PQ qA>"|x@Q })v \oND@@,pslE*.Q9 = Y$#2j nK5` 8@ `4`4Ԋb0G:2|FMijA J BbD8?1;CBdpxP@ ;8(3 sjna p-0A yxD)x!`%ц,8A7`A,XC ];L+F G mwaUd6a WPdP 0q*`+[YF:8y(.\!ML5{pŢpN; [Bpl t0 f4#ȣX/bA KH@8bE2E06D"-,-  Z` VqL@E&Cb} 3T8 ;$ 0s R 1@! B0d@@ ]%  0Pp @ @T |Yp50.Lj ʐ ` 0w00 @ P PrL&0D)pE0`=}E` gu 0 <g 7 f = % -uyzaW` Ppbn@z P հ p @vk05@G,pCY^vT8aWOp g Vn kL.';PNf` <].TR @]pJQM4k z tfL3`"3Dr `%iW3! b @@ @l@<A0FKP`Hz@ncW G3pqp`@,0:  BB"$^Y < ` }@J3@5`8:@PIRpW0NF=P.`p` $@TI! "2"P0BZ Ű `[&p(+1@7==7@1,gr4h P`V0!`oU !2)*1 b ` Sp^u ^ F/?0pS` pХ)") @h.0/;1PR:R*X .hP "1!'%CԠ Pk6! |ڧ~ / +pc Db$_1!.+CV PmR&,3`9@ڪ ;`1&^" CzP 'e&O!)/ `pF6BN@ZpK XI: ,aJ%Z@e\e`  `sNDUfw;[[kWC.p* p ;0& @ i-0qo p p `fQQg ~ HJH; mPG4'*tk7i`2ѐ2-zc}7 @ kPl4 z|۷z 0dPI%4c  ѐ r/a0 q`Z|0 [{{} PcG#* fO  0 @00A Ԡ P  ve@Xz` iL.0wO]m0 0 p \p ` 0 pvEZD}p  A4D5p= f@  ݀@֐ p CHCFˠ vpX;0~`9_  Po0 P `5xp7@C  aA p05pXp @ G!Ɏ V~` C>3=Aȍ1Q r  QC11zp 0 Sz ;<> ?v~-Jhp@ pY@ `ct s99Q<ǃ }S*P60Q@7 ڠ/s)S `7# ԚC@0H@`p{ p  x Kl N 5zsp p ]`^ P 5J9P J#Y$  @nB YU@ d!oPo 0 z Ig&8 Ku @!"ҹX)B`p pd9]χ` @@oY "L1A`kmL@$ 00߰ m0@W [kfVl pM0PP )7a`] e[A`@3 P f `CP0rǽУi' Ҁ 0΃4 `T&@ U^++0 @ p@8`Y$ א@:Ѡuְ xS m;psp 㐯J`[ 14̾vm P!>J1=Ӳ P iP?6@Qne  W\ p ~PK@<>p)MVd p n @ 0  w}K 6B ^ P  a "+w0#RqPp ` P P P %wr1 ΐk prx?p`L=Im~~qր ; [7ʽ(^"I<5ٶs]ĘQwߞzџlhvp FQ$dA $@kjA$%`gzꪯk:뫫&dQd&p9vt\\EPO_<QZɥhA"G'pgOGO|Wt)&=wxh w`~'=hw9vuw>{Fdɦyxwt{恇t?~w}rayXW7?P~ ౿ˁ`%8A VЂ`5AvЃ ;xgridfit/docs/o-top-500-y.png0000644000175000017500000001115210643720040015156 0ustar peterpeterPNG  IHDR^bKGD pHYs  tIME 1*iQ!IDATx]l߁U1n0l`c8>JAU!I#D+Y "Ϲ9ЪU/6,Cu{Z5Y9^TzS,> ƨu֎1N"^z<ٝOQ}g?wVu]'!Dʯ1>]"ɀB8*2`Y1!!WD9pdk `+xTǘ"n*p̀U )[fL7] wfed61#^c `9xM™C&3H &D+ &ᄆo@h2Û@e7 o27 @R Xe7 ]1Xe.LrO&a @11$IBDl~睭^y={_:tznO&ȡ$YV:F`1t}q=,5n˛o<9zUU7w2o}'C'nj86+VWHx7E] ?LkXluȑA#r/CÇ 1@ fbb|:V3>n>hQsI Jʒg3w?x;_{v̼13w/}!> R|%E](Ic\k/8iXw܃?#5}ix&M.\lqnddݻvwPP~pСުL&?vaԩꩩ;#WNשΝ$1ݻ'vV{^߻q={}$g0 eG1{F=n"0P@`0M `gVE4V#aZJP ]1xJraXJ+"Z]PBގF2M=ynJna ,7!u]¶Ë+'|/̪gEπO7+uʻHVacMҽ:J&UeʙU5S\: ?"4sBxlcwUi%7գPp)b˞Ǹ5Ы"Of'U1P>s?I ]Y؏_%&5ߤۋ 4kq״x*+סSYd1w(z=sk D(]Qvc!wʩ 9=v)V*(Ϳ,'>zlX8JBfL7] wf/x'9,weSMt.0*_ȲQ=H6T@w)B*bXMkU\#ge=rҹMkSݥp e ]1Xe M"`-2Û@e`@zF=z)1#F=7v#F=|cèG IY&!xĀUpx"@UpxoM"2 &d3 MgVM|mW VM*C8I7pd\o27 1D Q `#0L0aS#ĀUpx"@UpxoM"2 &d3 MgVM|mW VM*C8I7pd\o27 @J Xe7 ]1Xe7 &$‘*b@ `ȂQ@ %|cèڮ|cèop17 $9do=o@hboVMI#T$,xpI Rb*C8Io*C8IXe7 & P xM™C&3 0Dz#61#F=p1a2 F=ljd=o@hboVMI#T$,xpI Rb*C8Io*C8IXe7 & P xM™C&3H &D+ &a!$D82@e@ zY0aS#Āop"@op`#2 &d3 MgVM|mW VM*C8I7pd\o27 22ң~M#!@c-U $p8!z$#82I{$kav2c<ɌYiR2x$8 pR`ajV%X1Q&-jdr;)Q HNhUU#E=AThUR_J@Twg/VyDlR2jC92$P҄қʐ3soxpT @ ߇Q c)'oR1 3U>`}^}x/~ʲKx TΧXa*$LL2_Z:*mM?9*U |T2 둱#VU?FIŞˣMat(jEÖ ,NDR,wP+{(x#$0ޤސYcp̰b O8Cbޤ"oʚtJs[Umap){)mV~p5 BLVpGnQ(Spg\8Ɇ!p3&gg!Ts^7i)/9`D2YYD2(U:'UP PQGRSgrĠx\6K'31kWs̳ ϵcd>#/K7t(%b;lX?55__gT"< [֧uu#xIpx62;sg϶چ7?ݰO\>x0vmdۇ=BӻOë %)DܱcBybe:gLa 7Exz2w[|sh/߭]5^[C'Nnj86+VW42!xܹ3g=z{˖o|o]uuw_fQᇍwСMW~RS\ ==d=i[ٵf0t! cϴދfZ[i\9r^,v롇npێȖ7uڵwŸ$KS !׌q!tGt?s@˜ԗa^1\ijmm鶶̧mnn;j]sGۿ+-#cc76"J%䚉 >$>7;:~{4!>7n<}p` 7{ȿ\th p$I&O6lXޱusS񑑿?ķnv+{z cUmw~oD/› YHQDp Ώu/=9#^\SӢ2LKN? W{9rOck/\Hwhq6=_njڶx|n֝w=[ #O]7<UiIh]3l~Ӧ ۄP!c_nSNܼqtS>u~{MKߙN !?|{˖}饻UU>*nߏuw vsϷW::7!>lKnob$S[\+LJL<څS׏wsէ:u:}msf>S/V9#Z_g?53[G=}Fiuax|rrb]Bfɵj&I4NA8|0Ƣb > >/(&IFO~,*|øA C ^73[odch:|c\0|7fRmu]B0h4rL@uBz ضdnԆ:底劁ti,JV&Xnʺ\׍c H:5Moi0 |n *xy˲2M1u3fv_t] GG>:/|^,纏"4 Lv0l@\Ycs9J^oI6\NJ"Ρ:eę(<ϋNo,˔K雎v 0>e}8Ѥ:4/Smî, J­1zۂ@keRs2E6L~X:ur6lMt~~δ.\,mYmdD;TZ?.*a\۸yEyv(mېuԏ$x?(,˲)%4qrB.>O1>H4[uy>8Hl[v?W.h:MX}[+3r@Pׅ+9&?$gʶaYV$KH۶#Q&iUU8i&}W}?9g_".0`!P7F^󲶻 ud]eij:sA1vĎ.f_.?(.8!w:Fi y1ߵCOjkw i0Fູ cX,dˌ.y}ϬʔRx̟H#c0}?E^]d,34 Ý;Ο͊ 0<Ƕ iRض? ^1x'ƫ p ;w##A KңK9a>XVeSacPFy|IwoU>C)3:ML&,òP4I',w//{<\!*5 p/WeqrrA44{1E"aOL裏"q"ɓ8`YgΜe󶞚 fY2[ATSA`iIo2#d1;g122ߒ/6mpϒCURaxO3dZ;L.'Ydէ>~?/c1)U՛L&8,I"9vIt0 %;-i/5.'oHͭ[@J.CAy0lDE}Q 9MS8ΓO܆bu;OV̫m< ?̩G.OOU|.m; \ ;|0Lӌk+rD!!DHaĒ$ggSGbmu 6@,(չ\ < Ȍx\Gbe r|SeSܐRt9-ms3u5uVxO-?By^iu_`Hcb;>!]Qyd9/M/&}jl}e>Vl+qgUgSn.{(ʢ*/S "',NmG) po<QV~ :;C.3b=t>qq8_NTr'OAsYp, ի~&2PL=Y{ߦ} a ކi~XV2a8v˜hڞfꔹ)GV l9aD3pȷO0O(V㭎W?9d|Xh/^AU~1 ^ 9; !GIɲh-16tXͬWiGv% cu11b/pMl,q>2u3۲ϲ!DJɏ)Avb^uD+jϯWܮq _ζmR JiBT&鉠h%{b.k \O?)*ya ܮ{Ap)feH_ppw' uq=+Bë ed''}'}r`,a6H(&1ӄ@λң%ɛWX~,*ѭo>YbPMHj2ryp8"p=_ ˲z-;oJBzDA9d2t3GJm]1˿9Vgb7igE ԑ[x)y.~Q~:٩K tďlU8vMQuM+摗 N\K}p?ƶFiЭWN]ZdZ-ׅ!Bse8߲B89UێxCekۄbSķFK^/yXZ JC>~Ұ5^n@-nU0;utJf-v,m7u|[_mxk]am8zAÖl;}w݉/{sL~`ze1L*Lw=95]'0SmnkksA겊٪-GˬcmCr;zw[3 񙑯ݗM- <ܱeeai/X<3 uu >InsM)2-d%`(~?;/}QՂx7 $!RW"j9VWvivqxgU0 RRpXNz=9.Jo0+ ɽ+ p8? w:f7azձl7bGU;kw蠊 q Xgridfit

Tutorial 1: Gentium's period

To introduce the basics of Xgridfit, let's instruct one of the simplest possible glyphs: the period. Here's what it looks like in Gentium Italic when opened in FontForge:

Gentium period

Our aim in instructing this glyph is to move key points onto the gridlines (which run between pixels) so that the TrueType rasterizer always renders the glyph cleanly, without relying too much on anti-aliasing and other tricks. Here's how the uninstructed period sits on the raster grid at twenty pixels per em; notice that none of the points falls on a gridline. The darkened squares show that the anti-aliased glyph will be a shapeless blob.

Gentium period

We need to fit only the four points at the extrema to the grid: these are numbered 0, 5, 8, and 13: a sensible start on our project would be to name these points. At the same time we will erect the elements that every Xgridfit program and every glyph program must have: <xgridfit>, <pre-program> (needed even when empty), and <glyph>:

    <?xml version="1.0"?>
    <xgridfit xmlns="http://xgridfit.sourceforge.net/Xgridfit2">

      <constant name="left-sidebearing" value="last + 1"/>

      <pre-program>
      </pre-program>

      <glyph ps-name="period">
        <constant name="last" value="15"/>
        <constant name="left" value="8"/>
        <constant name="right" value="0"/>
        <constant name="bottom" value="5"/>
        <constant name="top" value="13"/>

      </glyph>

    </xgridfit>
  

We have also included a global constant left-sidebearing, which gives us access to the left sidebearing point for any glyph for which we have defined the constant last (which points to the number of the last point in the glyph outline).

Let us deal first with the horizontal movements of points left and right. We'll put all the programming for horizontal movement in a with-block:

    <with-vectors axis="x">

    </with-vectors>
  

Our strategy will be to position point left, and then position point right relative to it. In deciding how to position left, it would help to know whether its distance from the left-sidebearing point is a standard distance in this font--that is, whether other glyphs have the same left sidebearing. In fact, the colon and the exclamation mark have the same left sidebearing of 51 font units; a control value will help us control those glyphs in a consistent way. We'll put it right after the global constant:

    <control-value name="period-left-sidebearing" value="51"/>
  

Now we can add our first instruction to the glyph program We will position point left distance period-left-sidebearing from point left-sidebearing:

    <move distance="period-left-sidebearing">
      <reference>
        <point num="left-sidebearing"/>
      </reference>
      <point num="left"/>
    </move>
  

Since we have not said otherwise, it is implicit that we want the distance to be rounded so that left is positioned on a gridline.

The width of the period is also standard in this font, shared by various dots in (for example) the colon, semicolon and exclamation mark. So we need to add another control value:

    <control-value name="period-width" value="232"/>
  

To control the width of the period we position point right relative to point left. We could do this by adding a <move> element right after the one we just wrote, like this:

    <move distance="period-width">
      <reference>
        <point num="left"/>
      </reference>
      <point num="right"/>
    </move>
  

But it is better to nest the new <move> element inside the other. The point in a nested <move> is always positioned relative to the point moved by the parent <move>, so we can omit the <reference> element:

    <move distance="period-left-sidebearing">
      <reference>
        <point num="left-sidebearing"/>
      </reference>
      <point num="left"/>
      <move distance="period-width">
        <point num="right"/>
      </move>
    </move>
  

That finishes our work on the x axis. Let's look at the result. The program so far looks like this:

<?xml version="1.0"?>
<xgridfit xmlns="http://xgridfit.sourceforge.net/Xgridfit2">

  <constant name="left-sidebearing" value="last + 1"/>

  <control-value name="period-left-sidebearing" value="51"/>
  <control-value name="period-width" value="232"/>

  <pre-program>
  </pre-program>

  <glyph ps-name="period">
    <constant name="last" value="15"/>
    <constant name="left" value="8"/>
    <constant name="right" value="0"/>
    <constant name="bottom" value="5"/>
    <constant name="top" value="13"/>

    <with-vectors axis="x">
      <move distance="period-left-sidebearing">
	<reference>
	  <point num="left-sidebearing"/>
	</reference>
	<point num="left"/>
	<move distance="period-width">
	  <point num="right"/>
	</move>
      </move>
    </with-vectors>

  </glyph>

</xgridfit>
  

And when we run it from inside FontForge, the glyph looks like this:

Gentium period

It doesn't look like much yet, but you can see that points left and right are positioned on gridlines.

We'll start work on vertical moves by adding a with-block for the y axis:

    <with-vectors axis="y">

    </with-vectors>
  

The distances we have to work with here are that of point bottom from the baseline (-31) and that of point top from bottom (277). These are also standard in the font, found in the colon, exclamation mark and elsewhere. So we add control values:

    <control-value name="period-bottom" value="-31"/>
    <control-value name="period-height" value="277"/>
  

We'll start by positioning point bottom at position period-bottom. Since we are positioning the point on the grid rather than relative to another point, we don't need a <reference> element; and the distance will be rounded since we haven't said otherwise:

    <move distance="period-bottom">
      <point num="bottom"/>
    </move>
  

Then we'll position point top relative to point bottom. Once again, the preferred method is to nest a <move> element in the one we've just written:

    <move distance="period-bottom">
      <point num="bottom"/>
      <move distance="period-height">
        <point num="top"/>
      </move>
    </move>
  

Here's the result:

Gentium period

It looks really bad because we have moved only four points of the fifteen that make up the glyph. We can position the rest automatically by adding this instruction at the end of the program:

    <interpolate-untouched-points/>
  

And the result looks like this:

Gentium period

The glyph is rather narrow and tall at the resolution we have been using for illustration (20 pixels per em). If we want it to be rounder, we should adjust the control value period-height: that way, all of the various dots controlled by that control value will be adjusted at the same time. We add these elements to the <pre-program>:

    <round value="period-height"/>
    <control-value-delta>
      <delta-set size="11" distance="-8" cv="period-height"/>
    </control-value-delta>
  

The <round> element rounds the control value period-height at all resolutions. The <control-value-delta> element shrinks the distance by one pixel at 20 pixels per em (for details about the operation of delta instructions, see here). Since the distance period-height is already rounded, we can add an attribute round="no" to the element that moves top. Now when the program is run, the result looks like this:

Gentium period

You can check the appearance of the period at various resolutions in FontForge or using ftview (a utility that accompanies FreeType), and add <delta-set> elements to the <control-value-delta> element as needed. Now the complete Xgridfit file is as follows:

    <?xml version="1.0"?>
    <xgridfit xmlns="http://xgridfit.sourceforge.net/Xgridfit2">

      <constant name="left-sidebearing" value="last + 1"/>

      <control-value name="period-left-sidebearing" value="51"/>
      <control-value name="period-width" value="232"/>
      <control-value name="period-bottom" value="-31"/>
      <control-value name="period-height" value="277"/>

      <pre-program>
	<round value="period-height"/>
	<control-value-delta>
	  <delta-set size="11" distance="-8" cv="period-height"/>
	</control-value-delta>
      </pre-program>

      <glyph ps-name="period">
	<constant name="last" value="15"/>
	<constant name="left" value="8"/>
	<constant name="right" value="0"/>
	<constant name="bottom" value="5"/>
	<constant name="top" value="13"/>

	<with-vectors axis="x">
	  <move distance="period-left-sidebearing">
	    <reference>
	      <point num="left-sidebearing"/>
	    </reference>
	    <point num="left"/>
	    <move distance="period-width">
	      <point num="right"/>
	    </move>
	  </move>
	</with-vectors>
	<with-vectors axis="y">
	  <move distance="period-bottom">
	    <point num="bottom"/>
	    <move distance="period-height" round="no">
	      <point num="top"/>
	    </move>
	  </move>
	</with-vectors>
	<interpolate-untouched-points/>
      </glyph>

    </xgridfit>
  

The illustrations above were generated by running the Xgridfit program from the FontForge GUI (File--Execute Script). If we want to run it from the command line, we must add <infile> and <outfile> elements somewhere near the top of the file:

    <infile>Gentium-Italic.sfd</infile>
    <outfile>Gentium-Italic.ttf</outfile>
  

And now, supposing we have named the file Gentium-Italic.xgf, we can run the program with this command:

    xgridfit -f Gentium-Italic.xgf
  
xgridfit/docs/b-hinted.png0000644000175000017500000002706511130460714015055 0ustar peterpeterPNG  IHDR"sRGBbKGD pHYs  tIME&%fe IDATxy`T?gd&d% PvjZ.mnVk]Vk].ladGI d-3s~DYgG̙y{4uLLM4>d[4PgtѮlP!E~VqBARV Z/ƄLdc %ceZn_ìڶ;MaJ>$=`Ax(J= P5B&ZSqr>ewrs |ڹ+qYܾ496e˫i"꾆j0}%C5Y_ 5>l_Cz|4z̽jluk1̏Yƨ2HIMZjiM}m_v4Qi2͖5z2rzg{OLB#Y6ҳll_ZWMSʺz؟1uo Kq ۘ6!'Hey!#or3P= P5TohgF`w.6go.or^KmCVtO-3rz"Ɛ dpOddJ-l0gk2,0.ԇ+<:yjȝD\>ӳ`.T?5f8T;k:jI͂*I$bTG"_B8.=[Ū+qN&HcZM7@' ؚѸOjq,˸7 zm xvDqq@]'8^hNI3dlV.ZMvtNPnvu{WTALrȶ d II &h搭It=G` =Z6xk<5~? r˖ʊ{TozaĔ 1,ن4,ʎ$IT|4_ߧ0E0ӄW'qzж4; 18~qxs|X46%7aS8L%.LM4=-m;R5p JY%ב_4 A _z`eTlkk=c„a-D rQ42]fssl٫@<;*(Xo4_S A&#͆zl>Ҹe ( []iG<;V\Yʵ,[*V}׭:WQ^ʣ͑hd3*]?puO}LGʵ+VE.[wZF : DYqȿ{{Gģ C]#htMA'W3fE8#ajbk舣9Kr-#j.۶UD`HWRjM]("Y<. )rtc=c:_ _Adc&Xq;/GW{ʀAe -" s?6^#_Y sGQIa QgB%5rϾ#-('b4F~U؂aah 񻉿X16Y/@g(J*{. ,?w3CK_AP2OdkjFeּKz_AP4A4gzi;$jg7lSd\c@d&^%ЈO2Q8ɕ$ctɀ&5WwG\74Fن4Ӏ˾0ۇ> )*=A65&6)-.5foCnT_AP7i \Cu=G"\V$KEBlQ0HARlQ0HȌ̤q\lQ~S去y:~OkA'lԑަ-">AD6O1ȝP ~㌄HU6,@g$h:UlQ0N X.E8A'BJ"}p[ yCCټn6A6oh 5m}BlFCOm}BlA6k]"}p[Qd0@ #AK xd"M WA  @ ~80@ |dd@CB_C!l!l~AAh [k [4D-5p@80@ #-"u|Ӌ "&o@G qfd@CB_C!l!l~AAh [k [4D-5p@80@ #-"u|Ӌ "&o@G qfd@CB_C!l!l~AAh [k [4D-5p@80@ #-"uv;88JgX]X@BB0EO"he<1$)HRfe6>d;wRI dwI:#TwlN&f$n䂞4.5 g?'%? l ҊUiŢ>Crj:5&j+FK05:>xG~<8'#hl*8NI$:6xk<RTDCS{qjѣz=Ẻ<:qB sCVqnZ8{rc(03~n |ڥ&;$7g[(eS_bs*Fq kyS6ncXMF Lf8gCR(}&8'5%d2qǁ=g5z".te}i4Be!Fݵl`KP)G21َT(٤:u 921U^"HE42rz22z>aOwA ê#+s뒓+;Q\t v7ؿA~~~d7,R@ -wNWsVm()GTG^U˸qx8q|~ YUCj44~&l>UOUs߻T XӦY8OļxՑ`˽r뒛K_`җ)(XNkN^F~Yӕm?`coki{9w` l@d&^%Q^oRsŊ)-}קnes&Xiş-0sb)6o}6Xr-k5wQ^-㴙vsW?CKKH\ༀ? eɖ?ĔHN7~ zv}8)4eSm巉"Qx5Jr־gZ Οσ ~Qm<@ idsOv.{\yq^1NKan飿O/0%v*[G@gj>_*<<(-w.oT6쑷`BG.s+:8pHH坯R;n$# Bӓea"~;+qrw48䨣Snu܎,t˽PhJFb$ƪƓ. MYHjQY}<~;ffAp'\W4|oyf>/$@/~ab{6>m#!ɌlrsI׏%NGbD"$I"F@nL&KeG9n`OqNʇHѥ08Kf1)f2Z345eظ>wHɺ{}%%,[@zWz/z fCƊh(lnߣƙ̍YITN &JQY8v#,celkurYqs>L5^INaqbJ2ײviAW0l]7r#>fA%fSHHFQUߦǧ?BdK:˓!RtYy.Y180Yq5G:WxaK̍3Ae঴[xo )LzNT=KNeyZC]qFxql.+(|"CQP5%f*SbRy+N>%qwYY/fUJ:C#linŷ}YyM Et8a9cLsܒ,~GkuT=hk:s/ ~a鸓 :W~tlJzwQ1~D͇<=Yߧ8:Mc8U5j[TyUWEejzt5e2P"_{5>\yzs0PN"/zn@ߍz7GshXw  [?;E,񊾿EO :~ud:wz2 #o&Ho x,L\.;/+w }s<7Gu};%AvV%g>ݺ;S;w.q>|^\|}w2\1̓.Oѥ򛸭$yˀz!TW]nXPFE/do,?kYRpl>pO?iŝ#͹w9x^Cĺd|>>ȑu7Gw]g b$m~&q|@}'D*a>j+Ĭ2ɘ-AQk?Y@>_b8I)+Yv #9w8(jz1:{G'u&/2/KpՉjCU)u< 4ZqB*tianKN-ecFڴm'/*;r#?,:H$%[Ŕ);iK#W3E|kIDJ1adu$(g^t=J8VQ A66|^~[O>2{qV.5d2#z:-3m*kdy5,q.P#7~DlERzF)x8Q-%\\gK m)׆7׶=};j'WsDN=@_qiem.{_M{_cjOz"lDF{\p| 9 M `,_6'X]`k*+#:h.Me<8`Y•jY:]ɸ$g38ga*'l'hs>69Re0 QH fD೎e\1W5E-4Zxπ#֙dLG#ExESdcfo/j@-9Kan7޻s]W͚5w7`o DS`ަ=%+F"#)SyoHNLaAh09~2[k81N6xҎYnqDd;QpYNt.M3]>kNAYuJOD-d.8uy_Ǎf {4*DnAU5ua@g}]ҥ/t,uQ(8kғ"+\@h|Gs4ͱ36ֵAz4wgF_++RYK_tg0㌴'"p ͱc \jJOp$G$xZNWWq>'B]qdaA&^Kv Bʀ:T. ,#)R[P xEK¸m|WXd;OcbN.;xe۬]{u(D^#lz-,|' hGB%qAwO C+^{0GG†^aqDad B"}^4GJOD-)fm8Uv+=A6?j]Z֒/l%ٚM(|ל,YK4`[M2+=A6?j]-l;[K [OZUUBUU K4U^@kp(XV8މ]HFNLO 0N"!Tv'7*/uEk00()mC]:"H$zQټ=ܸTU7)fIs &j.k>/bgb,8@qo=_TGrjJ@{C59E??ԾOfޥp;h#~]8Be"䩧qKvR}}A@hT6Ek8>@3CmG}J;KɊF*e59lj 9m{x*>cF̀Q$Ǒ+*2dun.fh N*kq8"ƒYSeM aSSYLmwѭVUg2:Y՞ 4HX=i 9?k״BC!aƶIJQ21=A6ii♗n&E?})SQ h|Wx«{ܺݟ=RU}s+VNi#۳[rAEω)tSPt(-}s<9EGK:Con>빴~7sI4@(9XW{6A6Ìa?3'qS:B#1}?)Rt)>`Oh3>'=A6k}׆4C?l)s> w9=mYGnd=i2 Ş tZuGGlfE3+tpwL}nNp@yyKE}VC?!{ G {s)t@ads,N^QL7PA~6lٽ^y'G=22??3peZwr'?j_7 '548c̭d37:u~_0\zo&Wo_d便Tr_j˜6pgݘ}5dliFB<"3cu(qkDz((4bM&8tO_kkZPgad,v"A_{RƘ=Wp˽bziY #sxǦEscBPgP 漯D&+5⫝̸Q{\gM+ud9-<">3s97na #ScaGML2[MF'tt'#^yJ*aܞJc130ݴv@s=Vbz39֙z\$,p.n>SM ]swy>^].(4LgG;NvvKccvR%?f`c&~6\!,AN2NO;SY9N{q?y|0dUߢխG|1Rۤ|ص\"&^v,?+bmWVGcr&;&s],j;Ǹ~̖1[um1Q$$& OYjfO-g1Cyb@BvSS|<^^b9.ZuR=lt9itTC S624o%Zװ+/cb+L'3MF}vFQQe)GT_U;]\I8^:n1FۋI3}$&}qq.?u9)ԒWf<Ιcb1)Ll?*](]d3Պ*j5T)*UԒ&Q*qʺE^ic6##34"tO,J Ws긹ffyb02OrB5lHRwi]iu`I@!LֈVZt-DVی$,nuކqM*V&RaR$&N>/_;a7Lk{INU(21eƐG&G,GCSSlMJXk, bDۣGuhQh\ NIM6 Y+8$fڌEeKEM8kq8RSǁ4hV5ӦlMنE`WرI6Բ*4. \:(кQcp08 ]zb1:cuƢ5Ί,A6_*+GXb=MM; uFpj|C? _ n%80@0<21Z{2 P'!(C'A1{B21Z{221Z{"7qa h4/:IENDB`xgridfit/docs/structure.html0000644000175000017500000001645711311436615015612 0ustar peterpeter xgridfit

Structure of an Xgridfit Program

An Xgridfit program supplies the control-value table, pre-program, functions and glyph programs for the font. It also controls several parameters relating to TrueType instructions, stored in the font's maxp table. The contents of the file must be well-formed XML, validated against the Xgridfit RELAX NG schema (xgridfit.rnc or xgridfit.rng). Perhaps the easiest way to validate your program is to include the -V option on the Linux command line when you invoke Xgridfit:

    $ xgridfit -V myprog.xgf
  

Another worthwhile tool is nxml-mode, an Emacs mode that validates while you edit your program. To use nxml-mode, copy xgridfit.rnc to the nxml-mode schema directory and add this line to schemas.xml in the same directory:

    <documentElement localName="xgridfit" uri="xgridfit.rnc"/>
  

The first line in any Xgridfit program file must be the XML declaration:

    <?xml version="1.0" encoding="UTF-8"?>
  

Then comes the <xgridfit> element, the root element that contains all other information in the file. The <xgridfit> element must contain the Xgridfit namespace declaration:

    <xgridfit xmlns="http://xgridfit.sourceforge.net/Xgridfit2">
  

The child elements of <xgridfit> can come in any order, though it makes sense to group related elements (e.g. functions, control values) together.

Following are the possible children of the <xgridfit> element.

<glyph-select>

Specifies a list of glyphs to compile, ignoring all others. The glyph names in the list may be delimited by "+" or space--but only one or the other. It is all right to keep this element in the file when you don't need it: just empty it out. These are valid:

    <glyph-select>a macron amacron</glyph-select>
    <glyph-select></glyph-select>
  

<infile>

Specifies the name of the FontForge file or TrueType font to be opened by the script generated by Xgridfit.

<outfile>

Specifies the name of the file or font to be saved by the script generated by Xgridfit.

<datafile>

When running in merge-mode, Xgridfit needs to save information about the font. It can do so in the font.persistent object of an .sfd file it is saving or in a separate file. Use this element to specify the name of a separate file.

<constant>

Unlike the <constant> elements defined in a <glyph> program, <constant>s here are visible in all <glyph> programs, in <function>, <macro>, and <pre-program> elements.

<variable>

Like the global <constant>, the <variable> defined here is visible everywhere. It may be initialized by the <pre-program> so as to provide state information to all glyph programs, or it may be used anywhere for temporary storage.

<round-state>

These elements, permitted only here, define custom round states, which can be invoked anywhere.

<default>

These elements define graphics defaults and other defaults and settings.

<control-value>

A <control-value> element defines a control value, a specialized variable used by various instructions to regulate distance on the grid. A typical TrueType font has many <control-value> elements.

<alias>

An alternate name for a control-value, constant or variable.

<function>

A <function> element contains the definition of a function--a chunk of code that can be invoked from anywhere and, like the functions (methods, procedures) of other programming languages, can accept parameters and return values.

<macro>

A <macro> element contains the definition of a macro--a chunk of code that is compiled whenever the compiler encounters a <call-macro> element.

<pre-program>

The <pre-program> contains programming that is run whenever the font is about to be rasterized at a new size. Typical tasks for the <pre-program> are to round and adjust control values and set default values in the graphics state. The <pre-program> element is required, though it may be empty.

<glyph>

The file may contain any number of <glyph> elements. Each contains the programming for a single glyph.

xgridfit/docs/o-top-500-y.gif0000644000175000017500000001327510643720040015147 0ustar peterpeterGIF89a^s  p #$ ####%%#3''%5))))'8--....0022.C/D4499@@DDMMMMHhRRTTYY__aabbcc_hhiijjjjllnnppqqrrjttwwxxyyr}}~~~~ƀłăĄą~~‰ƀɺй곩!Created with The GIMP! ,^rrŖʑ͓ӝؠڦܩQDp߼)쇰[‚ ރpaÅ FtѢƊ %~dH$uh#J ;|)sH\z7&hQ݈>BN&MmЩӧTBUtҬrٛ4ϖ]lLj߲8nD-S[w¾r "oLrdU93fƍ=2Ҩej֟ۙ:f˶۽wzwg׷Nȓ+ׅ n߭kCұOڛ.uc6ѷ{䚃 X^x)&~ a&K NZWT!V! VT`MUbP#Xu%"U^d+/惠|mH]HaG!rxWDFIV2IXviؓN6|{ew&}llR'wq7gtuykIzi]f%袌6h.gYiv)iZr {XbseY%zY!rkɬJklZ,`BFBЈ2H=޸#A:cZmٞnnVj&9`ۈb{kUl[l‚1HN`J +^pm*+x4!H!D&ɮlꪛiɔ` TT"|Lsܘ`Gp@xNjmv4G+o4 l3`܌a7@U b[#-`sCmiTAq3w"L3؇_*(荧DŽG #AKxȝ? k_玻j\|.|?G){ܱ=.OOHGߺ>cg>J~ 3 ,|  ވ;3<ÉЄ#2ӔsD!O(*..w&nwgCL}npja gDB~ @JPMBcY!Ln@Lh:sQR1hWH%4i>۬(5TREԁn޿H/q_.9ѧx*+=]&KMF@aȞ ~G$$ZF}dVE{<=ל>5ļ`[U6skP EhLG)xVڔ(c+k*Ccf( hiQټ9q%ia/͖V},laXDֺж|fq+ۍ^qX׫%V 7Wm.q ]w ݻѾt+ʢִkiYVUc)Nmb9 疥pњ(ۂ#K#NmcyaoP1wՊX7S^:\xz\End#'9y[fm?.7Y%T/r[*K9p.p,_+Oٺ g<ȺcCǍn1ga>1Z {Ӡ&G=inڙF KZǭ4)bY'{fr,dP|gQβ, y|nNzՌ/󮶣m6+d6,BT~uڽ _G`5o=JҶη^}|qOcU8iKôsU8/⌧ҲM:r}w{ sA\N%7Ru6}p=`:'iE:s;?ˏ_嫻/s__|Q>~-xûGjM_ѧ?Z3?5Xv }y7z9G} \ (}6g/G&|]^Hx({|^g| 8v6nǂΗSr)zaghuڷǃxݷx>(y}E~N:~yTh~؅Y8w:6o*f8u dž9|iGv%8mzXtvt"H{e쵇{&|x/W-؈!1|5wWH艝HC8}gy[؄P(RXxXȄax؋hxnofHjh'g7nXxHZ]fb{ׇ{y荇(uHq8zXrHw8%NjWȅX(I ipI~yY? ! )')d8s|1Ɉ($ShH(Hm@)$HV{䈇FC6 q9Pf-YugV9k8&9%Y=HZ9)I(iaYv  p_(緖jY&*ii#G؎4ٕȕ`H~xB9fh?ٓa9G鎐٘Xyzٖl) 闻hh9rYrFx˩w]ؗYxΤ`Ř99Y꩕')ș?ǔ{Gɟɇhɛ9_; 镱iቜ)nz** )I"*ɊZvy$&Z05::)3ڣg"JYYj.YW9 V{D{ZHLzO*YIy:ʞR7J)Z'JC*2i{{z-};̙i|YgZnnʠ ڦ9dTI*cj"㈁m\ ߘzQk7zfZiکjw꧘>ڬ)B* /yjj:֪:: 3JjP:lJpS I陧/*:)zjŠ*E:؛{#o4 q⻬&\*ÕK@ÜRzyâHK_tKvPRx 0(-ς$ӭ/m ̙ܺ- ԪkE\e\|olh|qL=K _M{ 7(@Oy01H`1C~1J R@ p=01k`@mq N(2,3/S33S3`& 3j`>2p+20c i7#`~׃pæBC4*2W4KP惓d@P4A C :/> ,Gr5/_]3 p@ C忣臠5V0r9pCm}O<.5 5^鄬뙠 ԣ\ε=H7\7c8@8Mb"Js,>;%P/154T-2.;8S9:5 A9h9X0Oo6 N9g`9 @\p:s:G0H C;; [/pͳ! 1@P`l}ٕ;BD.lm'Q6s ͻVh fo[.lZKo佽;2^ljmqe ܛ;xgridfit/docs/tutorial2.html0000644000175000017500000002537110744214620015471 0ustar peterpeter Xgridfit

Tutorial 2: Gentium's o

The o in Gentium Italic presents us with a slightly more complex task than the period. The glyph shape itself is more complicated, and the distances we need to regulate are less standardized. Here is the glyph as it appears in FontForge: we have added names for the points that will have to be explicitly positioned and distances (in font units) for the stems that will have to be regulated.

Gentium period

Notice that the distances at the top and bottom of the glyph do not quite match; the same is true of the left and right. In fact, all of the lower-case letters with curves somewhat like that of o (a, c, d, e, g, etc.) have curves of slightly different widths. In a font of the quality of Gentium, it would be a mistake to assume that this variation is inadvertent; rather, Victor Gaultney was presumably aiming for optical rather than mathematical consistency in his glyph outlines. What is true of the stems is also true of the sidebearings: the left sidebearings of the lower-case letters with rounded left sides are slightly different.

These minor differences can cause problems at low resolutions, where a difference of a single pixel can make a character look lopsided, or too bold, or too thin. At the same time, we want to preserve the differences at higher resolutions, as on good laser printers or imagesetters. This is not really a problem for us, since the control-value cut in is intended to handle precisely this kind of situation. We need only to choose a standard width for these curved stems; if we make sure that the cut-in is always used, our standard width will be used at low resolutions and the designer's widths at high resolutions. We can experiment with the standard width and with various settings for the cut-in at any time.

The x-height and the distance of the bottom point of a rounded lower-case glyph from the baseline are consistent in this font. We will add the following control values to the ones we defined for the period:

    <control-value name="x-height" value="936"/>
    <control-value name="lc-round-char-bottom" value="-41"/>
    <control-value name="lc-vert-round-stem" value="143"/>
    <control-value name="lc-horz-round-stem" value="115"/>
    <control-value name="lc-round-char-left-side" value="55"/>
  

And we will get ready to write the glyph program by creating the <glyph> element and defining constants for the key point numbers:

    <glyph ps-name="o">
      <constant name="last" value="47"/>
      <constant name="topa" value="43"/>
      <constant name="topb" value="3"/>
      <constant name="bottoma" value="30"/>
      <constant name="bottomb" value="13"/>
      <constant name="lefta" value="35"/>
      <constant name="leftb" value="8"/>
      <constant name="righta" value="0"/>
      <constant name="rightb" value="20"/>
    </glyph>
  

For the o, we will nest <move> elements, building XML structures to correspond to the visible features of the glyph: the four rounded stems at the left, right, top and bottom. Remember that when we nest a <move> inside a <move> element, the point moved by the parent <move> is implicitly the reference point for the child <move>. Here are the horizontal and vertical moves:

    <with-vectors axis="x">
      <move distance="lc-round-char-left-side">
        <reference>
          <point num="left-sidebearing"/>
        </reference>
        <point num="lefta"/>
        <move distance="lc-vert-round-stem">
          <point num="leftb"/>
        </move>
      </move>
      <move>
        <reference>
          <point num="lefta"/>
        </reference>
        <point num="rightb"/>
        <move distance="lc-vert-round-stem">
          <point num="righta"/>
        </move>
      </move>
    </with-vectors>
    <with-vectors axis="y">
      <move distance="lc-round-char-bottom">
        <point num="bottoma"/>
        <move distance="lc-horz-round-stem">
          <point num="bottomb"/>
        </move>
      </move>
      <move distance="x-height">
        <point num="topa"/>
        <move distance="lc-horz-round-stem">
          <point num="topb"/>
        </move>
      </move>
    </with-vectors>
    <interpolate-untouched-points/>
  

First we position point lefta relative to the left-sidebearing point (defined in the last tutorial as a global <constant> dependent on point last). Then we position point leftb distance lc-vert-round-stem from lefta. We do the same with the right side of the glyph, but this time we start by positioning point rightb relative to point lefta, and then we work from the right side of the stem to the left. By omitting a distance attribute from the outer <move>, we accept, but round, the design width of the glyph. Later, if we find that one or more other glyphs in the font are the same width as the o, we can add a <control-value> for that measurement and a distance attribute here.

For the y axis, the operations are similar to what we did on the x axis. Here, however, we omit the reference points and position points <bottoma> and <topa> at absolute positions on the grid. If we go on writing instructions for this font, we will use the control values x-height and lc-round-char-bottom so frequently that it will make sense to round them in the <pre-program>, saving the TrueType engine the trouble of rounding them over and over while executing glyph programs. So we add these lines to the <pre-program>:

    <round value="x-height"/>
    <round value="lc-round-char-bottom"/>
  

And we add attributes round="no" and cut-in="no" to the two outer <move> elements. (We don't need the cut-in with such standard measurements; and for technical reasons it makes sense to turn off rounding and the cut-in at the same time.) Now the glyph program for o looks like this:

    <glyph ps-name="o">
      <constant name="last" value="47"/>
      <constant name="topa" value="43"/>
      <constant name="topb" value="3"/>
      <constant name="bottoma" value="30"/>
      <constant name="bottomb" value="13"/>
      <constant name="lefta" value="35"/>
      <constant name="leftb" value="8"/>
      <constant name="righta" value="0"/>
      <constant name="rightb" value="20"/>
      <with-vectors axis="x">
        <move distance="lc-round-char-left-side">
          <reference>
            <point num="left-sidebearing"/>
          </reference>
          <point num="lefta"/>
          <move distance="lc-vert-round-stem">
            <point num="leftb"/>
          </move>
        </move>
        <move>
          <reference>
            <point num="lefta"/>
          </reference>
          <point num="rightb"/>
          <move distance="lc-vert-round-stem">
            <point num="righta"/>
          </move>
        </move>
      </with-vectors>
      <with-vectors axis="y">
        <move distance="lc-round-char-bottom" round="no" cut-in="no">
          <point num="bottoma"/>
          <move distance="lc-horz-round-stem">
            <point num="bottomb"/>
          </move>
        </move>
        <move distance="x-height" round="no" cut-in="no">
          <point num="topa"/>
          <move distance="lc-horz-round-stem">
            <point num="topb"/>
          </move>
        </move>
      </with-vectors>
      <interpolate-untouched-points/>
    </glyph>
  

And now the <pre-program>, which we began to construct in the last tutorial, looks like this:

    <pre-program>
      <round value="period-height"/>
      <round value="x-height"/>
      <round value="lc-round-char-bottom"/>
      <control-value-delta>
        <delta-set size="11" distance="-8" cv="period-height"/>
      </control-value-delta>
    </pre-program>
  

At 20 pixels per em, the grid-fitted glyph now looks like this:

Gentium period

And here is how it looks at various resolutions from 30 ppem to 200 ppem. The pattern of pixels corresponds more closely to the original outline as the resolution goes up:

Gentium period
xgridfit/docs/o.gif0000644000175000017500000000762610643720040013602 0ustar peterpeterGIF89aXTppp! ,XTx0I8ͻ`(dihlp,tmx|pH,Ȥrl:Шt0"a`,u/9͡8R|k.|5xxn ~pY[>_ 3ao6\Z6u4  i>8j=a`- Ɯ -&%wӐ&:HAlE Ȑ dTXQE \@㩏Bd+ XFS±< \:0j6ya@SЖ@M|ZeQJBQ6rEvذT>zjYgp\ԓqz0,ԯ}^6Y`J:6Y2f#*3CpҦ<^W ;>9iLļ-.qJN@X& aS[rG{}wvv!ؿ=q<FGL/ BP>(bdBI"Pb]/8E'cb .V4!B~x#]3@L8#B < ;$M:2LmWz*pKl> If]QJSA\TʩD8vgֽ gS[:ySZ|(~ J(ZxU:C,}铦ڔ袯Ic ېh:*Oj|z] HƊ YhiʵPLA:v{1H&n}1 Hn,BInot$()l׮jߺACmdBSp.L$k q`>M90[IΔͰ ߍBoC#lwE+3=|M;1Q`N'}3)cp=`S[Vtt_Xr пҜd]ҜI0ߥ5duwնj8=YhU*$c<)k=ˠfh<)bN?(*(?ohG?h/ߖЍ;`q-(" JB`I(8|f%L9b`Jೇ13 HaqTìoeBCx@ ư}A|"Hqcy*Fax̣G w8HB~Ɏq)6$ B.bD#I)H$ cU~B/ҤaSMvt/ґ%*iK $&KAӐ~|bcBk⬔EpU+iD,:Iwvg9YOl29ftA@IP0o @KOON-h%P1Ш"9Zs%+Q^=hc I<_Ғ1EB|nͩjզ/{TjHT>QQeS~դժZM@oZV!Tk#kZK$S9`F*MkB [ا BlYVfYHY9p}hXڕjJJ,B}6lR[vnp3hsouzq]΅enu] n%xV mwK*AK.O;v 8@m) `$O4`#D/pD`xK…' "R/!"V Q vO G*2p^ "K رz@ɸ5rehXb2})xgo2/?5a2y%p6WN2l98ϭ[LbFh {@;@ǐt1VMǏF20gM Ә@qjQۀH65 @櫨[zt4sj3wva-6ۀY@!]2~^tOh0/˶MhmD̝^X7.Bt3пc-[;C7u n%o/g m6|ŵMq1÷e;KvxMΐ'$7!c|l DU~8:7s !S:}*7Gh~C'1As/REغȮebw'۳v }hw0v; n?p<gWv{"ީD;v7:m֢<6;y^>u;Rh5yڣ>|^}hH(О>|=?L[qNeX?35g\р??{8X6H}8;D2NG(B洄L'~E 4{OMM)!LNx~44QQH>V`̑ @,)RdP`zAB"?Nh^xL#MTFfRgFD퓈%qr(ONA8~c}yh'Ȋna`{Vtȉ_hpE:Z@>yS}uI Ȍ%`芈R/Ec}&`ȍ;~r`8'OX'TxR8xxmyY[|W9 .( gZ\s ZX !JXe'i\))y5;0 XAaRR+aVk`F^ ၓuF~Җ75[XgM1= _.Z•4*quS$St=0ΑO&h/aqNafVvЗ풖 72_2>/k1lAf:I3Qqks3`3&(U&d,59.i&!ii'i)OW%霯isiw`ezĝsgb]rYnew h) WrF%>GiT)9g%9eFУ=h` &f`hw.5WBY_zz(rî #8D "7z˰ (V{l"oJ֪%zڱ$0I@zD*2@&:R jA<5L+E R>k$=C;W[)\Ksdzj9~e;jl۶npr;t[v{xz|۷~;[ ;xgridfit/docs/oeg.print.css0000644000175000017500000000474610643720040015274 0ustar peterpeterbody {font-family: Junicode, gentium, caslon roman, serif; font-size: 12pt; line-height: 16pt; margin-left: 10%; margin-right: 10%} h1 {font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: normal; font-size: 18pt} h2 {font-size: 16pt} h3 {font-size: 14pt; font-weight: normal; font-style: italic;} h4 {font-size: 12pt; font-weight: normal; font-style: italic;} p {line-height: 16pt;} p.first {text-indent: 0pt} p.continued {text-indent: 0pt} pre {font-family: "courier new", "freemono", "bitstream vera sans mono"; font-size: 10pt; line-height: 12pt;} tt {font-family: "courier new", "freemono", "bitstream vera sans mono"; font-size: 10pt;} ul.detnote {font-size: 10pt;} dt {font-weight: bold} table {font-family: Junicode, gentium, caslon roman, serif;} table.std {padding: 2pt; border-style: solid; border-width: thin; border-color: black} table.notabene {padding: 5px; border-style: solid; border-width: medium; width: 95%} td {padding-left: 10px; padding-right: 10px; border-style: solid; border-width: thin; border-color: black; font-size: 12pt} td.alert {width: 10px; background-color: #D3D3D3; border-style: none} td.nb {border-style: none} td.plain {vertical-align: top; background-color: transparent; border-style: none;} div.bigindent {text-indent: 7em; display: block} div#jumplist {display: none} A:active {text-decoration: none; color: black} A:link {text-decoration: none; color: black} A:visited {text-decoration: none; color: black} span.note {display: block; border: solid thin black; padding-left: 1em; padding-right: 1em; font-size: 10pt; text-indent: 0;} div#copyright {border-top: solid thin black; margin-top: 10pt;} img {border-style: none;} xgridfit/bin/0000755000175000017500000000000011572451620012471 5ustar peterpeterxgridfit/bin/xgridfit0000755000175000017500000000020111353663600014230 0ustar peterpeter#!@python_prog@ from sys import exit from xgflib import run_xgridfit if not run_xgridfit(xgfdir="@xgridfit_dir@"): exit(1) xgridfit/bin/xgfconfig0000755000175000017500000000017511353663600014374 0ustar peterpeter#!@python_prog@ from xgflib import run_config from sys import exit if not run_config(xgfdir="@xgridfit_dir@"): exit(1) xgridfit/bin/xgfupdate0000755000175000017500000000326211313005340014374 0ustar peterpeter#!/bin/bash XSLT_DIR=@xgridfit_dir@/utils/ #XSLT_DIR=/usr/local/share/xml/xgridfit/utils/ ACTION='2' usage() { cat < myfont-new.xgf Here-is-the-usage-text } parseopts() { while getopts "hv:" optname do case "$optname" in "h") usage exit 0 ;; "v") ACTION=$OPTARG ;; "?") usage 1>&2 exit 1 ;; ":") usage 1>&2 exit 1 ;; *) echo "mysterious error" usage 1>&2 exit 1 ;; esac done return $OPTIND } runscript() { FNAME=$1 if [ -z "$FNAME" ] then usage 1>&2 exit 1 fi if [ ! -f "$FNAME" ] then echo "File $FNAME does not exist" 1>&2 exit 1 fi case $ACTION in '1') CMD="xsltproc ${XSLT_DIR}xgf-update.xsl $FNAME" CMD=$CMD" | xmllint --format - | sed -f ${XSLT_DIR}add-blanks.sed" eval $CMD ;; '2') CMD="xsltproc ${XSLT_DIR}xgf-add-namespace.xsl" if grep -q " element. I will add one." 1>&2 CMD="xsltproc ${XSLT_DIR}add-xgridfit-element.xsl $FNAME | "$CMD" -" fi CMD=$CMD" | xmllint --format - | sed -f ${XSLT_DIR}add-blanks.sed" eval $CMD ;; esac } parseopts "$@" argstart=$? runscript "${@:$argstart}" xgridfit/bin/ttx2xgf0000755000175000017500000000017711353663600014032 0ustar peterpeter#!@python_prog@ from xgflib import run_ttx2xgf from sys import exit if not run_ttx2xgf(xgfdir="@xgridfit_dir@"): exit(1) xgridfit/bin/getinstrs0000755000175000017500000001032211312522323014426 0ustar peterpeter#!@python_prog@ """Extracts instructions from a font and prints them on stdout.""" """ Copyright (c) 2009 by Peter .S Baker Issued under the GNU Public License, v. 2. This file is part of the Xgridfit package. """ import sys try: import fontforge except ImportError: print "You must install the FontForge Python extension before running" print "this program." sys.exit(1) from optparse import OptionParser def get_token_type(tok): """Returns 'int' if tok is an integer, 'instruction' if it is not.""" try: dummy = int(tok) return "int" except ValueError: return "instruction" def make_instruction(tok): """Transforms a raw instruction into an Xgridfit .""" istr = INST_SPACE + "" sys.stdout.write(GLYPH_SPACE) sys.stdout.write("\n") inst_list = instrs.split("\n") token_type = "instruction" eat_first_number = False for token in inst_list: token_str = token.strip() # allow blank lines in input if len(token_str) == 0: continue this_type = get_token_type(token_str) if this_type == "int": if this_type != token_type: if eat_first_number: num_string = push_cmd else: num_string = push_cmd + token_str else: if num_string == push_cmd: num_string += token_str else: num_string += " " + token_str eat_first_number = False else: if this_type != token_type: num_string += "
" print num_string if "PUSH" in token_str: if "NPUSH" in token_str: eat_first_number = True else: print make_instruction(token_str) token_type = this_type sys.stdout.write(GLYPH_SPACE) sys.stdout.write("
\n") USAGE_MSG = "usage: %prog [options] fontname glyphname ..." PARSER = OptionParser(usage = USAGE_MSG) PARSER.add_option("-r", "--raw", action="store_true", dest="plain_output", default=False, help="Output raw instructions") PARSER.add_option("-x", "--xgridfit", action="store_true", dest="xgf_element", default=False, help="Output XML declaration and Xgridfit element") (OPTIONS, ARGS) = PARSER.parse_args() if len(ARGS) < 2: print print "Error: not enough arguments" print PARSER.print_help() sys.exit(1) FONT_NAME = ARGS[0] GLYPH_LIST = ARGS[1:] PLAIN_OUTPUT = OPTIONS.plain_output XGF_ELEMENT = OPTIONS.xgf_element GLYPH_SPACE = "" INST_SPACE = " " try: FONT = fontforge.open(FONT_NAME) except EnvironmentError as detail: print "Error opening file", FONT_NAME print detail sys.exit(1) if XGF_ELEMENT: print "" print "" GLYPH_SPACE = " " INST_SPACE = " " for glyphname in GLYPH_LIST: try: INSTR_BINARY = FONT[glyphname].ttinstrs if len(INSTR_BINARY) == 0: print "glyph", glyphname, "has no instructions" else: INSTR_STRING = fontforge.unParseTTInstrs(INSTR_BINARY) if PLAIN_OUTPUT: print "# glyph", glyphname print INSTR_STRING print else: make_glyph_program(glyphname, INSTR_STRING) except TypeError as detail: sys.stderr.write("Error retrieving instructions from glyph \"") sys.stderr.write(glyphname) sys.stderr.write("\"\n") print detail if XGF_ELEMENT: print "" xgridfit/bin/xgfmerge0000755000175000017500000001044711313005340014214 0ustar peterpeter#!/bin/bash UTIL_PREFIX=@xgridfit_dir@/utils/ PARAMLIST='' RESOLVE_XINCLUDES=1 FILE_A='' SORT_OUTPUT=1 VERBOSE=1 ECHO_TIME=1 usage() { cat < element -o file Write result to file (otherwise to stdout) -p Prefer from file other than file-a -s Sort glyph elements in output -v Verbose messages -x Resolve XIncludes (except from file-a) Here-is-the-usage-text } parseopts () { while getopts "cEhno:psvx" optname do case "$optname" in "c") PARAMLIST=$PARAMLIST" --stringparam use-compile-globals yes" ;; "E") ECHO_TIME=0 ;; "h") usage exit 0 ;; "n") PARAMLIST=$PARAMLIST" --stringparam skip-b-no-compile no" ;; "o") OUTFILE=$OPTARG ;; "p") PARAMLIST=$PARAMLIST" --stringparam prep-mode priority" ;; "s") SORT_OUTPUT=0 ;; "v") VERBOSE=0 ;; "x") RESOLVE_XINCLUDES=0 ;; "\?") usage 1>&2 exit 1 ;; ":") usage 1>&2 exit 1 ;; *) usage 1>&2 exit 1 ;; esac done return $OPTIND } runscript () { START_TIME=`date +"%s"` if [ $# -lt 2 ] then echo "You must supply the names of at least two files." 1>&2 echo "Type \"xgfmerge -h\" or \"man xgfmerge\" for help." 1>&2 exit 1 fi if [ $VERBOSE -eq 0 ] then echo "Settings: " 1>&2 if [ ${#OUTFILE} -gt 0 ] then echo "Output will be written to $OUTFILE" 1>&2 fi if [ $RESOLVE_XINCLUDES -eq 0 ] then echo "XIncludes will be resolved in all files except $1" 1>&2 fi if [ $SORT_OUTPUT -eq 0 ] then echo "Output will be sorted" 1>&2 fi fi for f in $@ do if [ ${#FILE_A} -eq 0 ] then FILE_A=$f if [ ! -f "$FILE_A" ] then echo "Can't find file $FILE_A" 1>&2 exit 1 fi CURRENT_A=$FILE_A else FILE_B=$f if ! echo $FILE_B | grep -q "^\/" then FILE_B=`pwd`'/'$FILE_B fi if [ ! -f "$FILE_B" ] then echo "Can't find file $FILE_B" 1>&2 exit 1 fi if [ $VERBOSE -eq 0 ] then echo "Merging $CURRENT_A and $FILE_B" 1>&2 fi DELTMP=1 if [ $RESOLVE_XINCLUDES -eq 0 ] then if grep -q "http://www\.w3\.org/2001/XInclude" $FILE_B then TMP_X_FILE=`$MKTEMP_CMD` || exit 1 xsltproc --stringparam file-a $FILE_A ${UTIL_PREFIX}xinclude.xsl $FILE_B | \ xmllint --xinclude - >> $TMP_X_FILE if [ $VERBOSE -eq 0 ] then echo "$FILE_B with XIncludes written to $TMP_X_FILE" 1>&2 fi FILE_B=$TMP_X_FILE DELTMP=0 fi fi TMP_RESULT=`$MKTEMP_CMD` || exit 1 if [ $VERBOSE -eq 0 ] then echo "Result will be written to $TMP_RESULT" 1>&2 fi CMD="xsltproc --stringparam file-b $FILE_B $PARAMLIST ${UTIL_PREFIX}merge.xsl $CURRENT_A >> $TMP_RESULT" if [ $VERBOSE -eq 0 ] then echo "executing $CMD" 1>&2 fi eval $CMD if [ $DELTMP -eq 0 ] then if [ $VERBOSE -eq 0 ] then echo "Removing $TMP_X_FILE" 1>&2 fi rm -f $TMP_X_FILE fi if [ $FILE_A != $CURRENT_A ] then if [ $VERBOSE -eq 0 ] then echo "Removing $CURRENT_A" 1>&2 fi rm -f $CURRENT_A fi CURRENT_A=$TMP_RESULT fi done OUTCMD="cat $TMP_RESULT" if [ $SORT_OUTPUT -eq 0 ] then OUTCMD=$OUTCMD" | xsltproc ${UTIL_PREFIX}sort-glyphs.xsl -" fi OUTCMD=$OUTCMD" | xmllint --format - | sed -f ${UTIL_PREFIX}add-blanks.sed" if [ ${#OUTFILE} -gt 0 ] then OUTCMD="$OUTCMD > $OUTFILE" fi if [ $VERBOSE -eq 0 ] then echo "executing $OUTCMD" 1>&2 fi eval $OUTCMD if [ $VERBOSE -eq 0 ] then echo "Removing $TMP_RESULT" 1>&2 fi rm -f $TMP_RESULT END_TIME=`date +"%s"` if [ $ECHO_TIME -eq 0 ] then echo "Finished in "$(( $END_TIME - $START_TIME ))" seconds" 1>&2 fi } if [ $# -lt 2 ] then usage 1>&2 exit 1 fi if uname | grep -q "Darwin" then MKTEMP_CMD='mktemp -t xgfmerge' else MKTEMP_CMD='mktemp -t xgfmerge.XXXXXXXXXX' fi parseopts "$@" argstart=$? runscript "${@:$argstart}"