Skip to content

Add auto font install support#246

Draft
jonmmease wants to merge 12 commits intojonmmease/fontsource-installfrom
jonmmease/auto-fonts
Draft

Add auto font install support#246
jonmmease wants to merge 12 commits intojonmmease/fontsource-installfrom
jonmmease/auto-fonts

Conversation

@jonmmease
Copy link
Collaborator

@jonmmease jonmmease commented Feb 25, 2026

Summary

Add automatic font preprocessing during rendering. When enabled, vl-convert parses the compiled Vega spec to find referenced fonts, checks them against the local fontdb, and can download missing fonts from Fontsource before rendering.

This is the second of three PRs in the font management stack:

Motivation

Even with explicit install_font(), users still have to manually identify referenced fonts and preinstall them. That is error-prone and especially painful for themes/config-driven fonts.

This PR separates two independent concerns:

  • Network behavior: auto_install_fonts (bool) controls whether missing fonts may be downloaded from Fontsource
  • Missing-font policy: missing_fonts controls what happens when referenced fonts are unavailable (fallback, warn, error)

Behavior Matrix

auto_install_fonts missing_fonts Behavior
false fallback Default: no font preprocessing; renderer falls back naturally
false warn Validate against local fontdb and warn for missing fonts; no network
false error Validate against local fontdb and fail on missing fonts; no network
true fallback Attempt Fontsource downloads; continue with fallback on failures
true warn Attempt downloads; warn on API/unavailable/download failures
true error Attempt downloads; fail on API/unavailable/download failures

Generic CSS families (serif, sans-serif, etc.) are treated as generic fallbacks and are never flagged as missing.

Changes

New module: vl-convert-rs/src/extract.rs

  • CSS font-family parser (named vs generic entries)
  • Vega spec traversal to extract font-family strings from marks, axes, legends, titles, config, and wordcloud
  • resolve_first_fonts classification (Available, NeedsDownload, Generic, Unavailable) using first-font semantics

Core library: vl-convert-rs/src/converter.rs

  • Replaced the old mode enum with two config fields:
    • auto_install_fonts: bool
    • missing_fonts: MissingFontsPolicy (Fallback, Warn, Error)
  • Added preprocess_fonts pipeline that handles:
    • local availability checks
    • optional Fontsource catalog checks/downloads
    • warn/error behavior based on missing_fonts
  • Added strict local validation path (auto_install_fonts=false, missing_fonts=error) with no Fontsource API access
  • Renamed/expanded integration hooks:
    • maybe_compile_vl_with_preprocessed_fonts
    • maybe_preprocess_vega_fonts
  • Hooks apply across render + scenegraph paths (SVG/PNG/JPEG/PDF and scenegraph/msgpack)
  • Returns Vec<FontForHtml> as scaffolding for PR Add font embedding to HTML export and vegalite_fonts/vega_fonts API #247

CLI: vl-convert/src/main.rs

  • --auto-install-fonts (bool flag)
  • --missing-fonts <fallback|warn|error>
  • Both are global flags and are threaded through converter construction

Python bindings: vl-convert-python/src/lib.rs + vl_convert.pyi

  • configure_converter(auto_install_fonts: bool | None = None, missing_fonts: Literal["fallback", "warn", "error"] | None = None)
  • get_converter_config() now reports:
    • auto_install_fonts: bool
    • missing_fonts: "fallback" | "warn" | "error"
  • Async API/type stubs updated to match

Commits

  1. 0809967 feat: add font extraction and resolution module
  2. e24910e feat: add auto font download to converter
  3. d437728 feat: add auto_install_fonts plumbing to PR2
  4. 12d80fe fix: address 13 code review recommendations for auto-fonts
  5. dc280ef refactor: split behavior into auto_install_fonts + missing_fonts policy

Review Tour

Tier 1 — Start here:

  • vl-convert-rs/src/extract.rs — font-family parsing, Vega traversal, and first-font resolution logic

