🔧 Normalize font attributes to support old formats

This commit is contained in:
Elena Torro 2025-11-28 12:53:47 +01:00 committed by Belén Albeza
parent 4282cdcd2c
commit 786f73767b
4 changed files with 91 additions and 28 deletions

View File

@ -342,8 +342,8 @@
(fn [result {:keys [font-id] :as node}] (fn [result {:keys [font-id] :as node}]
(let [current-font (let [current-font
(if (some? font-id) (if (some? font-id)
(select-keys node [:font-id :font-variant-id]) (select-keys node [:font-id :font-variant-id :font-weight :font-style])
(select-keys txt/default-typography [:font-id :font-variant-id]))] (select-keys txt/default-typography [:font-id :font-variant-id :font-weight :font-style]))]
(conj result current-font))) (conj result current-font)))
#{}))) #{})))

View File

@ -20,7 +20,6 @@
[app.common.types.shape.layout :as ctl] [app.common.types.shape.layout :as ctl]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.config :as cf] [app.config :as cf]
[app.main.fonts :as fonts]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.render :as render] [app.main.render :as render]
[app.main.store :as st] [app.main.store :as st]
@ -828,7 +827,7 @@
(set-shape-vertical-align (get content :vertical-align)) (set-shape-vertical-align (get content :vertical-align))
(let [fonts (fonts/get-content-fonts content) (let [fonts (f/get-content-fonts content)
fallback-fonts (fonts-from-text-content content true) fallback-fonts (fonts-from-text-content content true)
all-fonts (concat fonts fallback-fonts) all-fonts (concat fonts fallback-fonts)
result (f/store-fonts shape-id all-fonts)] result (f/store-fonts shape-id all-fonts)]

View File

@ -9,6 +9,7 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.logging :as log] [app.common.logging :as log]
[app.common.types.text :as txt]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.config :as cf] [app.config :as cf]
[app.main.fonts :as fonts] [app.main.fonts :as fonts]
@ -49,10 +50,13 @@
:builtin)) :builtin))
(defn- font-db-data (defn- font-db-data
[font-id font-variant-id] [font-id font-variant-id font-weight-fallback font-style-fallback]
(let [font (fonts/get-font-data font-id) (let [font (fonts/get-font-data font-id)
closest-variant (fonts/find-closest-variant font font-weight-fallback font-style-fallback)
variant (fonts/get-variant font font-variant-id)] variant (fonts/get-variant font font-variant-id)]
variant)) (if (or (nil? closest-variant) (= closest-variant variant))
variant
closest-variant)))
(defn- font-id->uuid [font-id] (defn- font-id->uuid [font-id]
(case (font-backend font-id) (case (font-backend font-id)
@ -63,22 +67,22 @@
:builtin :builtin
uuid/zero)) uuid/zero))
(defn ^:private font-id->asset-id [font-id font-variant-id]
(defn ^:private font-id->asset-id [font-id font-variant-id font-weight font-style]
(case (font-backend font-id) (case (font-backend font-id)
:google :google
font-id font-id
:custom :custom
(let [font-uuid (custom-font-id->uuid font-id) (let [font-uuid (custom-font-id->uuid font-id)
matching-font (d/seek (fn [[_ font]] matching-font (some (fn [[_ font]]
(let [variant-id (or (:font-variant-id font) (dm/str (:font-style font) "-" (:font-weight font)))] (and (= (:font-id font) font-uuid)
(and (= (:font-id font) font-uuid) (= (str (:font-weight font)) (str font-weight))
(or (nil? font-variant-id) font))
(= variant-id font-variant-id))))) (seq @fonts))]
(seq @fonts))]
(when matching-font (when matching-font
(:ttf-file-id (second matching-font)))) (:ttf-file-id matching-font)))
:builtin :builtin
(let [variant (font-db-data font-id font-variant-id)] (let [variant (font-db-data font-id font-variant-id font-weight font-style)]
(:ttf-url variant)))) (:ttf-url variant))))
(defn update-text-layout (defn update-text-layout
@ -100,6 +104,7 @@
ptr (h/call wasm/internal-module "_alloc_bytes" size) ptr (h/call wasm/internal-module "_alloc_bytes" size)
heap (gobj/get ^js wasm/internal-module "HEAPU8") heap (gobj/get ^js wasm/internal-module "HEAPU8")
mem (js/Uint8Array. (.-buffer heap) ptr size)] mem (js/Uint8Array. (.-buffer heap) ptr size)]
(.set mem (js/Uint8Array. font-array-buffer)) (.set mem (js/Uint8Array. font-array-buffer))
(h/call wasm/internal-module "_store_font" (h/call wasm/internal-module "_store_font"
(aget shape-id-buffer 0) (aget shape-id-buffer 0)
@ -134,17 +139,17 @@
(rx/empty))))}) (rx/empty))))})
(defn- google-font-ttf-url (defn- google-font-ttf-url
[font-id font-variant-id] [font-id font-variant-id font-weight font-style]
(let [variant (font-db-data font-id font-variant-id)] (let [variant (font-db-data font-id font-variant-id font-weight font-style)]
(if-let [ttf-url (:ttf-url variant)] (if-let [ttf-url (:ttf-url variant)]
(str/replace ttf-url "https://fonts.gstatic.com/s/" (u/join cf/public-uri "/internal/gfonts/font/")) (str/replace ttf-url "https://fonts.gstatic.com/s/" (u/join cf/public-uri "/internal/gfonts/font/"))
nil))) nil)))
(defn- font-id->ttf-url (defn- font-id->ttf-url
[font-id asset-id font-variant-id] [font-id asset-id font-variant-id font-weight font-style]
(case (font-backend font-id) (case (font-backend font-id)
:google :google
(google-font-ttf-url font-id font-variant-id) (google-font-ttf-url font-id font-variant-id font-weight font-style)
:custom :custom
(dm/str (u/join cf/public-uri "assets/by-id/" asset-id)) (dm/str (u/join cf/public-uri "assets/by-id/" asset-id))
:builtin :builtin
@ -153,7 +158,7 @@
(defn- store-font-id (defn- store-font-id
[shape-id font-data asset-id emoji? fallback?] [shape-id font-data asset-id emoji? fallback?]
(when asset-id (when asset-id
(let [uri (font-id->ttf-url (:font-id font-data) asset-id (:font-variant-id font-data)) (let [uri (font-id->ttf-url (:font-id font-data) asset-id (:font-variant-id font-data) (:weight font-data) (:style font-data))
id-buffer (uuid/get-u32 (:wasm-id font-data)) id-buffer (uuid/get-u32 (:wasm-id font-data))
font-data (assoc font-data :family-id-buffer id-buffer) font-data (assoc font-data :family-id-buffer id-buffer)
font-stored? (not= 0 (h/call wasm/internal-module "_is_font_uploaded" font-stored? (not= 0 (h/call wasm/internal-module "_is_font_uploaded"
@ -187,6 +192,30 @@
(catch :default _e (catch :default _e
uuid/zero))) uuid/zero)))
(defn normalize-span-font
[span paragraph]
(let [font-id (:font-id span)
font-variant-id (:font-variant-id span)
font-weight-fallback (or (:font-weight span) (:font-weight paragraph))
font-style-fallback (or (:font-style span) (:font-style paragraph))
font-data (font-db-data font-id font-variant-id font-weight-fallback font-style-fallback)]
(-> span
(assoc :font-variant-id (or (:name font-data) (:id font-data) font-variant-id)
:font-weight (or (:weight font-data) font-weight-fallback)
:font-style (or (:style font-data) font-style-fallback)))))
(defn normalize-paragraph-font
[paragraph]
(let [font-id (:font-id paragraph)
font-variant-id (:font-variant-id paragraph)
font-weight-fallback (:font-weight paragraph)
font-style-fallback (:font-style paragraph)
font-data (font-db-data font-id font-variant-id font-weight-fallback font-style-fallback)]
(-> paragraph
(assoc :font-variant-id (or (:name font-data) (:id font-data) font-variant-id)
:font-weight (or (:weight font-data) font-weight-fallback)
:font-style (or (:style font-data) font-style-fallback)))))
(defn serialize-font-size (defn serialize-font-size
[font-size] [font-size]
(cond (cond
@ -244,26 +273,36 @@
(string? letter-spacing) (string? letter-spacing)
(or (d/parse-double letter-spacing) default-letter-spacing))) (or (d/parse-double letter-spacing) default-letter-spacing)))
(defn normalize-font-variant
[font-variant-id]
(if (or (nil? font-variant-id) (str/blank? font-variant-id))
"regular"
font-variant-id))
(defn store-font (defn store-font
[shape-id font] [shape-id font]
(let [font-id (get font :font-id) (let [font-id (get font :font-id)
font-variant-id (get font :font-variant-id) font-variant-id (get font :font-variant-id)
font-weight-fallback (or (get font :font-weight) 400)
font-style-fallback (or (get font :font-style) "normal")
emoji? (get font :is-emoji false) emoji? (get font :is-emoji false)
fallback? (get font :is-fallback false) fallback? (get font :is-fallback false)
font-data (font-db-data font-id font-variant-id font-weight-fallback font-style-fallback)
wasm-id (font-id->uuid font-id) wasm-id (font-id->uuid font-id)
raw-weight (or (:weight (font-db-data font-id font-variant-id)) 400) raw-weight (or (:weight font-data) font-weight-fallback)
weight (serialize-font-weight raw-weight) weight (serialize-font-weight raw-weight)
style (serialize-font-style (cond style (serialize-font-style (cond
(str/includes? font-variant-id "italic") "italic" (str/includes? font-variant-id "italic") "italic"
(str/includes? raw-weight "italic") "italic" (str/includes? raw-weight "italic") "italic"
:else "normal")) :else font-style-fallback))
asset-id (font-id->asset-id font-id font-variant-id) variant-id (or (:name font-data) font-variant-id)
asset-id (font-id->asset-id font-id variant-id raw-weight style)
font-data {:wasm-id wasm-id font-data {:wasm-id wasm-id
:font-id font-id :font-id font-id
:font-variant-id font-variant-id :font-variant-id variant-id
:style style :style style
:weight weight}] :weight weight}]
(store-font-id shape-id font-data asset-id emoji? fallback?))) (store-font-id shape-id font-data asset-id emoji? fallback?)))
;; FIXME: This is a temporary function to load the fallback fonts for the editor. ;; FIXME: This is a temporary function to load the fallback fonts for the editor.
@ -273,6 +312,29 @@
(doseq [font fonts] (doseq [font fonts]
(fonts/ensure-loaded! (:font-id font) (:font-variant-id font)))) (fonts/ensure-loaded! (:font-id font) (:font-variant-id font))))
(defn get-content-fonts
"Extends from app.main.fonts/get-content-fonts. Extracts the fonts used by the content of a text shape, resolving the correct font variant info."
[content]
(let [paragraph-set (first (get content :children))
paragraphs (get paragraph-set :children)]
(->> paragraphs
(mapcat #(get % :children))
(filter txt/is-text-node?)
(reduce
(fn [result {:keys [font-id font-variant-id font-weight font-style] :as node}]
(let [resolved-font-id (or font-id (:font-id txt/default-typography))
resolved-variant-id (or font-variant-id (:font-variant-id txt/default-typography))
font-weight-fallback (or font-weight (:font-weight txt/default-typography) 400)
font-style-fallback (or font-style (:font-style txt/default-typography) "normal")
font-data (font-db-data resolved-font-id resolved-variant-id font-weight-fallback font-style-fallback)
font-ref {:font-id resolved-font-id
:font-variant-id (or (:name font-data) (:id font-data) resolved-variant-id)
:font-weight (or (:weight font-data) font-weight-fallback)
:font-style (or (:style font-data) font-style-fallback)}]
(conj result font-ref)))
#{}))))
(defn store-fonts (defn store-fonts
[shape-id fonts] [shape-id fonts]
(keep (fn [font] (store-font shape-id font)) fonts)) (keep (fn [font] (store-font shape-id font)) fonts))

View File

@ -142,7 +142,9 @@
;; buffer has the following format: ;; buffer has the following format:
;; [<num-spans> <paragraph_attributes> <spans_attributes> <text>] ;; [<num-spans> <paragraph_attributes> <spans_attributes> <text>]
[spans paragraph text] [spans paragraph text]
(let [num-spans (count spans) (let [normalized-paragraph (f/normalize-paragraph-font paragraph)
normalized-spans (map #(f/normalize-span-font % normalized-paragraph) spans)
num-spans (count normalized-spans)
fills-size (* types.fills.impl/FILL-U8-SIZE MAX-TEXT-FILLS) fills-size (* types.fills.impl/FILL-U8-SIZE MAX-TEXT-FILLS)
metadata-size (+ PARAGRAPH-ATTR-U8-SIZE metadata-size (+ PARAGRAPH-ATTR-U8-SIZE
(* num-spans (+ SPAN-ATTR-U8-SIZE fills-size))) (* num-spans (+ SPAN-ATTR-U8-SIZE fills-size)))
@ -157,8 +159,8 @@
(-> offset (-> offset
(mem/write-u32 dview num-spans) (mem/write-u32 dview num-spans)
(write-paragraph dview paragraph) (write-paragraph dview normalized-paragraph)
(write-spans dview spans paragraph) (write-spans dview normalized-spans normalized-paragraph)
(mem/write-buffer heapu8 text-buffer)) (mem/write-buffer heapu8 text-buffer))
(h/call wasm/internal-module "_set_shape_text_content"))) (h/call wasm/internal-module "_set_shape_text_content")))