Skip to main content

Font Merge Engine

English | 日本語

The core font merge engine behind OFL Font Baker. The code in this directory is MIT-licensed and can be freely used in other projects.

Merges a base font (typically CJK) with a sub font (typically Latin or kana) into a single font file, replacing glyphs and OpenType features via cmap-based mapping.

For details on features and background, see the OFL Font Baker repository.

OFL Fonts Only

This library only accepts fonts licensed under the SIL Open Font License (OFL). If an input font's name table (nameID 13) does not contain an OFL license string, loading fails with an error.

Merged output is automatically tagged with OFL-compliant copyright and license metadata.

Installation

pip install ofl-font-baker

Requires Python 3.9+. fonttools and brotli are installed automatically.

Usage

Provide a JSON config on stdin. The engine supports two modes:

cat config.json | python3 merge_fonts.py

Path Mode

Specify output file paths explicitly via export.path. Only the files whose paths are provided are written.

{
  "baseFont": {
    "path": "/path/to/base.otf",
    "scale": 1.0,
    "baselineOffset": 0,
    "axes": []
  },
  "subFont": {
    "path": "/path/to/sub.ttf",
    "scale": 1.0,
    "baselineOffset": 0,
    "axes": [],
    "excludeCodepoints": ["U+2460-U+24FF", "U+203B"]
  },
  "output": {
    "familyName": "My Font",
    "weight": 400,
    "italic": false,
    "width": 5
  },
  "export": {
    "path": {
      "font": "/out/MyFont-Regular.otf",
      "woff2": "/web/MyFont-Regular.woff2"
    }
  }
}

Package Mode

Specify export.package to create a complete output directory with font files and metadata.

{
  "baseFont": { "path": "/path/to/base.otf", "scale": 1.0, "baselineOffset": 0, "axes": [] },
  "subFont": { "path": "/path/to/sub.ttf", "scale": 1.0, "baselineOffset": 0, "axes": [], "excludeCodepoints": [] },
  "output": { "familyName": "My Font" },
  "export": {
    "package": {
      "dir": "/exports/MyFont-Regular"
    }
  }
}

Output (JSON manifest on stdout):

{
  "outputDir": "/exports/MyFont-Regular",
  "fontPath": "/exports/MyFont-Regular/MyFont-Regular.otf",
  "woff2Path": "/exports/MyFont-Regular/MyFont-Regular.woff2",
  "oflPath": "/exports/MyFont-Regular/OFL.txt",
  "settingsPath": "/exports/MyFont-Regular/Settings.txt",
  "configPath": null,
  "files": [...]
}

Progress is emitted as JSON lines on stderr.

baseFont / subFont

Key Default Description
path Font file path (required).
scale 1.0 Outline scale factor.
baselineOffset 0 Vertical offset in font units.
axes [] Variable-font axis values: [{"tag": "wght", "currentValue": 400}, ...]. Empty for static fonts.
excludeCodepoints [] Sub-font only. Codepoints to keep sourced from baseFont. Each entry is "U+XXXX", "U+XXXX-U+YYYY" (inclusive range), or a raw integer. Useful for Latin + CJK merges that want CJK-conventional shapes for symbols (e.g. ①, ◯, ※, Ⅰ, ℃). Ignored on baseFont.

When the sub font carries a glyph name that the base font also uses but at a different codepoint (e.g. Inter encodes U+0298 ʘ as uni25CE while Noto Sans JP uses uni25CE for U+25CE ◎), the merge engine renames the sub-font glyph to {name}.sub so the base outline at the stranded codepoint stays intact. A warning is emitted to stderr for each rename. This is unconditional — same name with disjoint codepoint sets always means unrelated glyphs.

output

