ColrPak

A desktop color font editor for COLRv0 and COLRv1 fonts


Project maintained by mitradranirban Hosted on GitHub Pages — Theme by mattgraham

Changelog

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.


[0.7.0] - 2025-05-13

✨ New Features

🛠 Improvements & Refactoring

🌍 Internationalization (i18n)

🐛 Bug Fixes

[v0.6.1] - 2026-05-06

Fixed

fontra-color-support

fix(paint-tool): correct PaintTransform bounding box origin and eliminate fallback flash

[v0.6.0] - 2026-04-28

Added

Changed

Fixed

fontra-compile(color-support)

Internal

[v0.5.2] - 2026-04-26

fontra-color-support

featcolrv1 improve PaintComposite authoring in panel-color-layers.js

[v0.5.1] - 2026-04-24

Github Workflow

[v0.5.0] - 2026-04-24

fontra-color-support

Added

Fixed

[v0.4.5] -2026-04-22

fix(builder): cu2qu conversion, name table, and OpenType feature compilation

Three significant fixes to the font compilation pipeline:

  1. Fix cubic-in-glyf browser rejection (OTS compatibility)
    • Remove glyphDataFormat=1 assignment for cubic glyf outlines as glyph-1 support is not main stream in any app yet
    • Add cu2qu conversion inside buildTTGlyph() when cubic off-curve points (flagCubic) are detected in the default source
    • Conversion is performed across ALL sources in lockstep using Cu2QuPen to ensure identical point counts across masters
    • Rebuild gvar variation deltas from converted quadratic coordinates so outline variation is preserved correctly after conversion
    • Keeps glyphDataFormat=0 (quadratic TrueType), which is the only value accepted by browser OTS implementations today
    • OpenType 1.9 cubic-in-glyf (glyphDataFormat=1) is spec-valid but rejected by all current browsers; this fix ensures web-ready output
  2. Fix name table compiled from font source metadata
    • Replace empty setupNameTable(dict()) with data read from font-data.json via the existing getFontData() method
    • Populates familyName, styleName, fullName, uniqueFontIdentifier, version, and psName from fontInfo fields in the Fontra source
  3. Add OpenType feature compilation (GSUB/GPOS)
    • Read features.txt from the .fontra package root (Adobe .fea format)
    • Compile into GSUB and GPOS tables using fontTools feaLib (addOpenTypeFeatures) after the font is otherwise fully built
    • Supports all feature types: calt, kern, liga, mark, etc.
    • Failure is non-fatal: emits a warning and continues without features
  4. Fix duplicate function definitions (flake8 F811)
    • Remove duplicate definitions of _normalizePaletteLabels and _palettesHaveLabels that were already defined earlier in the module

      [v0.4.4] - 2026-04-16

      feat(colrv1): add CPAL palette names + fix variable paint compilation

New Features

CPAL v1 Palette Names

UI (panel-color-palette.js)

Translations (local-language-overrides.csv)

Bug Fixes

COLRv1 variable font compilation (builder.py)

[v0.4.3] - 2026-04-16

color-support

Add full COLRv1 round-trip support and fix variation handling

This major update enhances the OTF backend’s ability to read compiled COLRv1 color fonts and seamlessly convert them into Fontra’s native format, preserving crucial data like clip boxes and exact master metrics for editing and exporting.

COLRv1 Structural & ClipBox Support

Variation & Indexing Fixes

General Glyph & Font Source Updates

[v0.4.2] - 2026-04-13

ColrPak

fontra-color-support

fix(colrv1): restore layer-nested data structure for compiler and tool compatibility

In commit eae66e7, the COLRv1 data path was simplified to write to the root glyph’s customData. This caused a structural mismatch:

  1. The Paint Tool failed to render/manipulate handles because it targets the layer instance’s customData.
  2. The Fontra compiler failed to associate color paints with their respective geometric contours.

This change reverts the “simplification” and enforces the previous standard (nested under layers[id].glyph.customData).

Changes:

Fixes: Invisible paint handles and compiler rendering errors.

[v0.4.1] - 2026-04-12

fontra-color-support

Deployment:

[v0.4.0] - 2026-04-07

Colrpak Main

Fixed

fix(export): block OTF export for .fontra sources with user-facing error

COLRv1 fonts require TrueType (glyf) outlines — CFF2 (OTF) is incompatible with COLR/CPAL tables per the OpenType spec. .fontra is Colr Pak’s native COLRv1 format and must always compile to TTF or WOFF2.

Previously, selecting OTF as the export format for a .fontra source would silently pass the request to fontra_compile, which crashed deep in fontTools with AssertionError: assert not self.isTTF.

Note: .ufo and .designspace sources exporting to OTF are unaffected — COLRv0 with CFF outlines is valid per spec and fontmake handles it correctly. This guard is intentionally scoped to .fontra sources only.

