Resolve fluid geometry bounds in logical space and let the runtime set the density from the buffer scale
Stock widgets size themselves with `Length::fluid`, whose auto-clamp `[0.7·px, 1.5·px]` is documented as logical px, yet `Canvas::resolve_geom` resolved it against the physical viewport and applied the bounds to the physical value. On any HiDPI surface whose physical short side exceeds 618 px (412 × 1.5) the cap engaged: a 1080 × 1920 phone at scale 2 got its geometry at 1.5 physical px per design px, that is 0.75 logical, while fonts, resolved by `font_px` against the logical viewport and scaled at raster time, kept growing to 2.62. Rows, paddings and icons came out at 60 % of their intended size with the text overflowing them; at scale 1 physical and logical coincide, so a winit session never showed it. `Length::resolve_physical` takes the buffer scale and multiplies `min_px` / `max_px` by it before clamping; `resolve_with_density` delegates to it with scale 1. `Canvas::resolve_geom` passes its `dpi_scale`, so every stock-widget geometry shares the surface factor of the fonts, and `overlays_reconcile` does the same for `OverlaySpec::size`, which had the same mix. A zero scale falls back to unscaled bounds. The event loop now calls `set_density( sf )` right before `App::on_scale_changed`, both on `configure` and on `scale_factor_changed` of the main surface, so `Length::dp( n )` means n logical px in every app without plumbing; an app wanting a DPI-derived density still overrides it from that callback, and crustace already sets the same value there. Two tests cover the clamp at scale 2 and the geometry/font parity on a 1080 × 2460 canvas.
This commit is contained in:
+18
-1
@@ -318,7 +318,7 @@ impl Canvas
|
||||
/// a `Length::dp` override follows the canvas the widget draws on.
|
||||
pub fn resolve_geom( &self, l: Length ) -> f32
|
||||
{
|
||||
l.resolve_with_density( self.viewport_layout(), Length::EM_BASE_DEFAULT, self.density() )
|
||||
l.resolve_physical( self.viewport_layout(), Length::EM_BASE_DEFAULT, self.density(), self.dpi_scale() )
|
||||
}
|
||||
|
||||
/// Resolve an explicit [`Length`] in **font** space: against
|
||||
@@ -960,6 +960,23 @@ mod viewport_tests
|
||||
set_widget_scaling( WidgetScaling::Fluid );
|
||||
}
|
||||
|
||||
#[ test ]
|
||||
fn geom_px_fluid_cap_is_logical_on_hidpi()
|
||||
{
|
||||
use crate::types::{ set_widget_scaling, WidgetScaling };
|
||||
let _g = crate::TEST_GLOBALS_LOCK.lock().unwrap_or_else( |e| e.into_inner() );
|
||||
set_widget_scaling( WidgetScaling::Fluid );
|
||||
|
||||
// 1080 × 2460 phone at buffer scale 2: geometry and fonts must share
|
||||
// the same surface factor (2.62 physical px per design px).
|
||||
let mut c = Canvas::new( 1080, 2460 );
|
||||
c.set_dpi_scale( 2.0 );
|
||||
let geom = c.geom_px( 48.0 );
|
||||
let font = c.font_px( 48.0 ) * 2.0;
|
||||
assert!( ( geom - 48.0 / 412.0 * 1080.0 ).abs() < 1e-2 );
|
||||
assert!( ( geom - font ).abs() < 1e-2 );
|
||||
}
|
||||
|
||||
#[ test ]
|
||||
fn canvas_density_overrides_process_density()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user