From a01c4e1bad37c02336352a056dc42c1aa44386fa Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Mon, 15 Jun 2026 11:45:21 +0200 Subject: [PATCH] :bug: Fix scale viewer WASM canvas by devicePixelRatio like workspace --- frontend/src/app/main/render_viewer_wasm.cljs | 40 ++++++++++++++----- .../src/app/main/ui/viewer/viewport_wasm.cljs | 9 ++++- frontend/src/app/render_wasm/api.cljs | 30 +++++++------- 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/frontend/src/app/main/render_viewer_wasm.cljs b/frontend/src/app/main/render_viewer_wasm.cljs index 7de082b675..096a78cd71 100644 --- a/frontend/src/app/main/render_viewer_wasm.cljs +++ b/frontend/src/app/main/render_viewer_wasm.cljs @@ -12,6 +12,7 @@ [app.render-wasm.wasm :as wasm] [app.util.dom :as dom] [app.util.timers :as ts] + [app.util.webapi :as webapi] [goog.events :as events] [promesa.core :as p] [rumext.v2 :as mf])) @@ -30,14 +31,16 @@ (atom {:os-canvas nil :page-key nil :canvas-w 0 - :canvas-h 0})) + :canvas-h 0 + :dpr 1})) (defn- reset-viewer-snapshot! [] (reset! viewer-snapshot {:os-canvas nil :page-key nil :canvas-w 0 - :canvas-h 0})) + :canvas-h 0 + :dpr 1})) (defn- draw-bitmap! [canvas os-canvas object-id vis-w vis-h finish] @@ -135,9 +138,12 @@ (resolve nil)) vis-w (.-width canvas) vis-h (.-height canvas) + dpr (wasm.api/get-dpr) snap @viewer-snapshot same-page? (and (some? page-key) (identical? page-key (:page-key snap))) - same-size? (and (= vis-w (:canvas-w snap)) (= vis-h (:canvas-h snap))) + same-size? (and (= vis-w (:canvas-w snap)) + (= vis-h (:canvas-h snap)) + (= dpr (:dpr snap))) os (:os-canvas snap) do-render! (fn [os-canvas] (viewer-do-render! page-objects canvas os-canvas object-id @@ -151,7 +157,7 @@ (do (when-not same-size? (wasm.api/resize-offscreen-canvas! os vis-w vis-h) - (swap! viewer-snapshot assoc :canvas-w vis-w :canvas-h vis-h)) + (swap! viewer-snapshot assoc :canvas-w vis-w :canvas-h vis-h :dpr dpr)) (do-render! os)) (let [os-canvas (js/OffscreenCanvas. vis-w vis-h)] (when (wasm.api/initialized?) @@ -162,7 +168,8 @@ {:os-canvas os-canvas :page-key page-key :canvas-w vis-w - :canvas-h vis-h}) + :canvas-h vis-h + :dpr dpr}) (wasm.api/initialize-viewport page-objects scale size :background-opacity 0 @@ -192,11 +199,22 @@ (let [key (events/listen section "scroll" (fn [_] (sync!)))] #(events/unlistenByKey key)))))))) +(defn- use-viewer-dpr-key + "Bump a counter when browser zoom changes devicePixelRatio so WASM canvases + are resized like the workspace viewport." + [] + (let [dpr-key (mf/use-state 0)] + (mf/use-effect + (mf/deps []) + (fn [] + (webapi/on-dpr-change (fn [_] (swap! dpr-key inc))))) + @dpr-key)) + (defn- use-viewer-wasm-layers! [page-id page-objects size scale frame-id not-fixed-ref fixed-ref - not-fixed-include-ids fixed-include-ids fixed-clear-fills-ids] + not-fixed-include-ids fixed-include-ids fixed-clear-fills-ids dpr-key] (mf/use-layout-effect - (mf/deps page-id page-objects size scale frame-id + (mf/deps page-id page-objects size scale frame-id dpr-key not-fixed-include-ids fixed-include-ids fixed-clear-fills-ids) (fn [] (when (get page-objects frame-id) @@ -236,6 +254,8 @@ not-fixed-ref fixed-ref fixed-scroll-layer-ref not-fixed-include-ids fixed-include-ids fixed-clear-fills-ids] (use-fixed-scroll-sync! (some? fixed-scroll-layer-ref) fixed-scroll-layer-ref) - (use-viewer-wasm-layers! page-id page-objects size scale frame-id - not-fixed-ref fixed-ref - not-fixed-include-ids fixed-include-ids fixed-clear-fills-ids)) + (let [dpr-key (use-viewer-dpr-key)] + (use-viewer-wasm-layers! page-id page-objects size scale frame-id + not-fixed-ref fixed-ref + not-fixed-include-ids fixed-include-ids fixed-clear-fills-ids + dpr-key))) diff --git a/frontend/src/app/main/ui/viewer/viewport_wasm.cljs b/frontend/src/app/main/ui/viewer/viewport_wasm.cljs index 50f97f5cbf..02b9b1c831 100644 --- a/frontend/src/app/main/ui/viewer/viewport_wasm.cljs +++ b/frontend/src/app/main/ui/viewer/viewport_wasm.cljs @@ -12,12 +12,17 @@ [app.main.render-viewer-wasm :as rwv] [app.main.ui.viewer.shapes :as shapes] [app.main.ui.viewer.viewport-common :as vpc] + [app.render-wasm.api :as wasm.api] [rumext.v2 :as mf])) (defn- canvas-dimensions + "Physical canvas pixels (CSS layout size × DPR), matching the workspace WASM path." [scale size] - {:width (js/Math.round (* scale (:base-width size))) - :height (js/Math.round (* scale (:base-height size)))}) + (let [css-w (js/Math.round (* scale (:base-width size))) + css-h (js/Math.round (* scale (:base-height size))) + dpr (wasm.api/get-dpr)] + {:width (js/Math.round (* css-w dpr)) + :height (js/Math.round (* css-h dpr))})) (mf/defc wasm-hotspots-svg* [{:keys [vbox size class prepared prepared-all prepared-frame shape-filter]}] diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index a1a0a2f6bf..03b399c02f 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -1920,15 +1920,6 @@ (h/call wasm/internal-module "_set_view_end") (reset! view-interaction-active? false))) -(defn resize-offscreen-canvas! - "Resize a persistent OffscreenCanvas to new physical-pixel dimensions and - update the WASM render surfaces accordingly (via `_resize_viewbox`). The - design state (shape pool) is preserved so `set-objects` is not needed again." - [canvas new-physical-w new-physical-h] - (set! (.-width canvas) new-physical-w) - (set! (.-height canvas) new-physical-h) - (resize-viewbox (/ new-physical-w dpr) (/ new-physical-h dpr))) - (defn- debug-flags [] (cond-> 0 @@ -1939,6 +1930,22 @@ (contains? cf/flags :render-wasm-info) (bit-or 2r00000000000000000000000000001000))) +(defn set-render-options! + "Updates WASM render options with a new DPR value." + [new-dpr] + (h/call wasm/internal-module "_set_render_options" (debug-flags) new-dpr)) + +(defn resize-offscreen-canvas! + "Resize a persistent OffscreenCanvas to new physical-pixel dimensions and + update the WASM render surfaces accordingly (via `_resize_viewbox`). The + design state (shape pool) is preserved so `set-objects` is not needed again." + [canvas new-physical-w new-physical-h] + (let [dpr (get-dpr)] + (set! (.-width canvas) new-physical-w) + (set! (.-height canvas) new-physical-h) + (set-render-options! dpr) + (resize-viewbox (/ new-physical-w dpr) (/ new-physical-h dpr)))) + (defn- wasm-get-numeric-value [name] (when-let [raw (let [p (rt/get-params @st/state)] @@ -1953,11 +1960,6 @@ (let [setter-name (str/concat "_set_" (name param-name))] (h/call wasm/internal-module setter-name value)))) -(defn set-render-options! - "Updates WASM render options with a new DPR value." - [new-dpr] - (h/call wasm/internal-module "_set_render_options" (debug-flags) new-dpr)) - (defn- canvas-css-size "Return canvas size in CSS pixels.