Skip to content

Instantly share code, notes, and snippets.

@DallenB4
Created November 7, 2025 23:24
Show Gist options
  • Select an option

  • Save DallenB4/6a602040791ade1b84953b4b666f2ce7 to your computer and use it in GitHub Desktop.

Select an option

Save DallenB4/6a602040791ade1b84953b4b666f2ce7 to your computer and use it in GitHub Desktop.
Patch U+F8FF of a TrueType font with an SVG. Make sure your entire SVG is made of paths.
from fontTools.ttLib import TTFont
from fontTools.pens.ttGlyphPen import TTGlyphPen
from fontTools.pens.cu2quPen import Cu2QuPen
from fontTools.pens.transformPen import TransformPen
from fontTools.pens.boundsPen import BoundsPen
from fontTools.misc.transform import Transform
from fontTools.svgLib import SVGPath
def patch_svg_into_font(svg_path, input_ttf, output_ttf, max_err=0.02):
glyph_name = "uniF8FF"
font = TTFont(input_ttf)
# Font metrics
upem = font["head"].unitsPerEm
ascent = font["hhea"].ascent
descent = font["hhea"].descent
vbox_height = ascent - descent
# Determine glyph advance width
hmtx = font["hmtx"].metrics
if glyph_name in hmtx:
advanceWidth, _ = hmtx[glyph_name]
else:
first = font.getGlyphOrder()[0]
advanceWidth = hmtx.get(first, (upem, 0))[0]
tt_pen = TTGlyphPen(None)
cu2qu = Cu2QuPen(tt_pen, max_err)
svg = SVGPath(svg_path)
svg.draw(cu2qu)
glyph_raw = tt_pen.glyph()
bpen = BoundsPen(None)
glyph_raw.draw(bpen, None)
xMin, yMin, xMax, yMax = bpen.bounds
raw_w = xMax - xMin
raw_h = yMax - yMin
sx = advanceWidth / raw_w
sy = vbox_height / raw_h
scale = min(sx, sy)
target_cx = advanceWidth / 2
target_cy = (ascent + descent) / 2
glyph_cx = (xMin + xMax) / 2
glyph_cy = (yMin + yMax) / 2
dx = target_cx - scale * glyph_cx
dy = target_cy + scale * glyph_cy
tt_pen2 = TTGlyphPen(None)
cu2qu2 = Cu2QuPen(tt_pen2, max_err)
transform = Transform(scale, 0, 0, -scale, dx, dy)
tpen = TransformPen(cu2qu2, transform)
svg = SVGPath(svg_path)
svg.draw(tpen)
glyph = tt_pen2.glyph()
order = font.getGlyphOrder()
if glyph_name not in order:
order = order + [glyph_name]
font.setGlyphOrder(order)
font["glyf"][glyph_name] = glyph
lsb = int(round((advanceWidth - raw_w * scale) / 2))
font["hmtx"].metrics[glyph_name] = (int(round(advanceWidth)), lsb)
font.save(output_ttf)
print(f"Saved {output_ttf}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment