Skip to content

Conversation

valadaptive
Copy link
Contributor

@valadaptive valadaptive commented May 20, 2025

This implements @dfrg's proposal, since most people agreed it was the way forward.

If you don't want FontSizeRelative, I can remove it--MetricsRelative(1.0) is a sensible default that works at all font sizes. But some people leaned towards keeping FontSizeRelative.

The default line height has been changed from FontSizeRelative(1.2) (what I believe CSS uses) to MetricsRelative(1.0). This means a lot of the snapshot tests will change as well.

Copy link
Contributor

@nicoburns nicoburns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This generally looks good to me. A few minor points in comments, none of which I'd consider blocking.

My main question would be why so many (all?) of the snapshot tests have changed. Has the default line-height changed? In theory it seems like nothing here should change existing snapshots as we are only adding additional line-height options.

@valadaptive
Copy link
Contributor Author

Has the default line-height changed?

Yes, Chad suggested that in the original proposal. I can revert that if it touches too many tests.

@nicoburns
Copy link
Contributor

nicoburns commented May 20, 2025

Has the default line-height changed?

Yes, Chad suggested that in the original proposal. I can revert that if it touches too many tests.

I see. I don't feel particularly strongly about what the default is (I'm not planning to use the default anyway!). But could you document what the new default is and the previous default was (in the PR description), and perhaps add a note that this is why the snapshots have changed?

@valadaptive
Copy link
Contributor Author

Done.

Copy link
Contributor

@nicoburns nicoburns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies, I have a couple more changes to request:

  1. A changelog entry:
    • Should note the introduction of the Lineheight enum
    • Should note the change of default line-height
  2. Suggestions in comments are optional but recommended.

