Skip to content

Instantly share code, notes, and snippets.

@simoncozens
simoncozens / SKILL.md
Created September 16, 2026 20:29
rust-fontations-patterns/SKILL.md
name rust-fontations-patterns
description Idioms for reading, manipulating and writing OpenType fonts in Rust with the fontations crates (read-fonts, skrifa, write-fonts and fontdrasil). Use this when writing any Rust code that parses font tables, draws outlines, measures glyphs, works with design-space coordinates/locations (including avar), edits layout tables (GSUB/GPOS/GDEF/STAT) or builds/modifies font binaries. No project-specific abstractions — only the public crate APIs.

OpenType Font Manipulation in Rust (fontations)

Idioms for the fontations family of crates, as used in real-world font tooling:

| Crate | Version | Role |

@simoncozens
simoncozens / analyze-proportions.ipynb
Created August 6, 2026 11:31
Glyph proportion analysis
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@AllLetters = [ n ]; # Add some more letters here... But don't include the space!
@OneAway = [ n.oneaway ]; # a.oneaway b.oneaway etc.
@TwoAway = [ n.twoaway ];
@Peak = [ n.peak ];
lookup oneaway { sub @AllLetters by @OneAway; } oneaway;
lookup twoaway { sub @allLetters by @TwoAway; } twoaway;
lookup peak { sub @AllLetters by @Peak; } peak;
feature rclt {
@simoncozens
simoncozens / debug-merge.py
Created January 31, 2024 09:40
Helper script to debug merge issues in fonttools -o variable
from glyphsLib import load, to_designspace
from ufo2ft.featureCompiler import FeatureCompiler, parseLayoutFeatures
from fontTools.feaLib import ast
import argparse
class Checker:
def __init__(self, sources):
self.masters = []
for source in sources:
@simoncozens
simoncozens / sparsify.py
Last active May 13, 2026 21:52
sparsify.py - turn masters into sparse masters
import uuid
from glyphsLib import load, GSPath, GSNode, GSLayer
from fontTools.varLib.models import VariationModel, normalizeValue
import numpy as np
from tqdm import tqdm
import argparse
def interpolate_paths_without(glyph, intermediate_layer, intermediate_location):
tags = [axis.axisTag for axis in glyph.parent.axes]
#!/opt/homebrew/bin/python3
import sys
sys.path.insert(0, "/Users/simon/others-repos/ufo2ft/Lib")
from glyphsLib.classes import GSFont
from glyphsLib.builder import UFOBuilder
from glyphsLib.builder.font import fill_ufo_metadata
from fontmake.font_project import FontProject
from timeit import default_timer as timer
import requests
from dateutil.relativedelta import relativedelta, FR
from datetime import datetime
import os
lastweek = datetime.utcnow().replace(hour=0,microsecond=0) + relativedelta(weekday=FR(-1))
headers = {"Authorization": "bearer "+os.environ["GITHUB_TOKEN"]}
def run_query(query):
import sys
import os
DEFAULT_NGRAM_SIZE = 5
def all_ngrams(word, size=None):
if size is None:
size = DEFAULT_NGRAM_SIZE
for i in range(max(1, len(word) - size)):
from fontTools.ttLib import TTFont
from fontTools.ttLib.tables.otBase import OTTableWriter
import sys
from fontTools.feaLib.lookupDebugInfo import LOOKUP_DEBUG_INFO_KEY
font = TTFont(sys.argv[1])
def locate(table, ix):
if "Debg" not in font:
return str(ix)

Justification with Variable Fonts

  • In JSTF header
Type Name Description
uint16 majorVersion Major version of the JSTF table, = 1
uint16 minorVersion Minor version of the JSTF table, = 0
uint16 jstfScriptCount Number of JstfScriptRecords in this table
JstfScriptRecord jstfScriptRecords[jstfScriptCount] Array of JstfScriptRecords, in alphabetical order by jstfScriptTag