render, types, ci: resolution-time dp with per-canvas density, bounded GLES image cache, clippy gate, backend capability matrix
Length::dp no longer collapses to absolute pixels at construction: the design value travels in a new LengthBase::Dp variant and the density multiplication happens when the length is resolved. Previously dp( n ) baked in whatever density() returned at view-build time, so correctness across output changes depended on the view being rebuilt after set_density and in that order; now a density change is picked up by the very next paint with no reconstruction. Length::resolve keeps its signature (process density), and the new Length::resolve_with_density takes an explicit factor. dp becomes const in the bargain. Density also becomes overridable per canvas, the first step towards surface-local responsive state. SoftwareCanvas and GlesCanvas carry a density: Option<f32> analogous to the layout_viewport introduced for sub-canvas fluid resolution: None means "use the process global", Canvas::set_density pins a local factor, and sub-canvases inherit it. All canvas-routed resolution honours it — geom_px / font_px for stock-widget design pixels, and the new Canvas::resolve_geom / resolve_font for explicit Length values, which every widget now uses in place of the raw l.resolve( canvas.viewport_layout(), EM ) pattern (row, column, wrap_grid, spacer, container, separator, button, text, rich_text, text_edit, list_item, vslider, image, and the container draw path). Overlay sizing keeps resolving against the main surface with the global density, which is what it describes. New tests cover explicit-density resolution, resolution-time application, the local-over-global override and sub-canvas inheritance. The GLES image texture cache is now bounded. It was content-keyed but unbounded and never evicted, so a stream of distinct buffers — a photo carousel, video thumbnails — grew GPU memory for the lifetime of the canvas. The cache now tracks an estimated byte total (RGBA8, w × h × 4) against a 32 MiB budget and evicts least-recently-drawn textures on insert; the most recent entry is never evicted, so a single texture larger than the whole budget still draws and simply owns the cache until replaced. Drop-time cleanup is unchanged: drain deletes whatever the map holds. CI gains a Clippy step (workspace, all targets, test-support, -D warnings) sharing the build cache of the test job, with make clippy mirroring the invocation locally and CONTRIBUTING listing it. Run make clippy locally before pushing the first time — the gate has not seen the tree yet and pre-existing lints will fail CI until addressed. docs/backends.md formalises the software/GLES capability matrix that was previously scattered across per-method rustdoc: parity set (fills, strokes, text, images, paths, path clips), graceful degradations on software (flat-fill gradients, no shadows, no backdrop blur, hard bottom edge), GPU-only features (external textures), the shared Oklab-fallback limitation, and the cross-backend blit panic. Linked from README, onboarding and architecture's known-gaps list, which now states the parity gaps explicitly. The dp/density prose in architecture.md, lib.rs and the Length rustdoc is updated for resolution-time semantics and the per-canvas override.
This commit is contained in:
@@ -45,7 +45,7 @@
|
||||
//! method — see the module's own doc for when to use the guards
|
||||
//! and when not to.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{ HashMap, VecDeque };
|
||||
use std::sync::Arc;
|
||||
|
||||
use fontdue::Font;
|
||||
@@ -157,6 +157,11 @@ pub struct GlesCanvas
|
||||
/// the same inside offscreen content (scroll viewports, clip layers)
|
||||
/// as outside it.
|
||||
pub( crate ) layout_viewport: Option<( f32, f32 )>,
|
||||
/// Canvas-local pixel density for `Dp` resolution, when the owning
|
||||
/// surface sits on an output whose density differs from the process
|
||||
/// [`crate::density`]. `None` falls back to the global. Inherited by
|
||||
/// sub-canvases.
|
||||
pub( crate ) density: Option<f32>,
|
||||
pub global_alpha: f32,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
@@ -349,8 +354,13 @@ pub struct GlesCanvas
|
||||
// frame (the cache would happily serve the stale texture).
|
||||
// Content-keying tolerates that case at the cost of one
|
||||
// `DefaultHasher` pass over the bytes per draw call — fast for
|
||||
// any reasonable icon size.
|
||||
// any reasonable icon size. Bounded by `image.rs`'s
|
||||
// `IMAGE_CACHE_MAX_BYTES` with LRU eviction.
|
||||
image_cache: HashMap<(u32, u32, u64), (glow::Texture, u32, u32)>,
|
||||
// LRU order of `image_cache` keys, least-recent at the front.
|
||||
image_cache_lru: VecDeque<(u32, u32, u64)>,
|
||||
// Estimated GPU bytes held by `image_cache` (RGBA8: w × h × 4).
|
||||
image_cache_bytes: usize,
|
||||
|
||||
// Gradient LUT cache: FNV-ish hash of the 512×RGBA8 LUT bytes → texture.
|
||||
// Gradients are theme-derived and constant across frames; caching avoids
|
||||
|
||||
Reference in New Issue
Block a user