mirror of
https://github.com/penpot/penpot.git
synced 2025-06-24 14:16:59 +02:00
🎉 Add text fills
This commit is contained in:
parent
c2ce7c6cf6
commit
42ef2f929a
11 changed files with 451 additions and 279 deletions
|
@ -56,7 +56,7 @@
|
|||
|
||||
([{:keys [id points selrect] :as shape} content]
|
||||
(wasm.api/use-shape id)
|
||||
(wasm.api/set-shape-text-content content)
|
||||
(wasm.api/set-shape-text content)
|
||||
(let [dimension (wasm.api/text-dimensions)
|
||||
resize-v
|
||||
(gpt/point
|
||||
|
|
|
@ -188,7 +188,6 @@
|
|||
|
||||
(defn- store-image
|
||||
[id]
|
||||
|
||||
(let [buffer (uuid/get-u32 id)
|
||||
url (cf/resolve-file-media {:id id})]
|
||||
(->> (http/send! {:method :get
|
||||
|
@ -209,6 +208,33 @@
|
|||
(aget buffer 3))
|
||||
true))))))
|
||||
|
||||
(defn- get-fill-images
|
||||
[leaf]
|
||||
(filter :fill-image (:fills leaf)))
|
||||
|
||||
(defn- process-fill-image
|
||||
[fill]
|
||||
(rx/from
|
||||
(when-let [image (:fill-image fill)]
|
||||
(let [id (dm/get-prop image :id)
|
||||
buffer (uuid/get-u32 id)
|
||||
cached-image? (h/call wasm/internal-module "_is_image_cached"
|
||||
(aget buffer 0)
|
||||
(aget buffer 1)
|
||||
(aget buffer 2)
|
||||
(aget buffer 3))]
|
||||
(when (zero? cached-image?)
|
||||
(store-image id))))))
|
||||
|
||||
(defn set-shape-text-images
|
||||
[content]
|
||||
(let [paragraph-set (first (get content :children))
|
||||
paragraphs (get paragraph-set :children)]
|
||||
(->> paragraphs
|
||||
(mapcat :children)
|
||||
(mapcat get-fill-images)
|
||||
(map process-fill-image))))
|
||||
|
||||
(defn set-shape-fills
|
||||
[fills]
|
||||
(h/call wasm/internal-module "_clear_shape_fills")
|
||||
|
@ -218,23 +244,24 @@
|
|||
gradient (:fill-color-gradient fill)
|
||||
image (:fill-image fill)
|
||||
offset (mem/alloc-bytes sr-fills/FILL-BYTE-SIZE)
|
||||
heap (mem/get-heap-u32)]
|
||||
heap (mem/get-heap-u8)
|
||||
dview (js/DataView. (.-buffer heap))]
|
||||
(cond
|
||||
(some? color)
|
||||
(let [argb (sr-clr/hex->u32argb color opacity)]
|
||||
(sr-fills/write-solid-fill! offset heap argb)
|
||||
(do
|
||||
(sr-fills/write-solid-fill! offset dview (sr-clr/hex->u32argb color opacity))
|
||||
(h/call wasm/internal-module "_add_shape_fill"))
|
||||
|
||||
(some? gradient)
|
||||
(do
|
||||
(sr-fills/write-gradient-fill! offset heap gradient opacity)
|
||||
(sr-fills/write-gradient-fill! offset dview gradient opacity)
|
||||
(h/call wasm/internal-module "_add_shape_fill"))
|
||||
|
||||
(some? image)
|
||||
(let [id (dm/get-prop image :id)
|
||||
buffer (uuid/get-u32 id)
|
||||
cached-image? (h/call wasm/internal-module "_is_image_cached" (aget buffer 0) (aget buffer 1) (aget buffer 2) (aget buffer 3))]
|
||||
(sr-fills/write-image-fill! offset heap id opacity (dm/get-prop image :width) (dm/get-prop image :height))
|
||||
(sr-fills/write-image-fill! offset dview id opacity (dm/get-prop image :width) (dm/get-prop image :height))
|
||||
(h/call wasm/internal-module "_add_shape_fill")
|
||||
(when (== cached-image? 0)
|
||||
(store-image id))))))
|
||||
|
@ -254,7 +281,8 @@
|
|||
cap-start (-> stroke :stroke-cap-start sr/translate-stroke-cap)
|
||||
cap-end (-> stroke :stroke-cap-end sr/translate-stroke-cap)
|
||||
offset (mem/alloc-bytes sr-fills/FILL-BYTE-SIZE)
|
||||
heap (mem/get-heap-u32)]
|
||||
heap (mem/get-heap-u8)
|
||||
dview (js/DataView. (.-buffer heap))]
|
||||
(case align
|
||||
:inner (h/call wasm/internal-module "_add_shape_inner_stroke" width style cap-start cap-end)
|
||||
:outer (h/call wasm/internal-module "_add_shape_outer_stroke" width style cap-start cap-end)
|
||||
|
@ -262,22 +290,22 @@
|
|||
|
||||
(cond
|
||||
(some? gradient)
|
||||
(let [_ nil]
|
||||
(sr-fills/write-gradient-fill! offset heap gradient opacity)
|
||||
(do
|
||||
(sr-fills/write-gradient-fill! offset dview gradient opacity)
|
||||
(h/call wasm/internal-module "_add_shape_stroke_fill"))
|
||||
|
||||
(some? image)
|
||||
(let [id (dm/get-prop image :id)
|
||||
buffer (uuid/get-u32 id)
|
||||
cached-image? (h/call wasm/internal-module "_is_image_cached" (aget buffer 0) (aget buffer 1) (aget buffer 2) (aget buffer 3))]
|
||||
(sr-fills/write-image-fill! offset heap id opacity (dm/get-prop image :width) (dm/get-prop image :height))
|
||||
(sr-fills/write-image-fill! offset dview id opacity (dm/get-prop image :width) (dm/get-prop image :height))
|
||||
(h/call wasm/internal-module "_add_shape_stroke_fill")
|
||||
(when (== cached-image? 0)
|
||||
(store-image id)))
|
||||
|
||||
(some? color)
|
||||
(let [argb (sr-clr/hex->u32argb color opacity)]
|
||||
(sr-fills/write-solid-fill! offset heap argb)
|
||||
(do
|
||||
(sr-fills/write-solid-fill! offset dview (sr-clr/hex->u32argb color opacity))
|
||||
(h/call wasm/internal-module "_add_shape_stroke_fill")))))
|
||||
strokes))
|
||||
|
||||
|
@ -608,6 +636,12 @@
|
|||
fonts)]
|
||||
(f/store-fonts fonts))))
|
||||
|
||||
(defn set-shape-text
|
||||
[content]
|
||||
(concat
|
||||
(set-shape-text-images content)
|
||||
(set-shape-text-content content)))
|
||||
|
||||
(defn set-shape-grow-type
|
||||
[grow-type]
|
||||
(h/call wasm/internal-module "_set_shape_grow_type" (sr/translate-grow-type grow-type)))
|
||||
|
@ -697,7 +731,7 @@
|
|||
(when (some? corners) (set-shape-corners corners))
|
||||
(when (some? shadows) (set-shape-shadows shadows))
|
||||
(when (and (= type :text) (some? content))
|
||||
(set-shape-text-content content))
|
||||
(set-shape-text content))
|
||||
(when (= type :text)
|
||||
(set-shape-grow-type grow-type))
|
||||
(when (or (ctl/any-layout? shape)
|
||||
|
@ -711,9 +745,7 @@
|
|||
(set-grid-layout shape))
|
||||
|
||||
(let [pending (into [] (concat
|
||||
(if (and (= type :text) (some? content))
|
||||
(set-shape-text-content content)
|
||||
[])
|
||||
(set-shape-text content)
|
||||
(set-shape-fills fills)
|
||||
(set-shape-strokes strokes)))]
|
||||
(perf/end-measure "set-object")
|
||||
|
|
|
@ -6,30 +6,65 @@
|
|||
|
||||
(ns app.render-wasm.api.texts
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.render-wasm.api.fonts :as f]
|
||||
[app.render-wasm.helpers :as h]
|
||||
[app.render-wasm.mem :as mem]
|
||||
[app.render-wasm.serializers :as sr]
|
||||
[app.render-wasm.serializers.color :as sr-clr]
|
||||
[app.render-wasm.serializers.fills :as sr-fills]
|
||||
[app.render-wasm.wasm :as wasm]))
|
||||
|
||||
(defn utf8->buffer [text]
|
||||
(let [encoder (js/TextEncoder.)]
|
||||
(.encode encoder text)))
|
||||
|
||||
(defn set-text-leaf-fills
|
||||
[fills current-offset dview]
|
||||
(reduce (fn [offset fill]
|
||||
(let [opacity (or (:fill-opacity fill) 1.0)
|
||||
color (:fill-color fill)
|
||||
gradient (:fill-color-gradient fill)
|
||||
image (:fill-image fill)]
|
||||
(cond
|
||||
(some? color)
|
||||
(sr-fills/write-solid-fill! offset dview (sr-clr/hex->u32argb color opacity))
|
||||
|
||||
(some? gradient)
|
||||
(sr-fills/write-gradient-fill! offset dview gradient opacity)
|
||||
|
||||
(some? image)
|
||||
(sr-fills/write-image-fill! offset dview
|
||||
(dm/get-prop image :id)
|
||||
opacity
|
||||
(dm/get-prop image :width)
|
||||
(dm/get-prop image :height)))
|
||||
|
||||
(+ offset sr-fills/FILL-BYTE-SIZE)))
|
||||
current-offset
|
||||
fills))
|
||||
|
||||
(defn total-fills-count
|
||||
[leaves]
|
||||
(reduce #(+ %1 (count (:fills %2))) 0 leaves))
|
||||
|
||||
(defn write-shape-text
|
||||
;; buffer has the following format:
|
||||
;; [<num-leaves> <paragraph_attributes> <leaves_attributes> <text>]
|
||||
[leaves paragraph text]
|
||||
(let [num-leaves (count leaves)
|
||||
(let [le? true
|
||||
num-leaves (count leaves)
|
||||
paragraph-attr-size 48
|
||||
leaf-attr-size 52
|
||||
metadata-size (+ 1 paragraph-attr-size (* num-leaves leaf-attr-size))
|
||||
total-fills (total-fills-count leaves)
|
||||
total-fills-size (* sr-fills/FILL-BYTE-SIZE total-fills)
|
||||
leaf-attr-size 56
|
||||
metadata-size (+ paragraph-attr-size (* num-leaves leaf-attr-size) total-fills-size)
|
||||
text-buffer (utf8->buffer text)
|
||||
text-size (.-byteLength text-buffer)
|
||||
buffer (js/ArrayBuffer. (+ metadata-size text-size))
|
||||
dview (js/DataView. buffer)]
|
||||
|
||||
(.setUint32 dview 0 num-leaves)
|
||||
(.setUint32 dview 0 num-leaves le?)
|
||||
|
||||
;; Serialize paragraph attributes
|
||||
(let [text-align (sr/serialize-text-align (:text-align paragraph))
|
||||
|
@ -41,26 +76,26 @@
|
|||
typography-ref-file (sr/serialize-uuid (:typography-ref-file paragraph))
|
||||
typography-ref-id (sr/serialize-uuid (:typography-ref-id paragraph))]
|
||||
|
||||
(.setUint8 dview 4 text-align)
|
||||
(.setUint8 dview 5 text-direction)
|
||||
(.setUint8 dview 6 text-decoration)
|
||||
(.setUint8 dview 7 text-transform)
|
||||
(.setUint8 dview 4 text-align le?)
|
||||
(.setUint8 dview 5 text-direction le?)
|
||||
(.setUint8 dview 6 text-decoration le?)
|
||||
(.setUint8 dview 7 text-transform le?)
|
||||
|
||||
(.setFloat32 dview 8 line-height)
|
||||
(.setFloat32 dview 12 letter-spacing)
|
||||
(.setFloat32 dview 8 line-height le?)
|
||||
(.setFloat32 dview 12 letter-spacing le?)
|
||||
|
||||
(.setUint32 dview 16 (aget typography-ref-file 0))
|
||||
(.setUint32 dview 20 (aget typography-ref-file 1))
|
||||
(.setUint32 dview 24 (aget typography-ref-file 2))
|
||||
(.setInt32 dview 28 (aget typography-ref-file 3))
|
||||
(.setUint32 dview 16 (aget typography-ref-file 0) le?)
|
||||
(.setUint32 dview 20 (aget typography-ref-file 1) le?)
|
||||
(.setUint32 dview 24 (aget typography-ref-file 2) le?)
|
||||
(.setInt32 dview 28 (aget typography-ref-file 3) le?)
|
||||
|
||||
(.setUint32 dview 32 (aget typography-ref-id 0))
|
||||
(.setUint32 dview 36 (aget typography-ref-id 1))
|
||||
(.setUint32 dview 40 (aget typography-ref-id 2))
|
||||
(.setInt32 dview 44 (aget typography-ref-id 3)))
|
||||
(.setUint32 dview 32 (aget typography-ref-id 0) le?)
|
||||
(.setUint32 dview 36 (aget typography-ref-id 1) le?)
|
||||
(.setUint32 dview 40 (aget typography-ref-id 2) le?)
|
||||
(.setInt32 dview 44 (aget typography-ref-id 3) le?))
|
||||
|
||||
;; Serialize leaves attributes
|
||||
(loop [index 0 offset (+ 1 paragraph-attr-size)]
|
||||
(loop [index 0 offset paragraph-attr-size]
|
||||
(when (< index num-leaves)
|
||||
(let [leaf (nth leaves index)
|
||||
font-style (f/serialize-font-style (:font-style leaf))
|
||||
|
@ -70,26 +105,30 @@
|
|||
font-family (hash (:font-family leaf))
|
||||
font-variant-id (sr/serialize-uuid (:font-variant-id leaf))
|
||||
text-buffer (utf8->buffer (:text leaf))
|
||||
text-length (.-byteLength text-buffer)]
|
||||
text-length (.-byteLength text-buffer)
|
||||
fills (:fills leaf)
|
||||
total-fills (count fills)]
|
||||
|
||||
(.setUint8 dview offset font-style)
|
||||
(.setFloat32 dview (+ offset 4) font-size)
|
||||
(.setUint32 dview (+ offset 8) font-weight)
|
||||
(.setUint32 dview (+ offset 12) (aget font-id 0))
|
||||
(.setUint32 dview (+ offset 16) (aget font-id 1))
|
||||
(.setUint32 dview (+ offset 20) (aget font-id 2))
|
||||
(.setInt32 dview (+ offset 24) (aget font-id 3))
|
||||
(.setUint8 dview offset font-style le?)
|
||||
(.setFloat32 dview (+ offset 4) font-size le?)
|
||||
(.setUint32 dview (+ offset 8) font-weight le?)
|
||||
(.setUint32 dview (+ offset 12) (aget font-id 0) le?)
|
||||
(.setUint32 dview (+ offset 16) (aget font-id 1) le?)
|
||||
(.setUint32 dview (+ offset 20) (aget font-id 2) le?)
|
||||
(.setInt32 dview (+ offset 24) (aget font-id 3) le?)
|
||||
|
||||
(.setInt32 dview (+ offset 28) font-family)
|
||||
(.setInt32 dview (+ offset 28) font-family le?)
|
||||
|
||||
(.setUint32 dview (+ offset 32) (aget font-variant-id 0))
|
||||
(.setUint32 dview (+ offset 36) (aget font-variant-id 1))
|
||||
(.setUint32 dview (+ offset 40) (aget font-variant-id 2))
|
||||
(.setInt32 dview (+ offset 44) (aget font-variant-id 3))
|
||||
(.setUint32 dview (+ offset 32) (aget font-variant-id 0) le?)
|
||||
(.setUint32 dview (+ offset 36) (aget font-variant-id 1) le?)
|
||||
(.setUint32 dview (+ offset 40) (aget font-variant-id 2) le?)
|
||||
(.setInt32 dview (+ offset 44) (aget font-variant-id 3) le?)
|
||||
|
||||
(.setInt32 dview (+ offset 48) text-length)
|
||||
(.setInt32 dview (+ offset 48) text-length le?)
|
||||
(.setInt32 dview (+ offset 52) total-fills le?)
|
||||
|
||||
(recur (inc index) (+ offset leaf-attr-size)))))
|
||||
(let [new-offset (set-text-leaf-fills fills (+ offset leaf-attr-size) dview)]
|
||||
(recur (inc index) new-offset)))))
|
||||
|
||||
;; Add text content to buffer
|
||||
(let [text-offset metadata-size
|
||||
|
|
|
@ -15,16 +15,14 @@
|
|||
(def FILL-BYTE-SIZE (+ 4 (max GRADIENT-BYTE-SIZE IMAGE-BYTE-SIZE SOLID-BYTE-SIZE)))
|
||||
|
||||
(defn write-solid-fill!
|
||||
[offset heap-u32 argb]
|
||||
(let [dview (js/DataView. (.-buffer heap-u32))]
|
||||
(.setUint8 dview offset 0x00 true)
|
||||
(.setUint32 dview (+ offset 4) argb true)
|
||||
(+ offset FILL-BYTE-SIZE)))
|
||||
[offset dview argb]
|
||||
(.setUint8 dview offset 0x00 true)
|
||||
(.setUint32 dview (+ offset 4) argb true)
|
||||
(+ offset FILL-BYTE-SIZE))
|
||||
|
||||
(defn write-image-fill!
|
||||
[offset heap-u32 id opacity width height]
|
||||
(let [dview (js/DataView. (.-buffer heap-u32))
|
||||
uuid-buffer (uuid/get-u32 id)]
|
||||
[offset dview id opacity width height]
|
||||
(let [uuid-buffer (uuid/get-u32 id)]
|
||||
(.setUint8 dview offset 0x03 true)
|
||||
(.setUint32 dview (+ offset 4) (aget uuid-buffer 0) true)
|
||||
(.setUint32 dview (+ offset 8) (aget uuid-buffer 1) true)
|
||||
|
@ -35,22 +33,19 @@
|
|||
(.setInt32 dview (+ offset 28) height true)
|
||||
(+ offset FILL-BYTE-SIZE)))
|
||||
|
||||
|
||||
|
||||
(defn write-gradient-fill!
|
||||
[offset heap-u32 gradient opacity]
|
||||
(let [dview (js/DataView. (.-buffer heap-u32))
|
||||
start-x (:start-x gradient)
|
||||
[offset dview gradient opacity]
|
||||
(let [start-x (:start-x gradient)
|
||||
start-y (:start-y gradient)
|
||||
end-x (:end-x gradient)
|
||||
end-y (:end-y gradient)
|
||||
end-y (:end-y gradient)
|
||||
width (or (:width gradient) 0)
|
||||
stops (take shp/MAX-GRADIENT-STOPS (:stops gradient))
|
||||
type (if (= (:type gradient) :linear) 0x01 0x02)]
|
||||
(.setUint8 dview offset type true)
|
||||
(.setFloat32 dview (+ offset 4) start-x true)
|
||||
(.setFloat32 dview (+ offset 8) start-y true)
|
||||
(.setFloat32 dview (+ offset 12) end-x true)
|
||||
(.setFloat32 dview (+ offset 12) end-x true)
|
||||
(.setFloat32 dview (+ offset 16) end-y true)
|
||||
(.setFloat32 dview (+ offset 20) opacity true)
|
||||
(.setFloat32 dview (+ offset 24) width true)
|
||||
|
@ -60,8 +55,8 @@
|
|||
(+ offset FILL-BYTE-SIZE)
|
||||
(let [stop (first stops)
|
||||
hex-color (:color stop)
|
||||
opacity (:opacity stop)
|
||||
argb (clr/hex->u32argb hex-color opacity)
|
||||
stop-opacity (:opacity stop)
|
||||
argb (clr/hex->u32argb hex-color stop-opacity)
|
||||
stop-offset (:offset stop)]
|
||||
(.setUint32 dview loop-offset argb true)
|
||||
(.setFloat32 dview (+ loop-offset 4) stop-offset true)
|
||||
|
|
|
@ -150,7 +150,7 @@
|
|||
(api/set-shape-svg-raw-content (api/get-static-markup shape))
|
||||
|
||||
(= (:type shape) :text)
|
||||
(into [] (api/set-shape-text-content v)))
|
||||
(api/set-shape-text v))
|
||||
|
||||
:grow-type
|
||||
(api/set-shape-grow-type v)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue