fontations 0.0.1 copy "fontations: ^0.0.1" to clipboard
fontations: ^0.0.1 copied to clipboard

Flutter bindings for the fontations font stack (read-fonts / skrifa), powered by flutter_rust_bridge.

Unreleased #

Web #

  • The plugin declares the web platform and compiles the crate to WebAssembly: scripts/build_web.sh builds pkg/fontations.js + pkg/fontations_bg.wasm (nightly, -Z build-std, shared memory) and the example app builds and runs on the web. initFontations() and the rest of the API are unchanged.
  • lib/fontations_web.dart is the (empty) web entry point Flutter requires, and flutter_web_plugins is now a dependency for it.
  • scripts/coop_server.py serves a build with the cross origin isolation headers a threaded wasm module needs; without them SharedArrayBuffer is missing and the worker pool panics at start up.
  • Fix: the example could not be run at all. flutter run -d chrome and every plain static host send no COOP/COEP, so the module panicked with SharedArrayBuffer transfer requires self.crossOriginIsolated right after loading. example/web/coi_serviceworker.js now adds those headers to the navigation response, example/web/index.html registers it and reloads once, and example/web/flutter_bootstrap.js keeps Flutter's own service worker unregistered (one scope, one worker - Flutter's would evict this one). Any static server can now host the build; scripts/coop_server.py stays for hosts that can send the headers themselves.
  • Web has to be built separately - unlike every other platform it is not wired into the platform build systems.
  • Tests: the package gained test/fontations_test.dart (VM only; a browser run needs both the pkg/ files and the isolation headers, which the flutter test --platform chrome harness does not provide), and CI gained a web job plus cargo build --release && flutter test in the dart job.

Shaping fixes #

  • USE_MARK_FILTERING_SET is honoured: a lookup that names one takes its "is this a mark?" answer from that GDEF coverage table instead of the glyph classes. Previously the flag was parsed and ignored, so a font that filters marks had them treated as bases.
  • A ligature no longer reaches across a glyph the lookup ignores: every glyph of the sequence is checked, not just the first one.
  • Cursive attachment no longer writes its cross stream correction into y_advance. It belongs in y_offset; y_advance is vertical layout and used to move every following glyph of a vertical run.
  • The mark attachment lookups (mark to base / ligature / mark) now respect the lookup flags too; they used to skip them entirely.
  • Tests: eight new cases cover multiple, alternate, ligature, contextual, mark to base and cursive substitution, plus regression tests for each fix above. They splice the layout tables into a font with FontBuilder, which is the only way to exercise lookups the write side cannot produce.

CI #

  • Added .github/workflows/ci.yml: cargo fmt --check + cargo test on Linux, dart format + flutter analyze on Linux, an artifact freshness check, and the example's macOS integration tests.
  • scripts/build_xcframework.sh now records a fingerprint of rust/ in scripts/xcframework.sha256, and the new scripts/check_xcframework.sh compares it against the current crate. A stale prebuilt binary does not fail a build — SwiftPM links it silently — so CI fails on it instead. The macOS job is gated on this check, otherwise its tests could report on Rust code that is not the commit under test.

Packaging #

  • Added Swift Package Manager support for iOS and macOS (ios/fontations/Package.swift, macos/fontations/Package.swift). Apps that use SwiftPM now link a prebuilt binary (fontations.xcframework in each folder) instead of compiling Rust during the Xcode build, because SwiftPM has no script phases and its build tool plugins are sandboxed. The binaries are committed and rebuilt with ./scripts/build_xcframework.sh.
  • The CocoaPods integration still compiles Rust from source as before, and is used automatically by apps that have SwiftPM turned off.
  • initFontations() now resolves the Rust library in whichever shape it was built into the app: dynamically from the app bundle on SwiftPM, or from the app executable when CocoaPods linked Rust statically.

Write side #

  • GlyphSpec.components builds composite glyphs (translated, uniformly scaled parts reused from other glyphs), with the composite bounding box computed from the parts.
  • FontBuildRequest.ligatures writes GSUB ligature substitutions, and modifyFont can add them to an existing font.
  • GlyphSpec.colorLayers + FontBuildRequest.palette write COLR version 0 and CPAL, so Font.colorGlyph/ColorGlyphInfo.paint can draw them.
  • VariationAxisSpec.mappings writes an avar table, and the same mapping is applied to gvar/HVAR/MVAR deltas so they stay consistent.
  • VariationMaster.globalMetrics writes MVAR (hasc, hdsc, hlgp, hcla), so global metrics interpolate along the axes.
  • FontBuildRequest.verticalMetrics writes vhea + vmtx, with per glyph verticalAdvance / verticalOrigin.
  • FontBuildRequest.rawTables copies tables verbatim (fpgm, prep, cvt , gasp, …) and GlyphSpec.instructions stores per glyph TrueType hinting bytecode in glyf.
  • FontBuildRequest.variationSelectors writes cmap format 14.
  • modifyFont patches an existing font (metadata, kernPairs, alternates, ligatures) while copying every other table over untouched.
  • OS/2 is filled in properly (weight/width class, fsSelection from the subfamily name, vendor id, average width, unicode ranges) and the name table can carry designer, license, manufacturer and version.
  • kernPairs compile into a GPOS kern feature; STAT is written for variable fonts; StylisticAlternate.name becomes an ssNN/cvNN feature parameter.
  • Still open: CFF/CFF2 output, sbix/CBDT, VORG, COLR v1 and gvar on composites.

