mirror of
https://github.com/penpot/penpot.git
synced 2025-12-11 22:14:05 +01:00
✨ Calculate position data in wasm
This commit is contained in:
committed by
Belén Albeza
parent
b705cf953a
commit
ea4d0e1238
@@ -24,6 +24,8 @@
|
||||
(def revn-data (atom {}))
|
||||
(def queue-conj (fnil conj #queue []))
|
||||
|
||||
(def force-persist? #(= % ::force-persist))
|
||||
|
||||
(defn- update-status
|
||||
[status]
|
||||
(ptk/reify ::update-status
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.persistence :as-alias dps]
|
||||
[app.main.data.persistence :as dps]
|
||||
[app.main.data.plugins :as dp]
|
||||
[app.main.data.profile :as du]
|
||||
[app.main.data.project :as dpj]
|
||||
@@ -67,6 +67,7 @@
|
||||
[app.main.errors]
|
||||
[app.main.features :as features]
|
||||
[app.main.features.pointer-map :as fpmap]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.router :as rt]
|
||||
[app.render-wasm :as wasm]
|
||||
@@ -379,6 +380,59 @@
|
||||
(->> (rx/from added)
|
||||
(rx/map process-wasm-object)))))))
|
||||
|
||||
(when render-wasm?
|
||||
(let [local-commits-s
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
(rx/filter #(and (= :local (:source %))
|
||||
(not (contains? (:tags %) :position-data))))
|
||||
(rx/filter (complement empty?)))
|
||||
|
||||
notifier-s
|
||||
(rx/merge
|
||||
(->> local-commits-s (rx/debounce 1000))
|
||||
(->> stream (rx/filter dps/force-persist?)))
|
||||
|
||||
objects-s
|
||||
(rx/from-atom refs/workspace-page-objects {:emit-current-value? true})
|
||||
|
||||
current-page-id-s
|
||||
(rx/from-atom refs/current-page-id {:emit-current-value? true})]
|
||||
|
||||
(->> local-commits-s
|
||||
(rx/buffer-until notifier-s)
|
||||
(rx/with-latest-from objects-s)
|
||||
(rx/map
|
||||
(fn [[commits objects]]
|
||||
(->> commits
|
||||
(mapcat :redo-changes)
|
||||
(filter #(contains? #{:mod-obj :add-obj} (:type %)))
|
||||
(filter #(cfh/text-shape? objects (:id %)))
|
||||
(map #(vector
|
||||
(:id %)
|
||||
(wasm.api/calculate-position-data (get objects (:id %))))))))
|
||||
|
||||
(rx/with-latest-from current-page-id-s)
|
||||
(rx/map
|
||||
(fn [[text-position-data page-id]]
|
||||
(let [changes
|
||||
(->> text-position-data
|
||||
(mapv (fn [[id position-data]]
|
||||
{:type :mod-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:operations
|
||||
[{:type :set
|
||||
:attr :position-data
|
||||
:val position-data
|
||||
:ignore-touched true
|
||||
:ignore-geometry true}]})))]
|
||||
(dch/commit-changes
|
||||
{:redo-changes changes :undo-changes []
|
||||
:save-undo? false
|
||||
:tags #{:position-data}})))))))
|
||||
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/map deref)
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
(def profile
|
||||
(l/derived (l/key :profile) st/state))
|
||||
|
||||
(def current-page-id
|
||||
(l/derived (l/key :current-page-id) st/state))
|
||||
|
||||
(def team
|
||||
(l/derived (fn [state]
|
||||
(let [team-id (:current-team-id state)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.render-wasm.api :as wasm.api]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
@@ -275,3 +276,26 @@
|
||||
:y2 (:y end-p)
|
||||
:style {:stroke "red"
|
||||
:stroke-width (/ 1 zoom)}}]))]))))
|
||||
|
||||
(mf/defc debug-text-wasm-position-data
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [zoom (unchecked-get props "zoom")
|
||||
selected-shapes (unchecked-get props "selected-shapes")
|
||||
|
||||
selected-text
|
||||
(when (and (= (count selected-shapes) 1) (= :text (-> selected-shapes first :type)))
|
||||
(first selected-shapes))
|
||||
|
||||
position-data
|
||||
(when selected-text
|
||||
(wasm.api/calculate-position-data selected-text))]
|
||||
|
||||
(for [{:keys [x y width height]} position-data]
|
||||
[:rect {:x x
|
||||
:y (- y height)
|
||||
:width width
|
||||
:height height
|
||||
:fill "none"
|
||||
:strokeWidth (/ 1 zoom)
|
||||
:stroke "red"}])))
|
||||
|
||||
@@ -647,6 +647,12 @@
|
||||
:hover-top-frame-id @hover-top-frame-id
|
||||
:zoom zoom}])
|
||||
|
||||
(when (dbg/enabled? :text-outline)
|
||||
[:& wvd/debug-text-wasm-position-data
|
||||
{:selected-shapes selected-shapes
|
||||
:objects base-objects
|
||||
:zoom zoom}])
|
||||
|
||||
(when show-selection-handlers?
|
||||
[:g.selection-handlers {:clipPath "url(#clip-handlers)"}
|
||||
(when-not text-editing?
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
[app.main.refs :as refs]
|
||||
[app.main.render :as render]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.shapes.text]
|
||||
[app.main.worker :as mw]
|
||||
[app.render-wasm.api.fonts :as f]
|
||||
[app.render-wasm.api.texts :as t]
|
||||
@@ -1002,10 +1003,7 @@
|
||||
(run!
|
||||
(fn [id]
|
||||
(f/update-text-layout id)
|
||||
(mw/emit! {:cmd :index/update-text-rect
|
||||
:page-id (:current-page-id @st/state)
|
||||
:shape-id id
|
||||
:dimensions (get-text-dimensions id)})))))
|
||||
(update-text-rect! id)))))
|
||||
|
||||
(defn process-pending
|
||||
([shapes thumbnails full on-complete]
|
||||
@@ -1361,6 +1359,59 @@
|
||||
(h/call wasm/internal-module "_end_temp_objects")
|
||||
content)))
|
||||
|
||||
(def POSITION-DATA-U8-SIZE 36)
|
||||
(def POSITION-DATA-U32-SIZE (/ POSITION-DATA-U8-SIZE 4))
|
||||
|
||||
(defn calculate-position-data
|
||||
[shape]
|
||||
(when wasm/context-initialized?
|
||||
(use-shape (:id shape))
|
||||
(let [heapf32 (mem/get-heap-f32)
|
||||
heapu32 (mem/get-heap-u32)
|
||||
offset (-> (h/call wasm/internal-module "_calculate_position_data")
|
||||
(mem/->offset-32))
|
||||
length (aget heapu32 offset)
|
||||
|
||||
max-offset (+ offset 1 (* length POSITION-DATA-U32-SIZE))
|
||||
|
||||
result
|
||||
(loop [result (transient [])
|
||||
offset (inc offset)]
|
||||
(if (< offset max-offset)
|
||||
(let [entry (dr/read-position-data-entry heapu32 heapf32 offset)]
|
||||
(recur (conj! result entry)
|
||||
(+ offset POSITION-DATA-U32-SIZE)))
|
||||
(persistent! result)))
|
||||
|
||||
result
|
||||
(->> result
|
||||
(mapv
|
||||
(fn [{:keys [paragraph span start-pos end-pos direction x y width height]}]
|
||||
(let [content (:content shape)
|
||||
element (-> content :children
|
||||
(get 0) :children ;; paragraph-set
|
||||
(get paragraph) :children ;; paragraph
|
||||
(get span))
|
||||
text (subs (:text element) start-pos end-pos)]
|
||||
|
||||
{:x x
|
||||
:y (+ y height)
|
||||
:width width
|
||||
:height height
|
||||
:direction (dr/translate-direction direction)
|
||||
:font-family (get element :font-family)
|
||||
:font-size (get element :font-size)
|
||||
:font-weight (get element :font-weight)
|
||||
:text-transform (get element :text-transform)
|
||||
:text-decoration (get element :text-decoration)
|
||||
:letter-spacing (get element :letter-spacing)
|
||||
:font-style (get element :font-style)
|
||||
:fills (get element :fills)
|
||||
:text text}))))]
|
||||
(mem/free)
|
||||
|
||||
result)))
|
||||
|
||||
(defn init-wasm-module
|
||||
[module]
|
||||
(let [default-fn (unchecked-get module "default")
|
||||
|
||||
@@ -45,4 +45,29 @@
|
||||
:center (gpt/point cx cy)
|
||||
:transform (gmt/matrix a b c d e f)}))
|
||||
|
||||
(defn read-position-data-entry
|
||||
[heapu32 heapf32 offset]
|
||||
(let [paragraph (aget heapu32 (+ offset 0))
|
||||
span (aget heapu32 (+ offset 1))
|
||||
start-pos (aget heapu32 (+ offset 2))
|
||||
end-pos (aget heapu32 (+ offset 3))
|
||||
x (aget heapf32 (+ offset 4))
|
||||
y (aget heapf32 (+ offset 5))
|
||||
width (aget heapf32 (+ offset 6))
|
||||
height (aget heapf32 (+ offset 7))
|
||||
direction (aget heapu32 (+ offset 8))]
|
||||
{:paragraph paragraph
|
||||
:span span
|
||||
:start-pos start-pos
|
||||
:end-pos end-pos
|
||||
:x x
|
||||
:y y
|
||||
:width width
|
||||
:height height
|
||||
:direction direction}))
|
||||
|
||||
(defn translate-direction
|
||||
[direction]
|
||||
(case direction
|
||||
0 "rtl"
|
||||
"ltr"))
|
||||
|
||||
Reference in New Issue
Block a user