mirror of
https://github.com/penpot/penpot.git
synced 2026-02-12 14:42:56 +00:00
✨ Batch text layout updates
This commit is contained in:
committed by
Belén Albeza
parent
53c2acb3e6
commit
fd3d549f9c
@@ -10,6 +10,7 @@
|
||||
This exists to avoid circular deps:
|
||||
workspace.texts -> workspace.libraries -> workspace.texts"
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
@@ -17,6 +18,7 @@
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.modifiers :as dwm]
|
||||
[app.render-wasm.api :as wasm.api]
|
||||
[app.render-wasm.api.fonts :as wasm.fonts]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
@@ -64,7 +66,7 @@
|
||||
|
||||
(defn resize-wasm-text-debounce-commit
|
||||
[]
|
||||
(ptk/reify ::resize-wasm-text
|
||||
(ptk/reify ::resize-wasm-text-debounce-commit
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [ids (get state ::resize-wasm-text-debounce-ids)
|
||||
@@ -89,10 +91,10 @@
|
||||
;; are processed at the same time and not one-by-one. This will improve
|
||||
;; performance because it's better to make only one layout calculation instead
|
||||
;; of (potentialy) hundreds.
|
||||
(defn resize-wasm-text-debounce
|
||||
(defn resize-wasm-text-debounce-inner
|
||||
[id]
|
||||
(let [cur-event (js/Symbol)]
|
||||
(ptk/reify ::resize-wasm-text-debounce
|
||||
(ptk/reify ::resize-wasm-text-debounce-inner
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
@@ -107,20 +109,39 @@
|
||||
(rx/concat
|
||||
(rx/merge
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::resize-wasm-text-debounce))
|
||||
(rx/debounce 20)
|
||||
(rx/filter (ptk/type? ::resize-wasm-text-debounce-inner))
|
||||
(rx/debounce 40)
|
||||
(rx/take 1)
|
||||
(rx/delay 200)
|
||||
(rx/map #(resize-wasm-text-debounce-commit))
|
||||
(rx/take-until stopper))
|
||||
|
||||
(rx/of (resize-wasm-text-debounce id)))
|
||||
|
||||
(rx/of (resize-wasm-text-debounce-inner id)))
|
||||
(rx/of #(dissoc %
|
||||
::resize-wasm-text-debounce-ids
|
||||
::resize-wasm-text-debounce-event))))
|
||||
(rx/empty))))))
|
||||
|
||||
(defn resize-wasm-text-debounce
|
||||
[id]
|
||||
(ptk/reify ::resize-wasm-text-debounce
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
content (dm/get-in objects [id :content])
|
||||
fonts (wasm.fonts/get-content-fonts content)
|
||||
|
||||
fonts-loaded?
|
||||
(->> fonts
|
||||
(every?
|
||||
(fn [font]
|
||||
(let [font-data (wasm.fonts/make-font-data font)]
|
||||
(wasm.fonts/font-stored? font-data (:emoji? font-data))))))]
|
||||
|
||||
(if (not fonts-loaded?)
|
||||
(->> (rx/of (resize-wasm-text-debounce id))
|
||||
(rx/delay 20))
|
||||
(rx/of (resize-wasm-text-debounce-inner id)))))))
|
||||
|
||||
(defn resize-wasm-text-all
|
||||
"Resize all text shapes (auto-width/auto-height) from a collection of ids."
|
||||
[ids]
|
||||
|
||||
@@ -867,12 +867,12 @@
|
||||
|
||||
(set-shape-vertical-align (get content :vertical-align))
|
||||
|
||||
(let [fonts (f/get-content-fonts content)
|
||||
(let [fonts (f/get-content-fonts content)
|
||||
fallback-fonts (fonts-from-text-content content true)
|
||||
all-fonts (concat fonts fallback-fonts)
|
||||
result (f/store-fonts shape-id all-fonts)]
|
||||
all-fonts (concat fonts fallback-fonts)
|
||||
result (f/store-fonts all-fonts)]
|
||||
(f/load-fallback-fonts-for-editor! fallback-fonts)
|
||||
(h/call wasm/internal-module "_update_shape_text_layout")
|
||||
(f/update-text-layout shape-id)
|
||||
result))
|
||||
|
||||
(defn set-shape-grow-type
|
||||
|
||||
@@ -97,9 +97,8 @@
|
||||
|
||||
;; IMPORTANT: Only TTF fonts can be stored.
|
||||
(defn- store-font-buffer
|
||||
[shape-id font-data font-array-buffer emoji? fallback?]
|
||||
[font-data font-array-buffer emoji? fallback?]
|
||||
(let [font-id-buffer (:family-id-buffer font-data)
|
||||
shape-id-buffer (uuid/get-u32 shape-id)
|
||||
size (.-byteLength font-array-buffer)
|
||||
ptr (h/call wasm/internal-module "_alloc_bytes" size)
|
||||
heap (gobj/get ^js wasm/internal-module "HEAPU8")
|
||||
@@ -107,10 +106,6 @@
|
||||
|
||||
(.set mem (js/Uint8Array. font-array-buffer))
|
||||
(h/call wasm/internal-module "_store_font"
|
||||
(aget shape-id-buffer 0)
|
||||
(aget shape-id-buffer 1)
|
||||
(aget shape-id-buffer 2)
|
||||
(aget shape-id-buffer 3)
|
||||
(aget font-id-buffer 0)
|
||||
(aget font-id-buffer 1)
|
||||
(aget font-id-buffer 2)
|
||||
@@ -119,24 +114,31 @@
|
||||
(:style font-data)
|
||||
emoji?
|
||||
fallback?)
|
||||
|
||||
(update-text-layout shape-id)
|
||||
|
||||
true))
|
||||
|
||||
;; This variable will store the fonts that are currently being fetched
|
||||
;; so we don't fetch more than once the same font
|
||||
(def fetching (atom #{}))
|
||||
|
||||
(defn- fetch-font
|
||||
[shape-id font-data font-url emoji? fallback?]
|
||||
{:key font-url
|
||||
:callback #(->> (http/send! {:method :get
|
||||
:uri font-url
|
||||
:response-type :buffer})
|
||||
(rx/map (fn [{:keys [body]}]
|
||||
(store-font-buffer shape-id font-data body emoji? fallback?)))
|
||||
(rx/catch (fn [cause]
|
||||
(log/error :hint "Could not fetch font"
|
||||
:font-url font-url
|
||||
:cause cause)
|
||||
(rx/empty))))})
|
||||
[font-data font-url emoji? fallback?]
|
||||
(when-not (contains? @fetching font-url)
|
||||
(swap! fetching conj font-url)
|
||||
{:key font-url
|
||||
:callback
|
||||
(fn []
|
||||
(->> (http/send! {:method :get
|
||||
:uri font-url
|
||||
:response-type :buffer})
|
||||
(rx/map (fn [{:keys [body]}]
|
||||
(swap! fetching disj font-url)
|
||||
(store-font-buffer font-data body emoji? fallback?)))
|
||||
(rx/catch (fn [cause]
|
||||
(swap! fetching disj font-url)
|
||||
(log/error :hint "Could not fetch font"
|
||||
:font-url font-url
|
||||
:cause cause)
|
||||
(rx/empty)))))}))
|
||||
|
||||
(defn- google-font-ttf-url
|
||||
[font-id font-variant-id font-weight font-style]
|
||||
@@ -155,22 +157,31 @@
|
||||
:builtin
|
||||
(dm/str (u/join cf/public-uri "fonts/" asset-id))))
|
||||
|
||||
(defn font-stored?
|
||||
[font-data emoji?]
|
||||
(when-let [id-buffer (uuid/get-u32 (:wasm-id font-data))]
|
||||
(not= 0 (h/call wasm/internal-module "_is_font_uploaded"
|
||||
(aget id-buffer 0)
|
||||
(aget id-buffer 1)
|
||||
(aget id-buffer 2)
|
||||
(aget id-buffer 3)
|
||||
(:weight font-data)
|
||||
(:style font-data)
|
||||
emoji?))))
|
||||
|
||||
(defn- store-font-id
|
||||
[shape-id font-data asset-id emoji? fallback?]
|
||||
[font-data asset-id emoji? fallback?]
|
||||
(when asset-id
|
||||
(let [uri (font-id->ttf-url (:font-id font-data) asset-id (:font-variant-id font-data) (:weight font-data) (:style-name font-data))
|
||||
(let [uri (font-id->ttf-url
|
||||
(:font-id font-data) asset-id
|
||||
(:font-variant-id font-data)
|
||||
(:weight font-data)
|
||||
(:style-name font-data))
|
||||
id-buffer (uuid/get-u32 (:wasm-id font-data))
|
||||
font-data (assoc font-data :family-id-buffer id-buffer)
|
||||
font-stored? (not= 0 (h/call wasm/internal-module "_is_font_uploaded"
|
||||
(aget id-buffer 0)
|
||||
(aget id-buffer 1)
|
||||
(aget id-buffer 2)
|
||||
(aget id-buffer 3)
|
||||
(:weight font-data)
|
||||
(:style font-data)
|
||||
emoji?))]
|
||||
font-stored? (font-stored? font-data emoji?)]
|
||||
(when-not font-stored?
|
||||
(fetch-font shape-id font-data uri emoji? fallback?)))))
|
||||
(fetch-font font-data uri emoji? fallback?)))))
|
||||
|
||||
(defn serialize-font-style
|
||||
[font-style]
|
||||
@@ -280,8 +291,8 @@
|
||||
"regular"
|
||||
font-variant-id))
|
||||
|
||||
(defn store-font
|
||||
[shape-id font]
|
||||
(defn make-font-data
|
||||
[font]
|
||||
(let [font-id (get font :font-id)
|
||||
font-variant-id (get font :font-variant-id)
|
||||
normalized-variant-id (when font-variant-id
|
||||
@@ -301,14 +312,21 @@
|
||||
(str/includes? raw-weight "italic") "italic"
|
||||
:else font-style-fallback)
|
||||
variant-id (or (:id font-data) normalized-variant-id)
|
||||
asset-id (font-id->asset-id font-id variant-id raw-weight style)
|
||||
font-data {:wasm-id wasm-id
|
||||
:font-id font-id
|
||||
:font-variant-id variant-id
|
||||
:style (serialize-font-style style)
|
||||
:style-name style
|
||||
:weight weight}]
|
||||
(store-font-id shape-id font-data asset-id emoji? fallback?)))
|
||||
asset-id (font-id->asset-id font-id variant-id raw-weight style)]
|
||||
{:wasm-id wasm-id
|
||||
:font-id font-id
|
||||
:font-variant-id variant-id
|
||||
:style (serialize-font-style style)
|
||||
:style-name style
|
||||
:weight weight
|
||||
:emoji? emoji?
|
||||
:fallbck? fallback?
|
||||
:asset-id asset-id}))
|
||||
|
||||
(defn store-font
|
||||
[font]
|
||||
(let [{:keys [asset-id emoji? fallback?] :as font-data} (make-font-data font)]
|
||||
(store-font-id font-data asset-id emoji? fallback?)))
|
||||
|
||||
;; FIXME: This is a temporary function to load the fallback fonts for the editor.
|
||||
;; Once we render the editor content within wasm, we can remove this function.
|
||||
@@ -341,8 +359,8 @@
|
||||
#{}))))
|
||||
|
||||
(defn store-fonts
|
||||
[shape-id fonts]
|
||||
(keep (fn [font] (store-font shape-id font)) fonts))
|
||||
[fonts]
|
||||
(keep (fn [font] (store-font font)) fonts))
|
||||
|
||||
(defn add-emoji-font
|
||||
[fonts]
|
||||
|
||||
Reference in New Issue
Block a user