Files
rust_browser/docs/known_limitations_log.md
Zachary D. Rowitsch e74b16790d Add real font support with bundled Noto Sans and font property pipeline
Integrate ab_glyph-based font rendering with bundled Noto Sans fonts
(Regular, Bold, Italic, BoldItalic, Mono) to replace the fixed-width
text measurer in golden tests. Thread font-weight, font-style, and
font-family through the entire rendering pipeline: CSS parsing → style
computation → layout → display list → rasterizer.

Key changes:
- fonts crate: font database, shaper, and rasterizer with bundled fonts
- CSS: parse font-family (comma-separated lists), font-weight, font-style
- shared: FontWeight and FontStyle types
- style: font property inheritance and computation
- layout: ProportionalTextMeasurer using real font metrics
- display_list: font properties on Text items (conditional dump output)
- render: font-aware text drawing
- Golden tests regenerated with proportional font measurements
- New golden tests (137-141) for font weight, style, family, and headings
- Golden test regeneration infrastructure (regen_goldens.rs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 00:56:41 -05:00

4.4 KiB

Known Limitations Log

Items consciously deferred during implementation for simplicity. Not for planned features.

HTML Entity Decoding

  • Only ~200 common named entities supported; full HTML5 spec defines 2,125+ named character references

CSS Variables

  • Shorthand properties with var() now supported for: margin, padding, background, border, border-top/right/bottom/left, border-width, border-color, border-style
  • Custom property inheritance now uses Rc<HashMap> with copy-on-write via Rc::make_mut. Only elements that set custom properties pay for a deep clone. Location: crates/style/src/types.rs in inherit_from() and apply_custom_property()
  • substitute_vars() returns Option<Vec<CssToken>> and logs warnings - could return structured Result<_, VarSubstitutionError> with specific error variants (CircularReference, UndefinedVariable, MaxDepthExceeded, InvalidSyntax) for better error handling

UA Stylesheet

The user agent stylesheet (crates/style/src/ua_stylesheet.rs) includes several CSS properties and selectors that are not yet implemented. These are silently ignored but should be implemented for full HTML rendering:

CSS Properties

  • font-weight - implemented in M5; <b>, <strong>, <th> render bold
  • font-style - implemented in M5; <em>, <i> render italic
  • font-family - implemented in M5; <code>, <pre> use monospace
  • text-decoration - needed for <a> links to render underlined
  • border-spacing - needed for table cell spacing
  • border-collapse - needed for table border rendering modes
  • border-style: inset - is needed but not implemented

Pseudo-class Selectors

  • :link - not implemented; a:link rules don't match any elements
  • :visited - parsed but always returns false; a:visited rules never match

Font Rendering (Milestone 5)

Weight class granularity

Font weights are bucketed into two classes: Regular (100-499) and Bold (500-900). Requests for intermediate weights like 300 (Light) or 600 (Semi-Bold) map to the nearest class. This is correct fallback behavior per CSS font matching but loses fidelity. Acceptable for the current Noto Sans font set which only provides Regular (400) and Bold (700). If more font weight variants are bundled in the future, the WeightClass enum in crates/fonts/src/font_db.rs should be expanded accordingly.

X-height approximation

X-height (height of lowercase 'x', used for vertical-align: middle) is approximated as 50% of ascent rather than read from the font's OS/2 table. ab_glyph does not expose the sxHeight field. This produces slightly inaccurate middle alignment for fonts with unusual x-height ratios. Location: crates/layout/src/text_measure.rs in font_metrics_styled().

Oblique maps to italic

FontStyle::Oblique silently maps to FontStyle::Italic during font resolution. True oblique (algorithmically slanted regular glyphs) differs from true italic (designed alternate letterforms). This matches common browser behavior when dedicated oblique faces are unavailable. Location: crates/fonts/src/font_db.rs in resolve().

Bundled font binary size

Five Noto Sans TTF files (~3.1 MB total) are embedded in the binary via include_bytes!(). This ensures deterministic cross-platform rendering but increases binary size. No system font discovery is performed. If binary size becomes a concern, consider lazy loading or system font fallback as a future enhancement.

No text shaping

Text is laid out character-by-character with kerning pairs (L-to-R only). There is no complex script shaping (ligatures, contextual alternates, bidi). A future milestone could add rustybuzz for HarfBuzz-compatible shaping.

No glyph cache

Glyph rasterization is not cached — the same glyph at the same size is re-rasterized on every paint. Font resolution is cached (in FontDb), but the rasterized alpha masks are not. For text-heavy pages with repeated characters, a glyph cache keyed on (glyph_id, size) would reduce redundant work.

Font shorthand not parsed

The CSS font shorthand property (e.g., font: bold 16px/1.2 Arial, sans-serif) is not parsed. Only the individual longhand properties font-weight, font-style, and font-family are supported.

Variable fonts not supported

Only static TTF font files are supported. Variable font axes (weight, width, slant) are not used even if present in the bundled font files.