Skip to content

Native SWF Vector Font Extraction to XML#53

Open
MasterAlexS wants to merge 4 commits into
openfl:masterfrom
MasterAlexS:feature-native-fonts
Open

Native SWF Vector Font Extraction to XML#53
MasterAlexS wants to merge 4 commits into
openfl:masterfrom
MasterAlexS:feature-native-fonts

Conversation

@MasterAlexS
Copy link
Copy Markdown

Description

This PR introduces a zero-dependency native Haxe pipeline for extracting embedded vector fonts directly from parsed SWF files into XML.

The Motivation

Using external TTF compilers (or Java-based tools) during the build process is cumbersome. Furthermore, relying on standard OpenFL TextFields to render these generated .ttf files on native targets (especially Linux via FreeType) often results in inaccurate baseline alignments and slightly off-centered text compared to Flash.

By extracting the raw vector commands and metrics directly, developers can write their own custom text renderers (using graphics.drawPath()) to achieve 100% pixel-perfect text rendering across all platforms, completely bypassing OS-level text rendering quirks.

Technical Implementation

The extraction pipeline bypasses the complex .ttf generation and hooks directly into ShapeCommandExporter to extract DefineFont2 and DefineFont3 geometries.

  1. Direct-to-String SVG Path Generation: Instead of generating arrays of GlyphCommand enums and parsing them later, the SVG commands (M, L, Q) are generated on-the-fly using StringBuf.
  2. Multithreading (sys.thread): Native extraction processes multiple font tags concurrently using background threads with Mutex/Lock synchronization. This scales perfectly on large SWFs with multiple embedded fonts.
  3. Coordinate Rounding: TWIPS coordinates scaled to pixels often result in infinite floating-point artifacts (e.g., 1.33333333333333). Coordinates are rounded to 4 decimal places, which maintains flawless visual fidelity while significantly reducing the output XML file size.
  4. Cross-Platform Safety: Paths are constructed using haxe.io.Path.join() and we handle duplicate embedded font names by appending numeric suffixes (FontName_2.xml).

Testing

I have built a separate OpenFL test application that parses these generated XMLs. It uses pre-calculated openfl.Vector<Int> and Vector<Float> structures at runtime to pass the metrics directly to graphics.moveTo() and curveTo(). The results demonstrate perfectly crisp, baseline-accurate rendering on native Linux targets.

Usage via Neko:

haxe -cp src -cp scripts -lib openfl -lib lime -lib format -D optional-cffi -main ExportFonts -neko export_fonts.n
neko export_fonts.n <input.swf> <output_folder>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant