== Font parameters and smarts  ==

The minimum attributes a font object needs are `target` and `source`. For example, the following `wscript` file is about as simple as one can get:

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'Example-Regular.ttf')
----

This short file does more than might be expected. First of all it copies the input file `Example-Regular.ttf` to an output file `results/Example-Regular.ttf` (We will use Unix style `/` for path separators). This copy may seem redundant, but it is necessary for the rest of the system to work, and not all source fonts are unmodified `.ttf` files. If there are tests `.txt` files in a directory called `tests` then these can be run against this font.

Notice that an input and an output file may not have the same name. Even if the output file ends up in `results/` it still corresponds to a real input file that may or may not be in `results/`. So file paths must also be unique if the files are unique.

What if the source isn't a `.ttf` file? Then, we can simply change the above example to:

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'Example-Regular.ufo')
----

and the system will automatically convert the UFO source font to TrueType as it is copied into the `results` directory tree. Here we wouldn't actually need the `results/` prefix to the target because the filename isn't the same as the `source` attribute.

The complete list of core attributes to a font are:

target::
    Output file for the generated font within `results`.

source::
    Basic design file used to generate the initial form of the output font.

params::
    Command-line parameters passed to the program that converts the source font into the target font. This program changes depending on the source file format. For UFO it is psfufo2ttf.

version::
    This takes a version number in the form 'x'.'y' (a floating point number) and sets the output font to have that version. It may also be a tuple of the form (x.y, "text") where the text will be appended to the version string inside the font.
    If the tuple form is not used, then "text" is set to the package `buildversion`. If this is not wanted then use (x.y, "").

sfd_master::
    This attribute specifies a FontForge file that should be merged with the source FontForge file when creating the target. If the sfd_master file is the same as the source, then sfdmeld is not run.
_(You will have to install FontForge yourself as it is no longer part of the smith toolchain default dependencies)_


ap::
    Attachment point database associated with the source font.

ap_params::
    Parameters passed to the program that creates the ap database from the source font.

classes::
	An XML-structured file that allows glyph classes to be defined and then used by both Graphite and OpenType build processes.

no_test::
    If set to True will not include the font in the font tests. This can be set after the font object is created.

package::
    Package object to insert this font into. If not specified the global package is used.

typetuner::
    Specifies that typetuner should be run on the target and to use the given file as the typetuner configuration xml file.


=== OpenType ===

There are multiple ways of adding OpenType information to a font. One is to already have it in the source font. In this case, we need to indicate that we are working with an OpenType font, even if everything is internal to the font. The font builder needs to know for font testing purposes or if the font is generated from a legacy font.

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'source/Example-Regular.ufo',
     opentype = internal())
----

This will generate tests pertinent to OpenType testing. See the section on font tests.

One approach sometimes used for FontForge based projects is to keep all the lookups in one font and then to share these lookups across all the fonts in a project. For this we simply specify a `sfd_master` attribute and the font builder will use `sfdmeld` to integrate the lookups in the master into each font as it is built. _(You will have to install FontForge yourself as it is no longer part of the smith toolchain default dependencies)_


[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'Example-Regular.sfd',
     sfd_master = 'mymaster.sfd')
----

Obviously, if the `sfd_master` attribute is the same as the `source` file then no merge occurs. This is an alternative way of specifying that the font is OpenType.

Another approach to adding OpenType tables to a font is to use an external tool or text file to create the lookups and then to have smith compile them into the font. Two formats for source files are supported: Microsoft's VOLT (Visual OpenType Layout Tool) and Adobe's Feature File.

==== VOLT ====

This approach uses a command-line VOLT compiler to integrate the `.vtp` source into the font. In addition, the `.vtp` source is autogenerated from a source and any other elements that go to make the final integrated source. For example, we show a maximal `volt()` integration to show all the components and then discuss them.

Notice that while the initial parameter to such objects as `volt` is required, all named parameters are optional.

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'Example-Regular.ttf',
     opentype = volt('Example.vtp',
                     master = 'Example.vtp'),
     ap = 'Example.xml',
     classes = 'project_classes.xml')
----

We define the `.vtp` file to create for this font which will then be compiled into the font using `volt2ttf` as `Example.vtp`. We also declare a shared master volt project that is shared between all the fonts (well, at least this one!). In building a largely automated volt project, a program `make_volt` is used that can take attachment point information from an xml database `Example.xml`. This may be augmented with class information using `project_classes.xml`. These two file references are within the font rather than the volt details because they are shared with other smart font technologies particularly Graphite.

The complete list of attributes to Volt() are:

master::
    The volt source that is processed against the font to generate the font specific volt to be compiled into the font.

make_params::
    These parameters are passed to the make_volt process. The value is a string of parameters.

params::
    These parameters are passed to volt2ttf to modify the compiling of the volt source into OpenType tables.

no_make::
    If this attribute is present, make_volt isn't run and the first parameter is assumed to be the specific .vtp for this font.

no_typetuner::
    The VOLT2TTF program used to compile the volt into opentype, also has the capability to emit an XML control file for typetuner. By default, if the font requests typetuner be run, the volt2ttf options will be set to generate this file. Setting this attribute stops this generation from happening and you will need to create the file some other way.

==== FEA ====

The Adobe Font Development Kit for OpenType (AFDKO) has defined a textual syntax for OpenType tables, called a feature file. smith handles .fea files by merging font-specific classes (built from the AP and classes files) with a provided master fea file, and the resulting font-specific fea file is then compiled into the font.

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'Example-Regular.ttf',
     opentype = fea('Example.fea',
                    master = 'Example.fea'),
     ap = 'Example.xml',
     classes = 'project_classes.xml')
----

The complete list of attributes to fea() follow those of other classes:

master::
    The fea source that will be merged with autogenerated classes to create the font-specific .fea file.

make_params::
    Extra parameters to pass to `makefea`, the tool that is used to generate the font-specific .fea file.

no_make::
    If this attribute is present, then `makefea` isn't run and the first parameter references a file that already exists rather than one that will be created by fea().

to_ufo::
    If this attribute is present and not false and also if the source file for the font ends in `.ufo`, the generated fea will be copied into the source .ufo as the features.fea file.

depends::
    A python list of additional source files on which the OpenType depends. Typically these are files mentioned via `include()` in the master fea file.

buildusingfontforge::
    If this attribute is present and not false, the FEA file will be compiled using FontForge instead of fonttools. _(You will have to install FontForge yourself as it is no longer part of the smith toolchain default dependencies)_

keep_feats::
    This boolean, used only when buildusingfontforge is true, tells FontForge to keep all the lookups associated with a given feature that are already in the font, and not wipe them when merging the feature file. For example, keeping the kern feature lookups, which are often best handled in a font design application rather than in fea files.


=== FEAX ===

Feax is a set of extensions to provide easier and more powerful ways to write fea code. It is a fea preprocessor. For the specification of the feax language see https://github.com/silnrsi/feax/blob/main/docs/feaextensions.md[feaextensions.md]. 

`makefea` is the script to generate fea from a feax source file. 


=== Graphite ===

Adding Graphite tables to a font is much like adding VOLT information. The relevant files are declared either to the font or a `gdl()` object. For example:

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'Example-Regular.ttf',
     graphite = gdl('Example.gdl',
                     master = 'mymaster.gdl',
                     make_params = '-o "R C"'),
     ap = 'Example.xml',
     classes = 'project_classes.xml')
----

Notice that the `ap` and `classes` attributes have the same values and meaning as for OpenType tables. This is because the information is used in the creation of both sets of tables. The `Example.gdl` is created by the `make_gdl` process and it pulls in `mymaster.gdl` during compilation.

The complete list of attributes to a gdl() object are:

master::
    Non-font specific GDL that is #included into the font specific GDL.

make_params::
    Parameters passed to `make_gdl`.

params::
    Parameters to pass to `grcompiler` to control the compilation of Graphite source to Graphite tables in the font.