Tier 2 — Integration behavior:

  • vl-convert-rs/src/converter.rsMissingFontsPolicy, preprocess_fonts, and conversion-path hooks

Tier 3 — User-facing APIs:

  • vl-convert/src/main.rs — CLI options + converter wiring
  • vl-convert-python/src/lib.rs — Python config parsing/serialization
  • vl-convert-python/vl_convert.pyi — updated typing surface

Testing

Locally run:

  • cargo check -p vl-convert-rs -p vl-convert-python -p vl-convert

(Full test suites are expected to run in CI.)

jonmmease and others added 4 commits February 25, 2026 06:48
Add a new crate for downloading and caching font files from the
Fontsource catalog (which includes Google Fonts and other open-source
fonts). Features include:

- HTTP-based font file download with Fontsource API integration
- LRU-evicting disk cache with configurable size limit
- File-level locking for safe concurrent access
- Font metadata caching and validation
- Add fontsource dependency to vl-convert-rs
- Add FONTSOURCE_CACHE global, font registration, install_font(),
  and configure_font_cache() functions in text module
- Re-export install_font and configure_font_cache from crate root
- Add AutoInstallFonts enum and auto_install_fonts config field
  to VlConverterConfig (dormant until auto-download is implemented)
Python bindings:
- Add install_font() and install_font_asyncio() functions
- Add auto_install_fonts and font_cache_size_mb to configure_converter()
- Add AutoInstallFonts type and ConverterConfig updates to .pyi stubs

CLI:
- Add --install-font flag for explicit font installation
- Add --auto-install-fonts flag (strict/best-effort modes)
- Pass auto_install_fonts config through build_converter to all commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jonmmease jonmmease force-pushed the jonmmease/auto-fonts branch from 617b385 to ed148bb Compare February 25, 2026 13:15
The AutoInstallFonts enum, --auto-install-fonts CLI flag, and
auto_install_fonts Python parameter are moved to PR2 where the
actual auto-download logic lives.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jonmmease and others added 4 commits February 25, 2026 09:27
Remove font-subset from Cargo.lock (PR3-only dependency) and fix
rustfmt formatting in Python bindings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add extract module for parsing font-family strings from Vega specs
and resolving them against system fonts and the Fontsource catalog:

- CSS font-family string parser handling quoted/unquoted names
- Vega spec traversal extracting fonts from axes, titles, marks,
  legends, transforms, and config
- First-font resolution classifying fonts as available, downloadable,
  generic, or unavailable
- FontForHtml type for tracking font source (Google vs other)
Add AutoInstallFonts enum and configuration to converter, CLI,
Python bindings, and type stubs. Moved from PR1 where it was a no-op.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jonmmease jonmmease force-pushed the jonmmease/auto-fonts branch from 29c9209 to d437728 Compare February 25, 2026 14:27
jonmmease and others added 3 commits February 25, 2026 11:55
- Make extract::is_available pub, remove duplicated is_available_in_fontdb
- Strict mode now returns hard errors on download failures and API errors
- Network errors distinguished from "not in catalog" in error messages
- Replace unreachable!() for Off with return Ok(vec![])
- Change maybe_compile_vl_with_auto_fonts to return Option instead of nested Result
- Add auto-font hooks to all 4 scenegraph methods (vega/vegalite × json/msgpack)
- Add missing config keys: config.font, config.mark.font, header variants,
  axisDiscrete/Point/Quantitative/Temporal
- Fix axis/legend/title encode traversal to iterate all states (not just update)
- Case-insensitive generic family matching (Sans-Serif → Generic)
- Python type stubs use Literal["off", "strict", "best-effort"]
- Add comments: allow_http_access independence, FontForHtml scaffolding, doc separator
- Add 9 new tests for config keys, encode states, and case-insensitive generics

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jonmmease jonmmease changed the title Add auto font download support Add auto font install support Feb 26, 2026
@jonmmease jonmmease force-pushed the jonmmease/fontsource-install branch from 903179c to 116d812 Compare February 28, 2026 23:47
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