Comment on lines 492 to 501
LineHeight(value) => match (self.line_height, *value) {
(crate::LineHeight::MetricsRelative(a), crate::LineHeight::MetricsRelative(b))
| (
crate::LineHeight::FontSizeRelative(a),
crate::LineHeight::FontSizeRelative(b),
)
| (crate::LineHeight::Absolute(a), crate::LineHeight::Absolute(b)) => {
nearly_eq(a, b)
}
_ => false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of notes on this one:

  • Consider importing crate::LineHeight at the top of the file (partly for consistency with surrounding code, partly because I think the match would format better like that)
  • Consider making this a method on LineHeight.

Comment on lines 515 to 523
line_height: match self.line_height {
crate::LineHeight::MetricsRelative(value) => {
crate::LayoutLineHeight::MetricsRelative(value)
}
crate::LineHeight::FontSizeRelative(value) => {
crate::LayoutLineHeight::Absolute(value * self.font_size)
}
crate::LineHeight::Absolute(value) => crate::LayoutLineHeight::Absolute(value),
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as nearly_eq above (considering use crate::LineHeight + make this a method).

@valadaptive valadaptive force-pushed the line-height-styles branch from d7dfe8b to fc13ebb Compare May 20, 2025 12:56
Copy link
Member

@xStrom xStrom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to see absolute line height support moving forward!

I have a few inline comments.

On a more general note, this PR really shows that using default line height for snapshot tests is a bad idea. This type of PR would benefit greatly from zero changed snapshots. Anyway, the actual line height tests did manually specify a line height and still work, so the validity is just hidden in noise. I would prefer setting the old default line height as the default choice for tests to reduce the snapshot churn. However it's not a blocker.

@@ -523,7 +523,6 @@ impl<'a, B: Brush> BreakLines<'a, B> {
// Compute the run's vertical metrics
line.metrics.ascent = line.metrics.ascent.max(run.metrics.ascent);
line.metrics.descent = line.metrics.descent.max(run.metrics.descent);
line.metrics.leading = line.metrics.leading.max(run.metrics.leading);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't we calculating the line's leading any more? Unclear to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I probably should've mentioned this in the PR itself so more people could take a look at it. I believe that this is dead code now, since leading is always calculated here, and both of the removed leading-calculation lines should flow into that code unconditionally.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks and I think you're correct. Good catch!

Copy link
Member

@xStrom xStrom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This moves us forward nicely, thanks for your continued efforts!

@dfrg
Copy link
Collaborator

dfrg commented May 20, 2025

This moves us forward nicely, thanks for your continued efforts!

+1, much appreciated!

@valadaptive valadaptive force-pushed the line-height-styles branch 2 times, most recently from e25ca63 to dbb2d58 Compare May 21, 2025 01:37
@valadaptive valadaptive force-pushed the line-height-styles branch from dbb2d58 to c48e094 Compare May 21, 2025 01:38
@valadaptive
Copy link
Contributor Author

Updated the tests to use a default line height of FontSizeRelative(1.0).

One last (semi-related) thing: it seems the default line height used to be 1.2 if you used the TreeStyleBuilder, but 1.0 if you used the RangedStyleBuilder. This is seemingly due to a discrepancy between the Default impl for TextStyle and the one for ResolvedStyle.

In the future, we should probably find a way to avoid introducing further discrepancies of that sort, but for now I've listed it in the changelog. Only a couple tests used TreeStyleBuilder, and their snapshots now differ.

@valadaptive valadaptive requested a review from xStrom May 21, 2025 01:50
@nicoburns
Copy link
Contributor

Only a couple tests used TreeStyleBuilder, and their snapshots now differ.

Perhaps we ought to set the line-height explicitly in those specific tests?

Copy link
Member

@DJMcNab DJMcNab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code changes look really good. The only actionable changes are some docs/examples suggestions, which should be straightforward to implement.

Copy link
Member

@xStrom xStrom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like some commits got lost when you force pushed without pulling.

The previous situation of the different builders having different line height defaults is crazy, glad that's no longer the case.

Great to also see less snapshot churn here. We might want to eventually change the test default, but then it can happen independently of any code changes.

valadaptive and others added 9 commits May 21, 2025 19:26
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
Co-authored-by: Kaur Kuut <strom@nevermore.ee>
Co-authored-by: Kaur Kuut <strom@nevermore.ee>
Co-authored-by: Kaur Kuut <strom@nevermore.ee>
@valadaptive
Copy link
Contributor Author

Whoops--I need to get into the habit of using --force-with-lease instead of --force.

I've implemented most of the suggestions, and expanded the doc comments for the LineHeight type quite a bit. I've also implemented Default for LineHeight.

I'd rather update the few tests whose snapshots changed; I can visually confirm they still pass, and it's not a big deal since there's not as much snapshot churn as updating the entire test suite would be.

@valadaptive valadaptive requested review from xStrom and DJMcNab May 22, 2025 00:03
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like since this changes the default, it's okay to update the test to its prior equivalent rather than just letting it change arbitrarily for this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree here - this PR is fixing the bug that TreeBuilder had a different default, and so is updating the snapshots which used that.

Copy link
Member

@DJMcNab DJMcNab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor docs things, none of which are blocking.
I have tested this out in Vello Editor, and the new default works well.

Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree here - this PR is fixing the bug that TreeBuilder had a different default, and so is updating the snapshots which used that.

Copy link
Member

@xStrom xStrom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work, thanks!

Comment on lines +63 to +67
impl Default for LineHeight {
fn default() -> Self {
Self::MetricsRelative(1.0)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great👌

xStrom and others added 3 commits May 22, 2025 14:33
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
@valadaptive
Copy link
Contributor Author

I think I've addressed all the review comments (fingers crossed). Apologies if I've missed any.

@valadaptive valadaptive added this pull request to the merge queue May 24, 2025
Merged via the queue into linebender:main with commit 3a501b8 May 24, 2025
24 checks passed
@valadaptive valadaptive deleted the line-height-styles branch May 24, 2025 02:51
@xStrom xStrom added this to the 0.5 Release milestone Jun 1, 2025
github-merge-queue bot pushed a commit that referenced this pull request Jul 7, 2025
The two builders (ranged/tree) use different sources of truth to achieve
a default style. This is already a bad idea, as evidenced by them having
a [different default line
height](#362 (comment))
until very recently. It gets even worse, because the ranged builder uses
`ResolvedStyle::default()` which means it has a dummy font and doesn't
respect scale.

This PR makes both builders use a single source of truth - a `TextStyle`
which then gets resolved.

This means that we can confidently change our default style in only one
place - the `TextStyle::default` method. Those default values then also
get properly resolved according to available fonts, scale, etc.

Note that I didn't change the public API on purpose. I do think that
being able to immediately provide a custom root style to the ranged
builder, like it is possible with the tree builder, is probably worth
doing. However, I want to do any potential public API changes as a
focused follow-up PR.

The `PlainEditor::ime_cursor_area` method needed a slight modification
as well. It was depending on `ResolvedStyle::default()` for a font size
based calculation. That did not respect scale, so I fixed it by just
keeping track of the font size that was provided to the `PlainEditor`
constructor.

I replaced the custom `ResolvedStyle::default()` implementation with a
simple derive. The only remaining non-derivable part was setting the
font size to 16. Given that it doesn't respect scale, that custom
implementation just provides a false sense of utility. A zero font size
is perfectly fine for a state clearing default, which is how we're still
using it.

I also added a test to ensure that the default styles remain in sync
between the different builders.
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.

6 participants