render: pre-scale font_line_metrics by dpi_scale
Some checks failed
CI / build + test (push) Has been cancelled
CI / cargo audit (push) Has been cancelled

The text pipeline works in physical pixels: measure_text and draw_text multiply the font size by dpi_scale internally, and the layout rects widgets receive are physical too. font_line_metrics was the one exception — it returned line metrics at the logical size — so the line height and ascent the text and rich_text widgets derive from it came out divided by the surface scale factor. On any output with a scale other than 1 (e.g. a 200% display, or any fractional setting the compositor rounds up to buffer scale 2), wrapped lines overlapped, baselines sat too high, and preferred_size reported half the real text height.
Scale the size handed to horizontal_line_metrics by dpi_scale in both the Canvas wrapper and the GLES backend, matching the already pre-scaled font_metrics. At scale 1 the behaviour is unchanged.
This commit is contained in:
2026-08-11 22:04:22 +02:00
parent 98c82385c7
commit adbbc0248b
2 changed files with 6 additions and 5 deletions

View File

@@ -772,11 +772,11 @@ impl GlesCanvas
self.font_for_char( ch ).metrics( ch, size * self.dpi_scale ) self.font_for_char( ch ).metrics( ch, size * self.dpi_scale )
} }
/// Horizontal line metrics of the default font at `size` px (`None` if the /// Horizontal line metrics of the default font at `size` logical px (`None`
/// font lacks them). Not pre-scaled by `dpi_scale`. /// if the font lacks them), pre-scaled by `dpi_scale`.
pub fn font_line_metrics( &self, size: f32 ) -> Option<LineMetrics> pub fn font_line_metrics( &self, size: f32 ) -> Option<LineMetrics>
{ {
self.font.horizontal_line_metrics( size ) self.font.horizontal_line_metrics( size * self.dpi_scale )
} }
/// Resize the FBO and viewport. The previous color attachment is freed and /// Resize the FBO and viewport. The previous color attachment is freed and

View File

@@ -529,10 +529,11 @@ impl Canvas
self.font().metrics( ch, size * self.dpi_scale() ) self.font().metrics( ch, size * self.dpi_scale() )
} }
/// Convenience wrapper around `font().horizontal_line_metrics(...)`. /// Convenience wrapper around `font().horizontal_line_metrics(...)`,
/// pre-scaled by `dpi_scale` like [`Self::font_metrics`].
pub fn font_line_metrics( &self, size: f32 ) -> Option<LineMetrics> pub fn font_line_metrics( &self, size: f32 ) -> Option<LineMetrics>
{ {
self.font().horizontal_line_metrics( size ) self.font().horizontal_line_metrics( size * self.dpi_scale() )
} }
pub fn resize( &mut self, width: u32, height: u32 ) pub fn resize( &mut self, width: u32, height: u32 )