Key Default Description
familyName "Font" Output font family name.
postScriptName "" PostScript name (nameID 6). When empty, derived from familyName by stripping chars outside printable ASCII 33–126 and []{}<>()/%, clamped to 63 bytes.
version "1.000" Version string (nameID 5). A Version prefix is prepended automatically if missing.
weight 400 Font weight (100–900).
italic false Whether the output is italic.
width 5 Font width class (1–9).
upm (from base) Target units-per-em. When different from the base font, all metrics and outlines are scaled.
manufacturer "" Manufacturer name (nameID 8).
manufacturerURL "" Manufacturer URL (nameID 11).
copyright "" Additional copyright string appended to source copyrights.
trademark "" Additional trademark string appended to source trademarks.
metricsSource "base" Which font's vertical metrics (OS/2, hhea) to use. "base" keeps the base font metrics and expands only when the sub font is larger. "sub" overwrites with the sub font's metrics.
metadataMode "merge" Identity policy. "merge" (or null / unset) rewrites name / OS/2 / head identity records as a fresh derivative work — current default. "inheritBase" passes the base font's identity through untouched; "inheritSub" does the same with the sub font (errors if subFont is absent). Only the output.* fields you explicitly set act as overrides on top of the inherited identity, and OFL nameID 13/14, designer, vendor ID, and head.created/modified are left alone. Useful for intermediate artifacts or merges that should not self-identify as a new derivative (e.g. adding Noto Hentaigana glyphs into Noto Sans JP).
hinting "strip" TrueType output hinting policy. "strip" (also "unhinted" / "none") removes TT bytecode, fpgm, prep, and cvt , while keeping maxp valid for unhinted outlines. "ttfautohint" (also "autohint") first writes the final stripped TTF, then runs an external ttfautohint binary over the finished font. CFF output keeps its separate CFF hint-preserving path.

export.path

All keys are optional. Only files whose paths are specified are written. woff2 requires font.

Key Description
font Font file (OTF/TTF) path.
woff2 WOFF2 file path.
ofl OFL.txt path.
settings Settings.txt path.
config ExportConfig.json path.

export.package

Creates a complete output directory. Always generates font, WOFF2, OFL.txt, and Settings.txt.

Key Default Description
dir Output directory path (required).
overwrite false Allow overwriting an existing directory.
bundleInputFonts false Copy input fonts into a source/ subdirectory and write ExportConfig.json with relative paths. Makes the package self-contained and reproducible.

Tests

python3 -m pytest python/tests/ -v

Test fonts live in python/tests/fonts/.

License

The source code in this directory is licensed under the MIT License. See LICENSE for details.

Test fonts under tests/fonts/ follow each font's own license (OFL, etc.) and are not covered by the MIT notice.

Other parts of the parent repository (OFL Font Baker) are licensed under AGPL-3.0-or-later and are not covered by this MIT notice.

Metadata

Release files for ofl-font-baker 0.4.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ofl-font-baker 0.4.9
File Size Uploaded Provenance
ofl_font_baker-0.4.9.tar.gz 67.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ofl-font-baker 0.4.9
File Interpreter ABI Platform
ofl_font_baker-0.4.9-py3-none-any.whl Python 3 none any Details

Total release size: 140.4 kB

Release files / ofl_font_baker-0.4.9.tar.gz

Download URL ofl_font_baker-0.4.9.tar.gz
Size 67.4 kB
Tags Source
SHA-256 checksum
How to use checksums
720cbe506cf4cda7d2a67f0ea7189063630afb1fbb090d291d9a2c62fcc5433d
BLAKE2b-256 checksum
How to use checksums
9b2484aecaa81f476acbbacb177dc1bfcd4cef14d5f0317a9ca6eadd9258fbce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / ofl_font_baker-0.4.9-py3-none-any.whl

Download URL ofl_font_baker-0.4.9-py3-none-any.whl
Size 72.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b94af174f053d131896c56ed83a0e1f7504430946d00f2938679aa1265323fda
BLAKE2b-256 checksum
How to use checksums
ce864501762a1280288f81491fcc266e9c63c582c97153514086fa270e2ddea0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Security for ofl-font-baker 0.4.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page