mirror of
https://github.com/penpot/penpot.git
synced 2026-07-21 13:37:49 +00:00
🐛 Fix text selrect size (#10566)
* 🐛 Fix text selrect size * 🐛 Fix blinks on complex files --------- Co-authored-by: Belén Albeza <belen@hey.com>
This commit is contained in:
parent
88186eaec1
commit
d656d342fe
@ -65,6 +65,7 @@
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.variants :as dwva]
|
||||
[app.main.data.workspace.viewport :as dwv]
|
||||
[app.main.data.workspace.wasm-text :as dwwt]
|
||||
[app.main.data.workspace.zoom :as dwz]
|
||||
[app.main.errors]
|
||||
[app.main.features :as features]
|
||||
@ -441,6 +442,14 @@
|
||||
;; Keep comment thread positions in sync on undo/redo
|
||||
(rx/of (dwcm/watch-comment-thread-position-changes stoper-s))
|
||||
|
||||
;; Resize auto-grow text shapes whose selrect does not match
|
||||
;; the WASM text layout once their fonts finish loading.
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? :app.render-wasm.api/stale-text-selrects))
|
||||
(rx/map deref)
|
||||
(rx/map (fn [{:keys [ids]}]
|
||||
(dwwt/resize-wasm-text-all ids))))
|
||||
|
||||
(let [local-commits-s
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
|
||||
@ -42,12 +42,14 @@
|
||||
(wasm.api/set-shape-text-images id content)
|
||||
(let [dimension (when (not= :fixed grow-type)
|
||||
(wasm.api/get-text-dimensions))]
|
||||
{:width (if (#{:fixed :auto-height} grow-type)
|
||||
(:width selrect)
|
||||
(:width dimension))
|
||||
:height (if (= :fixed grow-type)
|
||||
(:height selrect)
|
||||
(:height dimension))}))))
|
||||
;; nil dimension = shape not present in WASM state; skip the resize.
|
||||
(when (or (= :fixed grow-type) (some? dimension))
|
||||
{:width (if (#{:fixed :auto-height} grow-type)
|
||||
(:width selrect)
|
||||
(:width dimension))
|
||||
:height (if (= :fixed grow-type)
|
||||
(:height selrect)
|
||||
(:height dimension))})))))
|
||||
|
||||
(defn resize-wasm-text-modifiers
|
||||
([shape]
|
||||
|
||||
@ -573,15 +573,19 @@
|
||||
(wasm.api/push-ruler-theme-colors!)
|
||||
(wasm.api/request-render "rulers-colors-theme")))))
|
||||
|
||||
;; Ruler overlay updates below only change the UI surface, not the shapes.
|
||||
;; They use `render-from-cache!` (cached tiles + UI, atomic) instead of a full
|
||||
;; `request-render`, which would kick off a progressive tile-by-tile shape
|
||||
;; re-render that flashes on zoomed-in views (see penpot ruler-selection flash).
|
||||
(mf/with-effect [@canvas-init? frame-visible?]
|
||||
(when @canvas-init?
|
||||
(wasm.api/set-rulers-frame-visible! frame-visible?)
|
||||
(wasm.api/request-render "rulers-frame")))
|
||||
(wasm.api/render-from-cache!)))
|
||||
|
||||
(mf/with-effect [@canvas-init? show-rulers?]
|
||||
(when @canvas-init?
|
||||
(wasm.api/set-rulers-visible! show-rulers?)
|
||||
(wasm.api/request-render "rulers-visible")))
|
||||
(wasm.api/render-from-cache!)))
|
||||
|
||||
(mf/with-effect [@canvas-init? show-rulers? offset-x offset-y]
|
||||
(when (and @canvas-init? show-rulers?)
|
||||
@ -592,7 +596,7 @@
|
||||
(some-> ruler-selection :width) (some-> ruler-selection :height)]
|
||||
(when (and @canvas-init? show-rulers?)
|
||||
(wasm.api/set-rulers-selection! ruler-selection)
|
||||
(wasm.api/request-render "rulers-selection")))
|
||||
(wasm.api/render-from-cache!)))
|
||||
|
||||
;; Paint background + rulers instantly, before shapes finish loading. Runs
|
||||
;; after the ruler push effects so the WASM ruler state is already set.
|
||||
|
||||
@ -58,6 +58,7 @@
|
||||
[app.util.timers :as timers]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[potok.v2.core :as ptk]
|
||||
[promesa.core :as p]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
@ -459,6 +460,20 @@
|
||||
(when (and wasm/context-initialized? (not @wasm/context-lost?))
|
||||
(h/call wasm/internal-module "_render_ui_only")))
|
||||
|
||||
(defn render-from-cache!
|
||||
"Blit the shapes from the cached tile atlas and redraw the UI overlay
|
||||
(rulers, selection band) fresh on top, in a single atomic frame. The
|
||||
*shapes* are the cached part (already-rasterized tiles, not rebuilt); the UI
|
||||
is re-rendered every call, which is what lets it reflect a new selection.
|
||||
|
||||
Use for UI-only updates that don't change shapes (e.g. the ruler selection
|
||||
band): unlike `request-render`, it never kicks off a progressive,
|
||||
tile-by-tile shape re-render, so it does not flash on zoomed-in views where
|
||||
the scene spans multiple tiles."
|
||||
[]
|
||||
(when (and wasm/context-initialized? (not @wasm/context-lost?))
|
||||
(h/call wasm/internal-module "_render_from_cache" 0)))
|
||||
|
||||
;; CSS-pixel blur radius for the page-transition snapshot (DPR-scaled in WASM).
|
||||
(def ^:private TRANSITION_BLUR_RADIUS 4.0)
|
||||
|
||||
@ -1282,17 +1297,19 @@
|
||||
([]
|
||||
(if-not (initialized?)
|
||||
{:x 0 :y 0 :width 0 :height 0 :max-width 0}
|
||||
(let [offset (-> (h/call wasm/internal-module "_get_text_dimensions")
|
||||
(mem/->offset-32))
|
||||
heapf32 (mem/get-heap-f32)
|
||||
width (aget heapf32 (+ offset 0))
|
||||
height (aget heapf32 (+ offset 1))
|
||||
max-width (aget heapf32 (+ offset 2))
|
||||
(let [ptr (h/call wasm/internal-module "_get_text_dimensions")]
|
||||
;; NULL pointer when there is no current shape or it is not a text.
|
||||
(when-not (zero? ptr)
|
||||
(let [offset (mem/->offset-32 ptr)
|
||||
heapf32 (mem/get-heap-f32)
|
||||
width (aget heapf32 (+ offset 0))
|
||||
height (aget heapf32 (+ offset 1))
|
||||
max-width (aget heapf32 (+ offset 2))
|
||||
|
||||
x (aget heapf32 (+ offset 3))
|
||||
y (aget heapf32 (+ offset 4))]
|
||||
(mem/free)
|
||||
{:x x :y y :width width :height height :max-width max-width}))))
|
||||
x (aget heapf32 (+ offset 3))
|
||||
y (aget heapf32 (+ offset 4))]
|
||||
(mem/free)
|
||||
{:x x :y y :width width :height height :max-width max-width}))))))
|
||||
|
||||
(defn intersect-position-in-shape
|
||||
[id position]
|
||||
@ -1452,19 +1469,45 @@
|
||||
[text-ids]
|
||||
(run! f/force-update-text-layout text-ids))
|
||||
|
||||
(defn- text-selrect-stale?
|
||||
"Check if the WASM-measured dimensions of an auto-grow text shape differ
|
||||
from its stored selrect (same 0.1px tolerance as the classic renderer)."
|
||||
[{:keys [id selrect grow-type]}]
|
||||
(when-let [{:keys [width height]} (get-text-dimensions id)]
|
||||
(case grow-type
|
||||
:auto-width (or (not (mth/close? width (:width selrect) 0.1))
|
||||
(not (mth/close? height (:height selrect) 0.1)))
|
||||
:auto-height (not (mth/close? height (:height selrect) 0.1))
|
||||
false)))
|
||||
|
||||
(defn- sync-stale-text-selrects!
|
||||
"Emit the ids of auto-grow text shapes whose selrect no longer matches the
|
||||
measured layout, so the workspace resizes them (data-event instead of a
|
||||
direct call to avoid a circular dependency; see the watcher in
|
||||
`app.main.data.workspace/initialize-workspace`)."
|
||||
[shapes]
|
||||
(let [stale-ids (into []
|
||||
(comp (filter cfh/text-shape?)
|
||||
(filter (comp #{:auto-width :auto-height} :grow-type))
|
||||
(filter text-selrect-stale?)
|
||||
(map :id))
|
||||
shapes)]
|
||||
(when (seq stale-ids)
|
||||
(st/emit! (ptk/data-event ::stale-text-selrects {:ids stale-ids})))))
|
||||
|
||||
(defn- relayout-after-fonts!
|
||||
"Relayout text shapes once their pending fonts have resolved. Shapes in
|
||||
`font-pending-ids` had a font fetched, so they get a forced relayout to pick
|
||||
up the real glyph metrics; the remaining text shapes get a normal layout."
|
||||
"Relayout text shapes once their pending fonts have resolved. Font fetches
|
||||
are deduped per URL and storing a font does not invalidate cached layouts,
|
||||
so every text shape (not only the fetch triggers in `font-pending-ids`)
|
||||
needs a forced relayout; then re-sync selrects that drifted."
|
||||
[shapes font-pending-ids]
|
||||
(let [force-ids (set font-pending-ids)
|
||||
text-ids (into [] (comp (filter cfh/text-shape?) (map :id)) shapes)
|
||||
forced (filterv force-ids text-ids)
|
||||
rest-ids (filterv (complement force-ids) text-ids)]
|
||||
(when (seq forced)
|
||||
(force-update-text-layouts forced))
|
||||
(when (seq rest-ids)
|
||||
(update-text-layouts rest-ids))))
|
||||
(let [text-ids (into [] (comp (filter cfh/text-shape?) (map :id)) shapes)]
|
||||
(when (seq text-ids)
|
||||
(if (seq font-pending-ids)
|
||||
(do
|
||||
(force-update-text-layouts text-ids)
|
||||
(sync-stale-text-selrects! shapes))
|
||||
(update-text-layouts text-ids)))))
|
||||
|
||||
(defn process-pending
|
||||
[shapes thumbnails full font-pending-ids on-complete]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user