Skip to content

Add root-level styles to Layout - #1

Draft
nicoburns wants to merge 4 commits into
mainfrom
devin/1784943663-root-level-styles
Draft

Add root-level styles to Layout#1
nicoburns wants to merge 4 commits into
mainfrom
devin/1784943663-root-level-styles

Conversation

@nicoburns

@nicoburns nicoburns commented Jul 25, 2026

Copy link
Copy Markdown
Member

Summary

Adds persistent root-level styles to Layout (linebender#291), so the root style is no longer discarded after building and its font metrics are available even for empty layouts (fixes the invisible-cursor case from linebender#391).

New public type nesting a regular TextStyle:

pub struct RootStyle<'family, 'settings, B: Brush> {
    pub style: TextStyle<'family, 'settings, B>,
    /// Opt-in CSS-like strut: floor every line's metrics by the root font's metrics.
    pub strut: bool,
}
impl From<TextStyle<..>> for RootStyle<..> // strut: false

All three builders now take it (breaking change):

ranged_builder(fcx, text, scale, quantize, root_style: &RootStyle<B>)
style_run_builder(.., root_style: &RootStyle<B>)
tree_builder(fcx, scale, quantize, root_style: &RootStyle<B>) // was &TextStyle

The root style is resolved once, stored on LayoutData, and exposed via:

Layout::root_style() -> &Style<B>
Layout::root_font_size() / root_line_height() -> f32
Layout::root_font_metrics() -> &FontMetrics

Key mechanics:

  • FontMetrics::from_font(font, size, synthesis, variations) (new in parley_engine) computes metrics directly via skrifa without shaping; root metrics are resolved with a fontique query using the root style's family/weight/width/style/variations.
  • Empty layouts no longer shape a fake " " to get cursor metrics — empty layouts and trailing empty lines (after a final newline) now derive their line-box/content-box metrics from the root font metrics and root line height.
  • RangedBuilder::push_default still updates the layout's root style, preserving existing semantics.
  • With strut: true, each line's ascent/descent/line-height are floored by the root font's metrics (CSS strut behavior); default remains unchanged.
  • Fixed an underflow in analysis when a zero-length style range carried a non-default word_break.

All builder call sites (examples, benches, editor, tests) migrated; new tests cover empty-layout metrics, trailing empty lines, strut flooring, and builder equivalence of the new root fields.

Link to Devin session: https://app.devin.ai/sessions/84c19f0ab14045d6a472af0934ded64c
Requested by: @nicoburns


Devin Review

Status Commit
⚪ Not started

Run Devin Review

Open in Devin Review (Staging)

@nicoburns nicoburns self-assigned this Jul 25, 2026
@devin-ai-integration

Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

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