Read side #

  • Raw access to any table (Font.tableData / tableLength / hasTable) plus a structured view of GSUB/GPOS (Font.layout: scripts, languages, features, lookup counts).
  • Font.attributes() (weight / stretch / style from OS/2), Font.glyphName() + glyphNameSource(), Font.nameRecords({nameId}) with every localization, Font.charmapInfo() / charMappings() / glyphToChar().
  • Font.glyphMetrics() (advance, left side bearing, bounds), vertical metrics from vhea/vmtx/VORG.
  • COLR color glyphs flattened into layers (Font.colorGlyph, colorPalettes) with a ColorGlyphInfo.paint(canvas) helper on the Dart side, and embedded bitmaps (Font.bitmapStrikes, Font.bitmapGlyph) decoded to RGBA.
  • Font.outline(..., hinted: true) applies the hinting in the font, and GlyphOutline now reports format, hasHinting and hasOverlaps; Font.outlineFormat() says whether outlines come from glyf or CFF.
  • Font.shape(text, {size, variations, script, language, features}) applies GSUB and GPOS instead of only describing them: single, multiple, alternate and ligature substitutions, reverse chains, and the contextual and chained contextual lookups (with their nested lookups); single, pair, cursive, mark-to-base, mark-to-ligature and mark-to-mark positions. Returns advances, offsets and the source cluster of every glyph.
  • MATH: Font.hasMath(), mathConstants({ppem}), mathGlyphInfo(...) and mathVariants(...) expose the constants, the per glyph italics correction, accent attachment and corner kerns, and the variants and assembly of a stretchy delimiter.
  • VARC: Font.hasVarc() and varcComponents(...) resolve a variable composite glyph into the components it is drawn from, with their transforms, axis values and whether their condition holds at the location.
  • cmap format 14: Font.mapVariant(codePoint, selector) and Font.variantMappings() look up variation selectors.
  • avar / avar2: Font.avarInfo() reports the per axis segment maps and whether avar2 deltas are present; Font.normalizedCoords(variations) reports the normalized coordinate a set of user settings ends up at.
  • Font.shape takes features as a list that distinguishes "unset" from "empty": null uses the defaults, [] turns every feature off.

Example #

  • New shaping page (example/lib/shaping_page.dart): shapes a run of text with Font.shape, draws the positioned glyphs on a canvas, and lets you toggle every feature the font declares (default / all off / custom).
  • The font info page now also shows attributes(), the GSUB/GPOS feature lists, the cmap summary, the live avar-normalized coordinates next to the axis sliders, and which optional tables the font carries (MATH, VARC, COLR, bitmaps, vertical metrics, cmap 14).
  • Shared demo widgets live in example/lib/demo_widgets.dart.
  • The example no longer hardcodes its font: example/lib/font_source.dart holds the open font, the reading and shaping pages both follow it, and the reading page can open any .ttf / .otf / .ttc / .otc through a native open panel (file_picker). A .ttc collection gets a face selector, the files opened in a session can be switched between, and the bundled Inter is one button away. The preview text is editable, so a font that is not Latin can still be inspected.
  • The example is now responsive: at 900px and above the shell swaps the bottom NavigationBar for a NavigationRail (labels appear from 1240px) and the read/shaping pages split into two columns, so a desktop window is not one very wide single column. The writing page keeps its board + panel split but caps the panel at 560px. The macOS window opens at 1180×820 with a 640×720 minimum.
  • Tests: 32 Rust unit tests and 15 Flutter integration tests.

0.0.1 #

  • Initial release: exposes the fontations font stack (read-fonts / skrifa) to Flutter via flutter_rust_bridge.
    • Font.fromBytes to parse a font or a single face of a .ttc collection.
    • Font.info / readFontInfo for name table strings, metrics, fvar axes, named instances and the table directory.
    • Font.charToGlyph, Font.advanceWidth and Font.outline for glyph level access, including variable font locations.
    • GlyphOutline.toPath() helper that turns outlines into a dart:ui Path.
    • buildFont compiles glyph contours (in font units) into a .ttf using write-fonts, covering head/hhea/maxp/hmtx/OS/2/glyf/loca/ name/cmap/post.
    • buildFont also writes variable fonts: declare axes (plus optional instances) and give each glyph masters — alternative outlines pinned to points in variation space — to get fvar + gvar. Masters must be point compatible with the default outline.
    • buildFont also writes stylistic sets: StylisticAlternate entries become extra glyphs reachable through GSUB single substitutions (ss01..ss20, cv01, ...). Each alternate carries its own advance width.
    • Example app gained a second page: draw a character on a board, bind it to a code point, save several masters along a wght axis plus discrete variants under ss01..ss20, export the font and render it through FontLoader, with a live interpolation preview and per-feature previews.
1
likes
160
points
112
downloads

Documentation

API reference

Publisher

verified publishernoob-coder.com

Weekly Downloads

Flutter bindings for the fontations font stack (read-fonts / skrifa), powered by flutter_rust_bridge.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, flutter_rust_bridge, flutter_web_plugins

More

Packages that depend on fontations

Packages that implement fontations