A desktop color font editor for COLRv0 and COLRv1 fonts
All notable changes to Colr Pak and its components are documented here. Colr Pak is a fork of Fontra Pak, built on Fontra and fontra-compile.
.woff2) export for both v0 and v1 color fontsRebrand: replace Fontra references with ColrPak
refactor: simplify CompileFontMakeAction to invoke fontmake directly from source path Remove intermediate UFO/designspace export step and helper functions (addInstances, addGlyphOrder, addMinimalGaspTable, _fixColorLibKeys). Instead, unwrap the backend chain to find the original source path and pass it directly to fontmake_main.
fix: execute fontra_compile natively to resolve PyInstaller PATH issues
Previously, exportFontToPathCompile used subprocess.run(["fontra-compile"]).
When packaged with PyInstaller, this caused the application to search the system
$PATH (e.g., ~/.local/bin) for the executable rather than using the bundled module,
causing the compilation to fail.
This replaces the subprocess call with a direct python import of the bundled
fontra_compile.__main__.main function. To maintain exact compatibility with
the existing UI log parser, this commit also:
sys.argv and os.chdir to simulate the external command environmentio.StringIOSystemExit to accurately report the return code in the log filefix1: post hhea and os2 metrics not transmitted from fontra format font-info
Derive hhea and OS/2 metrics from shared source lineMetricsHorizontalLayout and customData instead of letting fontTools default to zeros
startAngle and endAngle keys in Fontra JSON by
providing a 0.0 fallback, preventing silent failures when defaults
are omitted._merge_node to convert Fontra’s turn
fractions (0-1) into the degrees expected by fontTools/paintcompiler.
This fixes the issue where variation deltas in the VarStore were
calculated with the wrong magnitude.
fix(colrv1): correct PaintLinearGradient P2 projection, radial transform, and sweep gradient arc
Three bugs in the COLRv1 canvas renderer caused gradient paints to render incorrectly relative to what the font specifies.
— PaintLinearGradient —
Canvas 2D createLinearGradient takes two points, but COLRv1 defines three: P0 (start), P1 (end), and P2 (rotation anchor). The renderer was passing P0→P1 directly and ignoring P2, producing wrong or reversed gradient axes.
Fix: project P1 onto the perpendicular of (P2−P0) to derive the correct effective end point P1eff before calling createLinearGradient. When P2 coincides with P0 (degenerate case) fall back to P1 unchanged.
— PaintRadialGradient —
COLRv1 radial gradients support an affine transform on the gradient cone, allowing elliptical or rotated radials. The renderer silently discarded paint.transform, so any non-circular radial gradient rendered as a plain symmetric cone.
Fix: wrap the paint in ctx.save()/ctx.restore() and apply paint.transform via ctx.transform() before calling createRadialGradient, so the cone is correctly skewed/rotated by the context matrix.
— PaintSweepGradient —
Three separate errors:
endAngle ignored — createConicGradient was called with only startAngle; endAngle was never read. Partial arc sweeps always filled the full 360°.
Wrong sweep direction — COLRv1 sweep angles are counter-clockwise (font Y-up). Canvas 2D createConicGradient is clockwise (Y-down). The scene transform already flips Y, so the angle must be negated to preserve the correct sweep direction. Without this, all sweeps were mirrored.
Color stops not remapped to arc — stops are defined by the font author relative to the [startAngle, endAngle] arc (0→1 across that arc), but were being passed directly to the conic gradient which interprets them relative to a full 360° turn. Fix: scale each stop offset by arcSpan / (2π) before calling _applyColorLine.
Previews color v1 paint actually what is going to shipped in final font
fontra_compile fix : COLRv1 multi-source variation VarStore population
Exports working variable COLR TTF.
COLRv1 variable font compiles and renders correctly with colour palette and variable axes intact
mitradranirban/colr-pak)edit-tools-paint) for interactive COLRv1 editing:
paletteIndex for PaintSolid layersFontra Pak to Colr Pak in fontra-menuscolr.py — use absolute instead of relative importsmitradranirban/fontra, branch fontra-color-support)2026.3.4paletteIndex in gradient colorStops — _convertColorLine was reading stop.Color?.PaletteIndex but raw fontTools stores PaletteIndex directly on the stop object; all gradient palette indexes were defaulting to 0_setV1ArrayField, _writeV1Paint) and correct colorStops nesting structuremitradranirban/fontra-compile branch fontra-color-support )copyFont stripping color palette data from temporary UFO before compiling through fontmake, which caused color variable fonts to export as monochromelib.plist in variable font compilationcolr-pak 0.1.3
Bugfix: Removed drop-unreachable-glyphs from the export workflow and drop-unused-sources-and-layers from the fontmake compile action in fontra-compile — both filters were silently stripping color layer glyphs before fontmake could build the COLR/CPAL tables, resulting in monochrome output.
mitradranirban/colr-pak).fontra to .ttf/.otf via fontra-compile — resolves
TypeError: run_original() takes 0 positional arguments but 4 were given
crash when exporting from a loaded TTF fontdoExportAs to use top-level exportFontToPath and new
exportFontToPathCompile functions as multiprocessing targets, matching
upstream Fontra Pak structure and preventing future breakageCOLR_PAK_VERSION constant for single-point version managementmitradranirban/fontra, branch fontra-color-support)fix(colrv1): Restore paletteIndex in gradient colorStops —
_convertColorLine was reading stop.Color?.PaletteIndex but raw
fontTools stores PaletteIndex directly on the stop object; all gradient
palette indexes were defaulting to 0fix(colrv1): Fix “add stop” button for COLRv1 gradients — fix method
name references (_setV1ArrayField, _writeV1Paint) and correct
colorStops nesting structurefix(colrv1): TTF COLRv1 paint loading, panel detection and rendering —
.bak file from bisectrelease/0.2.0mitradranirban/fontra-compile)feat: Add COLRv1 compile support via PythonBuilder — reads paint data
and palettes directly from font-data.json/glyph JSON; implements full
_dataToPaint() covering solid, gradients, transforms, composite, with
varscalar() for Fontra keyframe variation specscompile_colorv1_action.py entry point — COLRv1
compilation now handled entirely in build.pycolorV1_export_helper from fontra-compile integration.fontra files exclusively to fontra-compile for proper
COLR and CPAL table compilation2026.3.2add convertPaintGraph/convertColorLine for fontTools raw format
conversion; fix COLRv0 TTF panel detection
fix: Add color palette support for UFO backend.ufo/.designspace (COLRv0), .fontra (COLRv1).glyphs/.glyphspackage (without COLR data).ttf filesfeat(colrv1): Variable font support for .fontra sources + full paint
graph fixes — add getTagLocation(), getPaintGraph(), resolveVal();
fix all 32 paint format handlers including composite modes, PaintGlyph,
bezier curvesfeat(color-layers): Add COLRv1 type-aware parameter UI with
PAINT_PARAM_SCHEMA, paired field rendering, _setV1PaintParam() mutatorfeat(color-palettes): Enhance palette panel — alpha slider, palette tab
strip, usage badges, remove buttons, PALETTES_KEY exportpaintcompiler base COLRv1 builder backendufo2ft working