Skip to content

Latest commit

 

History

History
145 lines (115 loc) · 5.66 KB

developer-documentation.md

File metadata and controls

145 lines (115 loc) · 5.66 KB

Developer documentation

Building

The prerequisites are:

  • GNU Make
  • Python 3.12 or later
  • FontForge 20190801 with Python 3 extensions
  • unifdef

To build the basic default set of fonts, run:

python3 -m venv venv
. venv/bin/activate
pip install --no-deps -r requirements.txt
make

That will produce four fonts:

  • fonts/RawndMusmusDuployan/unhinted/otf/RawndMusmusDuployan-Bold.otf
  • fonts/RawndMusmusDuployan/unhinted/otf/RawndMusmusDuployan-Regular.otf
  • fonts/RawndMusmusDuployan/unhinted/ttf/RawndMusmusDuployan-Bold.ttf
  • fonts/RawndMusmusDuployan/unhinted/ttf/RawndMusmusDuployan-Regular.ttf

See .github/workflows/main.yml for how to get the prerequisites on Ubuntu. The steps should be analogous on other platforms. Getting FontForge to build correctly is a challenge.

Testing

The additional prerequisite for testing is:

  • HarfBuzz 8.1.0 or later

To test the fonts, run:

python3 -m venv venv
. venv/bin/activate
pip install --no-deps -r dev-requirements.txt
make CHARSET=testing check

Alternatively, push a commit and wait for GitHub Actions to run CI.

Releasing and tagging

To release the font, run make release. This creates an annotated tag of the form NotoSansDuployan-v${version}.

Tags of the form almost-NotoSansDuployan-v${version} correspond to the commits most similar to the indicated Noto versions. They are created manually.

Advanced build options

Makefile has many available targets. The main ones are:

  • all: Build the fonts. This is the default target.
  • A specific font path ending with .otf or .ttf: Build one font. (This might build other fonts too; see below for a discussion of vertical metrics.)
  • clean: Remove the fonts and other build leftovers.
  • check: Run various tests.
  • hb-shape and hb-view: Build HarfBuzz’s command-line utilities.
  • requirements.txt and dev-requirements.txt: Update *requirements.txt based on *requirements.in.
  • release: Create a Git tag for the current commit, then a new commit updating to the next version number.
  • sync-noto: Prepare to sync the downstream Noto repository with changes in this repository. (Some manual work is still required.)

These targets are affected by various variables:

  • CHARSET: Which character set variant to build: standard for Rawnd Musmus Duployan, noto for Noto Sans Duployan, or testing for Ilo Snas Duployan.
  • WEIGHTS: A space-separated list of weights to build. The only valid weights are Regular and Bold. The default is both.
  • SUFFIXES: A space-separated list of OpenType variants to build. The only valid variants are otf and ttf. The default is both.
  • NOTO: If defined, build a Noto font.
  • UNJOINED: If defined, build an Unjoined font.
  • FONT_FAMILY_NAME: The name of the font.
  • VERSION: The base version number. It is automatically augmented with various affixes.
  • RELEASE: If defined, this is a release build. This only affects the version number.
  • TALL_TEXT: A string that helps determine the common vertical metrics across all the fonts.
  • COVERAGE: Whether to measure code coverage when building the fonts and whether to enforce a minimum coverage percentage when testing.
  • HB_VERSION: The version of HarfBuzz to build when building its command-line utilities.
  • NEXT_VERSION: The next version number. By default, the next version number increments the minor part of VERSION.

All the fonts for a given character set variant should share the same vertical metrics. When building the fonts, preliminary versions of all of the fonts with that character set variant are built, and the final fonts’ vertical metrics are set to the most extreme values of all of them. If TALL_TEXT is defined, the vertical metrics are also modified to make sure the bounding box of TALL_TEXT falls within every font’s vertical metrics. By default, it is defined with a string that is suitable for Chinook Jargon and reasonable for other modes.

How it works

Most of the build is done by a Python script, which has some documentation in docstrings and comments. At a high level, this is what is does:

  1. Using the specified character set, decide what code points will go in 'cmap'. Each code point gets a schema. A schema is a build-time abstraction of a glyph.
  2. Send the schemas through a sequence of phases. A phase is an abstraction of a sequence of OTL lookups (usually GSUB). A GSUB phase can add or remove schemas from the set of current schemas, corresponding to the set of glyphs that can exist at that point in OTL.
  3. Using FontForge, draw the schemas by expanding their strokes, and convert them to glyphs. Schemas that behave and look the same up to this point are merged and get the same glyph.
  4. Send the schemas through another sequence of phases. These phases have access to glyphs and can create lookups that depend on their exact bounding boxes and anchor points. (Bounding boxes in particular are necessary for the width system.) Schemas created in these phases are not subject to later merging.
  5. Add mark attachment GPOS rules.
  6. Compile the font with fontTools.