no_make::
    If this attribute is present, `make_gdl` is not run and the first parameter is assumed to be the gdl for the specific font.

depends::
    A python list of additional source files on which the GDL depends. Typically these are files mentioned via `#include` in the master GDL file.


=== Legacy Fonts ===

Fonts can also be built from another font, either legacy-encoded or generated from a source font or fonts. This can be achieved by giving a `legacy()` object as the `source` attribute for the font. For example, for a font generated from a legacy font using `ttfbuilder` we might do:

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = legacy('myfont_src.ttf',
                     source = 'my_legacyfont.ttf',
                     xml = 'legacy_encoding.xml',
                     params = '-f ../roman_font.ttf',
                     ap = 'my_legacyfont.xml'))
----

The legacy object creates the source font that is then copied to the output and perhaps smarts are added too.

The complete set of attributes to a `legacy()` object is:

source::
    The legacy source font (`.ttf`) to use to convert to the Unicode source font.

xml::
    ttfbuilder configuration xml file to use for the conversion

params::
    Command line arguments to ttfbuilder. Note that files specified here need `../` prepended to them.

ap::
    Attachment point database of the legacy font that will be converted to the font.ap attribute file.

noap::
    Instructs the legacy converter not to create the ap database specified in the font. This would
    get used when another process, after legacy conversion, modifies the font and then you want the
    build system to autogenerate the ap database from that modified font rather than from the
    legacy font conversion process.


=== WOFF ===

https://www.w3.org/TR/WOFF/[WOFF] and https://www.w3.org/TR/WOFF2/[WOFF2] files are TTF files in special compressed formats used for webfont delivery. Smith can generate both WOFF and WOFF2 files. For example:

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'Example-Regular.ttf',
     woff = woff('Example', metadata='metadata.xml')
----

The first parameter to `woff()` is the name of the woff file(s) to be generated. Filename extension, if present, is ignored.

The `woff` object takes these optional attributes:

params::
    This string is passed as additional command line options to the `psfwoffit` command.

metadata::
    Name of the xml file containing https://www.w3.org/TR/WOFF/#Metadata[woff extended metadata]

privdata::
    Name of the file containing https://www.w3.org/TR/WOFF/#Private[woff private data]

type::
    Indicates which type(s) of woff to generate; value can be `'woff'` or `'woff2'`. If not supplied or set to `('woff', 'woff2')` then both woff and woff2 are generated.

cmd::
    A command string that should be used instead of `psfwoffit` to build woff file(s). Within the command string:

* `${TGT}` identifies the woff file to be built.
* `${SRC[0]}` identifies the TTF file to be used for input.
* If the `metadata` attribute was provided, `${SRC[1]}` will identify it.
* If the `privdata` attribute was provided, the last item in the `${SRC}` list will identify it.


By default, the font version is extracted from the input ttf and used as the version for the woff font. To override with a specific version use the `params` attribute:

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'Example-Regular.ttf',
     woff = woff('Example', params='-v 3.2', metadata='metadata.xml')
----

To use a command other than `psfwoffit` to create woff files, the `cmd` attribute can provide the desired command and its options. For example, to use `ttf2woff` to create woff file:

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'Example-Regular.ttf',
     woff = woff('Example', type='woff', metadata='metadata.xml', 
                cmd='ttf2woff -m ${SRC[1]} -v 3.2 ${SRC[0]} ${TGT}')
----

=== Fret ===

Fret is a font reporting tool that generates a PDF report from a font file, giving information about all the glyphs in the font.

The `fret` object takes these attributes:

params::
    A parameter list to pass to fret. If not specified, then fret is run with the `-r` command line argument.

[source,python,linenums]
----
font(target = 'results/Example-Regular.ttf',
     source = 'Example-Regular.ttf',
     fret = fret('results/Example.pdf', params='-r -o i'))
----

=== DesignSpace ===

