From 0da6b87b5f4866323059caeeb55c51de0cfc9293 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 26 Mar 2026 16:12:23 +0100 Subject: [PATCH] :tada: Allow get param to set antialias threshold --- frontend/src/app/render_wasm/api.cljs | 12 ++++++++++++ render-wasm/src/main.rs | 9 +++++++++ render-wasm/src/render.rs | 9 +++++++-- render-wasm/src/render/grid_layout.rs | 10 ++++++++-- render-wasm/src/render/options.rs | 21 ++++++++++++++++++++- render-wasm/src/render/ui.rs | 16 ++++++++++++++-- render-wasm/src/shapes.rs | 6 ++---- 7 files changed, 72 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 0254324696..a8b0b69cf8 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -23,6 +23,7 @@ [app.common.uuid :as uuid] [app.config :as cf] [app.main.refs :as refs] + [app.main.router :as rt] [app.main.store :as st] [app.main.ui.shapes.text] [app.main.worker :as mw] @@ -1410,6 +1411,15 @@ (contains? cf/flags :render-wasm-info) (bit-or 2r00000000000000000000000000001000))) +(defn- wasm-aa-threshold-from-route-params + "Reads optional `aa_threshold` query param from the router" + [] + (when-let [raw (let [p (rt/get-params @st/state)] + (:aa_threshold p))] + (let [n (if (string? raw) (js/parseFloat raw) raw)] + (when (and (number? n) (not (js/isNaN n)) (pos? n)) + n)))) + (defn set-canvas-size [canvas] (let [width (or (.-clientWidth ^js canvas) (.-width ^js canvas)) @@ -1445,6 +1455,8 @@ ;; Initialize Wasm Render Engine (h/call wasm/internal-module "_init" (/ (.-width ^js canvas) dpr) (/ (.-height ^js canvas) dpr)) (h/call wasm/internal-module "_set_render_options" flags dpr) + (when-let [t (wasm-aa-threshold-from-route-params)] + (h/call wasm/internal-module "_set_antialias_threshold" t)) ;; Set browser and canvas size only after initialization (h/call wasm/internal-module "_set_browser" browser) diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index cff52ad821..42a8c46671 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -145,6 +145,15 @@ pub extern "C" fn set_render_options(debug: u32, dpr: f32) -> Result<()> { Ok(()) } +#[no_mangle] +#[wasm_error] +pub extern "C" fn set_antialias_threshold(threshold: f32) -> Result<()> { + with_state_mut!(state, { + state.render_state_mut().set_antialias_threshold(threshold); + }); + Ok(()) +} + #[no_mangle] #[wasm_error] pub extern "C" fn set_canvas_background(raw_color: u32) -> Result<()> { diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 3b8e353213..133df97cf0 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -617,6 +617,10 @@ impl RenderState { Ok(()) } + pub fn set_antialias_threshold(&mut self, value: f32) { + self.options.set_antialias_threshold(value); + } + pub fn set_background_color(&mut self, color: skia::Color) { self.background_color = color; } @@ -798,7 +802,8 @@ impl RenderState { }); } - let antialias = shape.should_use_antialias(self.get_scale()); + let antialias = + shape.should_use_antialias(self.get_scale(), self.options.antialias_threshold); let fast_mode = self.options.is_fast_mode(); let has_nested_fills = self .nested_fills @@ -2164,7 +2169,7 @@ impl RenderState { } if let Some(clips) = clip_bounds.as_ref() { - let antialias = element.should_use_antialias(scale); + let antialias = element.should_use_antialias(scale, self.options.antialias_threshold); self.surfaces.canvas(target_surface).save(); for (bounds, corners, transform) in clips.iter() { if target_surface == SurfaceId::Export { diff --git a/render-wasm/src/render/grid_layout.rs b/render-wasm/src/render/grid_layout.rs index 9f5067469e..18d1d7be60 100644 --- a/render-wasm/src/render/grid_layout.rs +++ b/render-wasm/src/render/grid_layout.rs @@ -4,14 +4,20 @@ use crate::shapes::modifiers::grid_layout::grid_cell_data; use crate::shapes::Shape; use crate::state::ShapesPoolRef; -pub fn render_overlay(zoom: f32, canvas: &skia::Canvas, shape: &Shape, shapes: ShapesPoolRef) { +pub fn render_overlay( + zoom: f32, + antialias_threshold: f32, + canvas: &skia::Canvas, + shape: &Shape, + shapes: ShapesPoolRef, +) { let cells: Vec> = grid_cell_data(shape, shapes, true); let bounds = shape.bounds(); let mut paint = skia::Paint::default(); paint.set_style(skia::PaintStyle::Stroke); paint.set_color(skia::Color::from_rgb(255, 111, 224)); - paint.set_anti_alias(shape.should_use_antialias(zoom)); + paint.set_anti_alias(shape.should_use_antialias(zoom, antialias_threshold)); paint.set_stroke_width(1.0 / zoom); diff --git a/render-wasm/src/render/options.rs b/render-wasm/src/render/options.rs index 9505d0b254..7b1a49f540 100644 --- a/render-wasm/src/render/options.rs +++ b/render-wasm/src/render/options.rs @@ -4,11 +4,24 @@ const PROFILE_REBUILD_TILES: u32 = 0x02; const TEXT_EDITOR_V3: u32 = 0x04; const SHOW_WASM_INFO: u32 = 0x08; -#[derive(Debug, Copy, Clone, PartialEq, Default)] +#[derive(Debug, Copy, Clone, PartialEq)] pub struct RenderOptions { pub flags: u32, pub dpr: Option, fast_mode: bool, + /// Minimum on-screen size (CSS px at 1:1 zoom) above which vector antialiasing is enabled. + pub antialias_threshold: f32, +} + +impl Default for RenderOptions { + fn default() -> Self { + Self { + flags: 0, + dpr: None, + fast_mode: false, + antialias_threshold: 15.0, + } + } } impl RenderOptions { @@ -40,4 +53,10 @@ impl RenderOptions { pub fn show_wasm_info(&self) -> bool { self.flags & SHOW_WASM_INFO == SHOW_WASM_INFO } + + pub fn set_antialias_threshold(&mut self, value: f32) { + if value.is_finite() && value > 0.0 { + self.antialias_threshold = value; + } + } } diff --git a/render-wasm/src/render/ui.rs b/render-wasm/src/render/ui.rs index 7d6436fbc8..bb7cc72c0f 100644 --- a/render-wasm/src/render/ui.rs +++ b/render-wasm/src/render/ui.rs @@ -23,7 +23,13 @@ pub fn render(render_state: &mut RenderState, shapes: ShapesPoolRef) { if let Some(id) = show_grid_id { if let Some(shape) = shapes.get(&id) { - grid_layout::render_overlay(zoom, canvas, shape, shapes); + grid_layout::render_overlay( + zoom, + render_state.options.antialias_threshold, + canvas, + shape, + shapes, + ); } } @@ -50,7 +56,13 @@ pub fn render(render_state: &mut RenderState, shapes: ShapesPoolRef) { } if let Some(shape) = shapes.get(&shape.id) { - grid_layout::render_overlay(zoom, canvas, shape, shapes); + grid_layout::render_overlay( + zoom, + render_state.options.antialias_threshold, + canvas, + shape, + shapes, + ); } } diff --git a/render-wasm/src/shapes.rs b/render-wasm/src/shapes.rs index dc129e8695..22f8cf3529 100644 --- a/render-wasm/src/shapes.rs +++ b/render-wasm/src/shapes.rs @@ -56,7 +56,6 @@ use crate::math::{self, Bounds, Matrix, Point}; use crate::state::ShapesPoolRef; const MIN_VISIBLE_SIZE: f32 = 2.0; -const ANTIALIAS_THRESHOLD: f32 = 15.0; const MIN_STROKE_WIDTH: f32 = 0.001; #[derive(Debug, Clone, PartialEq)] @@ -768,9 +767,8 @@ impl Shape { extrect.width() * scale < MIN_VISIBLE_SIZE && extrect.height() * scale < MIN_VISIBLE_SIZE } - pub fn should_use_antialias(&self, scale: f32) -> bool { - self.selrect.width() * scale > ANTIALIAS_THRESHOLD - || self.selrect.height() * scale > ANTIALIAS_THRESHOLD + pub fn should_use_antialias(&self, scale: f32, threshold: f32) -> bool { + self.selrect.width() * scale > threshold || self.selrect.height() * scale > threshold } pub fn calculate_bounds(&self, apply_transform: bool) -> Bounds {