Added

Both nsis setup exe and msi installer for Windows Platform are now available

Changed

Modified Version scheme and organisaion in Pyinstaller Spec to avoid confusion with Upstream fontra

fontra-compile (color-support)

Fixed

fix(builder): force TTF mode for .fontra sources to prevent CFF2/COLR collision

COLRv1 fonts require TrueType (glyf) outlines — the OpenType spec does not permit CFF2 in a font with COLR/CPAL tables. When a .fontra source contained cubic curves, buildCFF2 was being set to True by the caller, causing:

  1. FontBuilder to initialize with isTTF=False
  2. The COLRv1 paint path to run (correctly detecting color data)
  3. setupCFF2() to be called immediately after, triggering: assert not self.isTTF → AssertionError (fontTools/fontBuilder.py:576)

Two guards added in builder.py:

build() — early guard before prepareGlyphs():

buildFont() — final guard before FontBuilder is instantiated:

cu2qu handles cubic→quadratic conversion transparently during glyf table construction, so forcing TTF mode does not lose any outline fidelity.

Reproducer: open any .fontra font with cubic outlines → Export As → TTF Previously: AssertionError crash in fontra_compile.main.main() Now: compiles cleanly with correct glyf + COLR/CPAL tables

fix(colrv1): correct PaintSweepGradient angle units in dataToPaint — scale startAngle/endAngle by 360.0 to convert Fontra turn fractions (0–1) to degrees expected by paintcompiler. Regression introduced when the same fix was applied to the mergenode variation path in v0.2.4 but missed the static dataToPaint path.

fontra-color-support

Fixed

fix(colrv1-renderer): correct PaintComposite color rendering

COLRv1 glyphs with PaintComposite nodes rendered with incorrect colors
due to backdrop paint bleeding directly onto the main canvas context.

Root cause: Canvas 2D globalCompositeOperation composites against
existing canvas content, not against a local backdrop. PaintComposite
requires isolated rendering per the COLRv1 spec.

Fix: render backdrop and source into OffscreenCanvas buffers, apply
composite mode between them, blit result to main canvas.

fixes issue #2

Tested with: knobs, ticket, boarding-pass emoji glyphs.

Added

feat(colrv1): implement async clip glyph rendering for COLRv1 canvas

- Read paint graph from customData["colorv1"] (new backend format)
- Resolve self-referencing PaintGlyph clips from positionedGlyph directly
- Use getGlyphInstance to fetch external clip glyphs asynchronously
- Add module-level _resolvedPathCache to persist paths across render frames
- Add _pendingGlyphs guard to prevent duplicate fetch requests
- Move COLRv1 pre-fetch to positionedLines listener in scene-controller
- Use loadGlyphs for bulk pre-fetching referenced component glyphs
- Canvas now renders COLRv1 glyphs with correct colors and clipping

Clip glyph transform/positioning and axis-aware instantiation are
still to be addressed in a future release.

[v0.3.2] - 2026-04-02

Packaging

[v0.3.1] - 2026-03-29

fontra-compile

[v0.3.0] - 2026-03-27

Added

[v0.2.8] - 2026-03-26

fontra-color-support

[v0.2.7] - 2026-03-24

Changed

Rebrand: replace Fontra references with ColrPak

Started

[v0.2.5] -2026-03-22

Fixed

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:

[v0.2.4] - 2026-03-21

Fixed - fontra_compile@fontra-color-support

fix1: post hhea and os2 metrics not transmitted from fontra format font-info

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:

  1. endAngle ignored — createConicGradient was called with only startAngle; endAngle was never read. Partial arc sweeps always filled the full 360°.

  2. 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.

  3. 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

[v0.2.2] - 2026-03-19

fontra_compile fix : COLRv1 multi-source variation VarStore population

Exports working variable COLR TTF.

[v0.2.1] — 2026-03-18

Fixed

Verified

COLRv1 variable font compiles and renders correctly with colour palette and variable axes intact

[v0.2.0] - 2026-03-18

Colr Pak (mitradranirban/colr-pak)

Features

Bug Fixes


Fontra (mitradranirban/fontra, branch fontra-color-support)

Features

Bug Fixes


fontra-compile (mitradranirban/fontra-compile branch fontra-color-support )

Bug Fixes

[v0.1.3] - 2026-03-16

colr-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.

[v0.1.2] - 2026-03-15

Colr Pak (mitradranirban/colr-pak)

Bug Fixes

Refactor


Fontra (mitradranirban/fontra, branch fontra-color-support)

Bug Fixes


fontra-compile (mitradranirban/fontra-compile)

Features

Removals


[v0.1.1] - 2026-03-12

Colr Pak

Maintenance

[v0.1.0] - 2026-03-10