An alternative to the `font` object is the `designspace` object. A designspace specification normally defines a family of related fonts, and therefore the designspace object typically results in a number of fonts being generated -- in essence the designspace object creates multiple font objects. Most of the attributes of a font object also apply to a designspace object, the differences are described below.

Instead of a `source` attribute, the designspace object uses a
https://github.com/fonttools/fonttools/tree/main/Doc/source/designspaceLib#document-xml-structure[designspace] file. Each instance described in the designspace file is treated as a source, and the designspace object iterates over all these instances and builds output from each.

Thus the minimum needed for the designspace object is a designspace file and `target` attribute:

[source,python,linenums]
----
designspace('source/Example.designspace',
    target = '${DS:FILENAME_BASE}.ttf')
----

Except for `source` and `sfd_master`, all other attributes of the font object can be used with the designspace object. Additionally the following attribute can be used:

instanceparams::
    Command line arguments to `psfcreateinstances`. A common usage is to supply the `-W` option to force weight-fixing for RIBBI font families.

instances::
    Sometimes it is not desirable to build all the instances in a designspace file. This attribute if not None is a list of instance names to build. If None, all instances will be built. This allows for such patterns as follows which limits a build to just one font in a set for quicker building:

[source,python,linenums]
----
opts = preprocess_args({'opt': '--quick'})
designspace('source/Example.designspace', # ...
    instances = ['Example Regular'] if '--quick' in opts else None)
----

shortcircuit::
    If this is set to True then if a design space instance has the same configuration parameters as a master, smith will not
    generate an instance, but use the master file directly. If False then a new instance is always created. Defaults to True.

Note, however, that in contrast to the simplest font object, the `target` attribute cannot be as simple as `Example-Regular.ttf` but must be an expression that yields an appropriate filename for each instance. This will also be true for some other attributes as well, for example the attachment point information specified by the `ap` attribute will need to be different for each instance.

To facilitate this, the designspace object provides a number of variables whose value is based on the particular instance being processed. To prevent possible name conflicts, the designspace object uses a `DS:` prefix for each of the variables it provides.

For a given instance, each attribute and each location introduce one or more variables. Consider the following instance definition:

[source,xml,linenums]
----
<instance
    familyname="Example"
    stylename="Bold"
    name="Example Bold"
    filename="instances/Example-Bold.ufo"
    >
    <location>
        <dimension name="weight" xvalue="700" />
        <dimension name="width"  xvalue="100" />
        <dimension name="custom" xvalue="0" />
    </location>
    <info />
    <kerning />
</instance>

----

Based on the corresponding instance attributes, the following variables will be defined:

[options="header",width="80%",cols="2,4"]
|=========================================
| variable           | string value
| `${DS:FAMILYNAME}` | `Example`
| `${DS:STYLENAME}`  | `Bold`
| `${DS:NAME}`       | `Example Bold`
| `${DS:FILENAME}`   | `instances/Example-Bold.ufo`
|=========================================

Additionally, for each variable above, three additional variables are defined. Adding __&#95;DASH__ to the variable name results in a value where all spaces are replaced with a hyphen. Adding __&#95;NOSPC__ produces a value where all spaces are removed. Finally, adding __&#95;BASE__ provides a value which is the basename (without the extension) of the original value. For example:

[width="80%",cols="2,4"]
|=========================================
| `${DS:NAME_DASH}`     | `Example-Bold`
| `${DS:NAME_NOSPC}`    | `ExampleBold`
| `${DS:FILENAME_BASE}` | `Example-Bold`
|=========================================

Based on the location specified for the instance, the following variables are defined:

[width="80%",cols="2,4"]
|=========================================
| `${DS:AXIS_WEIGHT}` | `700`
| `${DS:AXIS_WIDTH}`  | `100`
| `${DS:AXIS_CUSTOM}` | `0`
|=========================================

One additional variable provides the path from the build directory to the instance UFO, which for our example would be:

[width="80%",cols="2,4"]
|=========================================
| `${DS:FILE}` | `source/instances/Example-Bold.ufo`
|=========================================
