4 Outlines
dxtr edited this page 2026-10-17 04:35:18 +02:00

Outlines

glyph-outline font glyph → list of contours

The glyph's outline, walked by HarfBuzz's draw API (hb_font_draw_glyph), as a list of contours. Each contour is a list of segments starting with a :move-to:

(:move-to x y)
(:line-to x y)
(:conic-to cx cy x y)              ; quadratic Bézier, control point then end point
(:cubic-to c1x c1y c2x c2y x y)    ; cubic Bézier

This is the same form as cl-ft2:glyph-outline, so code that consumes outlines works with either library.

(hb:glyph-outline font (hb:font-char-glyph font #\L))
;; => (((:MOVE-TO 201 1493) (:LINE-TO 403 1493) (:LINE-TO 403 170)
;;      (:LINE-TO 1130 170) (:LINE-TO 1130 0) (:LINE-TO 201 0) (:LINE-TO 201 1493)))

A glyph with no outline (space, a bitmap-only glyph) gives nil.

Coordinates

  • In the font's units, y up: font units for a plain font, pixels at the face's size for an ft2-font (see Core concepts).
  • After variations: the font's current design coordinates apply.
  • Unhinted. For hinted outlines use cl-ft2.
  • Exact: integers where integral, otherwise floats for a plain font and rationals for an ft2-font. The implied on-curve points between two consecutive TrueType off-curve points are exact midpoints here, where FreeType truncates them to integer 26.6 values.

The same glyph through an ft2-font at 32 px:

(((:MOVE-TO 201/64 1493/64) (:LINE-TO 403/64 1493/64) (:LINE-TO 403/64 85/32)
  (:LINE-TO 565/32 85/32) (:LINE-TO 565/32 0) (:LINE-TO 201/64 0) (:LINE-TO 201/64 1493/64)))

Segments and contours

  • TrueType (glyf) glyphs give :line-to and :conic-to; CFF/CFF2 glyphs give :line-to and :cubic-to.
  • Every contour ends at its start point: HarfBuzz adds the closing :line-to when the outline does not already return there, as in the example. There is no separate close marker.
  • Contour direction follows the font: TrueType outer contours are clockwise, CFF counter-clockwise (in y-up coordinates). Fill with the non-zero winding rule, which is correct for both.
  • Composite glyphs are flattened: you get the components' contours, transformed.

Uses

  • Feeding a vector or GPU renderer (MSDF, Slug, tessellation). cl-textrender builds its outline layer (cubic-to-quadratic conversion, packed quadratics) on this.
  • Converting text to paths for SVG or PDF output.
  • Clip paths for glyph-paint's :push-clip-glyph.

Thread safety

The outline is collected through a special variable bound per call, and the callbacks are static, so concurrent calls on different threads are fine (subject to the font's own thread rules).