Files
skills/docs/media/fonts/font-convert/src/utils/reverse-winding.md
2026-05-29 08:20:56 +01:00

2.8 KiB

reverseWinding

Purpose

Reverses the winding order of a typeface.js path command sequence. Three.js FontLoader expects counter-clockwise winding for outer contours, while some TrueType and CFF fonts ship with clockwise winding. Calling reverseWinding before serialising glyphs ensures the outline direction is corrected without reprocessing the source binary.

Features

  • Splits commands at each M/m moveto to identify individual subpaths
  • Drops Z/z close-path commands (they are implicit in typeface.js rendering)
  • Reverses command order within each subpath
  • Swaps cubic bezier control point pairs (x1/y1 ↔ x2/y2) to maintain curve shape
  • Preserves quadratic bezier single control point after destination flip
  • Works with zero commands (returns empty array, no error)
  • Operates entirely on the PathCommand type from @suaveplan/font-convert

Usage: Basic Example

import { reverseWinding } from "@suaveplan/font-convert";
import type { PathCommand } from "@suaveplan/font-convert";

const commands: PathCommand[] = [
  { type: "m", x: 0,   y: 0 },
  { type: "l", x: 100, y: 0 },
  { type: "l", x: 50,  y: 100 },
  { type: "z" },
];

const reversed = reverseWinding(commands);
// reversed[0] = { type: "m", x: 50, y: 100 }   — last point becomes new start
// reversed[1] = { type: "l", x: 100, y: 0 }
// reversed[2] = { type: "l", x: 0,   y: 0 }

Usage: Advanced Example

import { reverseWinding } from "@suaveplan/font-convert";
import type { PathCommand } from "@suaveplan/font-convert";

// Cubic bezier: reversal swaps x1/y1 and x2/y2
const cubicCommands: PathCommand[] = [
  { type: "m", x: 0, y: 0 },
  { type: "b", x1: 10, y1: 20, x2: 30, y2: 40, x: 100, y: 0 },
];

const rev = reverseWinding(cubicCommands);
// rev[0] = { type: "m", x: 100, y: 0 }
// rev[1] = { type: "b", x1: 30, y1: 40, x2: 10, y2: 20, x: 0, y: 0 }
//            ^^^ x2/y2 and x1/y1 are swapped relative to the original

API Reference

reverseWinding(commands: PathCommand[]): PathCommand[]

Parameter Type Description
commands PathCommand[] Array of path commands as produced by FontConverter

Returns: A new array of PathCommand objects in reversed winding order. The input array is not mutated.

Implementation Notes

The function mirrors the winding-reversal algorithm used in typeface.js's own CLI tooling and the reference FontConverter.ts. Subpath splitting is done by scanning for m/M commands; z/Z close-path commands are discarded because typeface.js renderers treat each subpath as implicitly closed. The reversed list starts with a new m command pointing at the last non-close command of the original path, then walks the original path backwards, placing each point at the previous command's destination.