A Length::dp font size keeps its logical size on a scaled output instead of growing with the scale
On a 14.1" 2560x1440 laptop, where forge picks a 2.25 output scale and ltk draws at buffer scale 3, the title of every settings screen but the first came out about three times its design size, while on a 1920x1080 laptop at scale 1 the same title was smaller than the 28 px heading of the home screen. That title is a `list_item` with `.font_size( Length::widget( 20.0 ) )`, which in `WidgetScaling::Physical` is `Length::dp( 20.0 )`. `Canvas::resolve_font` resolved a `Dp` length with the canvas' density, which the runtime sets to the output scale, and returned it as a font size. Font sizes are logical: the raster path multiplies them by `dpi_scale`. A `Dp` font size was therefore scaled twice, 20 × 3 = 60 logical px and 180 physical, against 20 at scale 1. Geometry did not have the problem, because `resolve_geom` returns physical pixels that nothing scales again, and neither did a stock widget without an override, because `font_px` already divided by `dpi_scale` in Physical mode. The same `dp` value thus gave one size through `font_px` and another through an explicit override. `resolve_font` now resolves `Dp` with `density / dpi_scale`, so that `× dpi_scale` at raster yields `n × density` physical pixels, the same as `resolve_geom` gives the same length. Pixel, viewport and fluid lengths are untouched, since they do not depend on the density. The Physical branch of `font_px` now delegates to `resolve_font( Length::dp( design_px ) )`, which is the formula it carried on its own. Every caller of `resolve_font` is affected: the `font_size` overrides of `button`, `text_edit` and `list_item`, and the `size` of `text` and `rich_text` when given a `Dp` or, in Physical mode, a `Length::widget`. At scale 1 nothing changes. The new test `dp_font_matches_dp_geometry_on_hidpi` checks at scale 3 that a 20 dp font resolves to 20 logical px, equals `font_px( 20 )` for `Length::widget`, and times the scale equals the same length resolved as geometry.
This commit is contained in:
+23
-5
@@ -336,10 +336,12 @@ impl Canvas
|
||||
/// [`Self::viewport_logical`], with this canvas' [`Self::density`],
|
||||
/// times the global accessibility [`crate::text_scale`]. Counterpart
|
||||
/// of [`Self::resolve_geom`] for font sizes, which are handed to the
|
||||
/// raster path pre-`dpi_scale`.
|
||||
/// raster path pre-`dpi_scale`, so `Dp` uses `density / dpi_scale`.
|
||||
pub fn resolve_font( &self, l: Length ) -> f32
|
||||
{
|
||||
l.resolve_with_density( self.viewport_logical(), Length::EM_BASE_DEFAULT, self.density() )
|
||||
let scale = self.dpi_scale();
|
||||
let scale = if scale > 0.0 { scale } else { 1.0 };
|
||||
l.resolve_with_density( self.viewport_logical(), Length::EM_BASE_DEFAULT, self.density() / scale )
|
||||
* crate::types::text_scale()
|
||||
}
|
||||
|
||||
@@ -375,9 +377,7 @@ impl Canvas
|
||||
}
|
||||
WidgetScaling::Physical =>
|
||||
{
|
||||
let scale = self.dpi_scale();
|
||||
let scale = if scale > 0.0 { scale } else { 1.0 };
|
||||
design_px * self.density() / scale * crate::types::text_scale()
|
||||
self.resolve_font( Length::dp( design_px ) )
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1148,6 +1148,24 @@ mod viewport_tests
|
||||
set_density( 1.0 );
|
||||
set_widget_scaling( WidgetScaling::Fluid );
|
||||
}
|
||||
|
||||
#[ test ]
|
||||
fn dp_font_matches_dp_geometry_on_hidpi()
|
||||
{
|
||||
use crate::types::{ set_widget_scaling, set_density, WidgetScaling };
|
||||
let _g = crate::TEST_GLOBALS_LOCK.lock().unwrap_or_else( |e| e.into_inner() );
|
||||
|
||||
set_widget_scaling( WidgetScaling::Physical );
|
||||
set_density( 3.0 );
|
||||
let mut c = Canvas::new( 2560, 1440 );
|
||||
c.set_dpi_scale( 3.0 );
|
||||
assert_eq!( c.resolve_font( Length::dp( 20.0 ) ), 20.0 );
|
||||
assert_eq!( c.resolve_font( Length::widget( 20.0 ) ), c.font_px( 20.0 ) );
|
||||
assert_eq!( c.resolve_font( Length::dp( 20.0 ) ) * 3.0, c.resolve_geom( Length::dp( 20.0 ) ) );
|
||||
|
||||
set_density( 1.0 );
|
||||
set_widget_scaling( WidgetScaling::Fluid );
|
||||
}
|
||||
}
|
||||
|
||||
#[ cfg( test ) ]
|
||||
|
||||
Reference in New Issue
Block a user