mirror of
https://github.com/penpot/penpot.git
synced 2025-01-24 07:29:08 -05:00
🐛 Fix problems with old texts
This commit is contained in:
parent
ec63d23666
commit
64ffa9bb3f
10 changed files with 107 additions and 77 deletions
|
@ -224,7 +224,7 @@
|
|||
:internal.shape.text.position-data/font-size
|
||||
:internal.shape.text.position-data/font-style
|
||||
:internal.shape.text.position-data/font-weight
|
||||
:internal.shape.text.position-data/rtl?
|
||||
:internal.shape.text.position-data/rtl
|
||||
:internal.shape.text.position-data/text
|
||||
:internal.shape.text.position-data/text-decoration
|
||||
:internal.shape.text.position-data/text-transform]
|
||||
|
@ -243,7 +243,7 @@
|
|||
(s/def :internal.shape.text.position-data/font-size string?)
|
||||
(s/def :internal.shape.text.position-data/font-style string?)
|
||||
(s/def :internal.shape.text.position-data/font-weight string?)
|
||||
(s/def :internal.shape.text.position-data/rtl? boolean?)
|
||||
(s/def :internal.shape.text.position-data/rtl boolean?)
|
||||
(s/def :internal.shape.text.position-data/text string?)
|
||||
(s/def :internal.shape.text.position-data/text-decoration string?)
|
||||
(s/def :internal.shape.text.position-data/text-transform string?)
|
||||
|
|
|
@ -117,13 +117,31 @@
|
|||
|
||||
;; --- Helpers
|
||||
|
||||
(defn to-new-fills
|
||||
[data]
|
||||
[(d/without-nils (select-keys data [:fill-color :fill-opacity :fill-color-gradient :fill-color-ref-id :fill-color-ref-file]))])
|
||||
|
||||
(defn- shape-current-values
|
||||
[shape pred attrs]
|
||||
(let [root (:content shape)
|
||||
nodes (->> (txt/node-seq pred root)
|
||||
(map #(if (txt/is-text-node? %)
|
||||
(merge txt/default-text-attrs %)
|
||||
%)))]
|
||||
(map (fn [node]
|
||||
(if (txt/is-text-node? node)
|
||||
(let [fills
|
||||
(cond
|
||||
(or (some? (:fill-color node))
|
||||
(some? (:fill-opacity node))
|
||||
(some? (:fill-color-gradient node)))
|
||||
(to-new-fills node)
|
||||
|
||||
(some? (:fills node))
|
||||
(:fills node)
|
||||
|
||||
:else
|
||||
(:fills txt/default-text-attrs))]
|
||||
(-> (merge txt/default-text-attrs node)
|
||||
(assoc :fills fills)))
|
||||
node))))]
|
||||
(attrs/get-attrs-multi nodes attrs)))
|
||||
|
||||
(defn current-root-values
|
||||
|
@ -140,8 +158,10 @@
|
|||
(defn current-text-values
|
||||
[{:keys [editor-state attrs shape]}]
|
||||
(if editor-state
|
||||
(-> (ted/get-editor-current-inline-styles editor-state)
|
||||
(select-keys attrs))
|
||||
(let [result (-> (ted/get-editor-current-inline-styles editor-state)
|
||||
(select-keys attrs))
|
||||
result (if (empty? result) txt/default-text-attrs result)]
|
||||
result)
|
||||
(shape-current-values shape txt/is-text-node? attrs)))
|
||||
|
||||
|
||||
|
@ -220,24 +240,27 @@
|
|||
(cph/group-shape? shape) (cph/get-children-ids objects id))]
|
||||
(rx/of (dch/update-shapes shape-ids #(update-text-content % update-node? attrs/merge attrs))))))))
|
||||
|
||||
(defn migrate-node
|
||||
[node]
|
||||
(let [color-attrs (select-keys node [:fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient])]
|
||||
(cond-> node
|
||||
(d/not-empty? color-attrs)
|
||||
(-> (dissoc :fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient)
|
||||
(assoc :fills [color-attrs]))
|
||||
|
||||
(nil? (:fills node))
|
||||
(assoc :fills (:fills txt/default-text-attrs)))))
|
||||
|
||||
(defn migrate-content
|
||||
[content]
|
||||
(txt/transform-nodes
|
||||
#(or (txt/is-text-node? %) (txt/is-paragraph-node? %))
|
||||
(fn [node]
|
||||
(let [color-attrs (select-keys node [:fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient])]
|
||||
(cond-> node
|
||||
(d/not-empty? color-attrs)
|
||||
(-> (dissoc :fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient)
|
||||
(assoc :fills [color-attrs])))))
|
||||
content))
|
||||
(txt/transform-nodes (some-fn txt/is-text-node? txt/is-paragraph-node?) migrate-node content))
|
||||
|
||||
(defn update-text-with-function
|
||||
[id update-node-fn]
|
||||
(ptk/reify ::update-text-with-function
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(d/update-in-when state [:workspace-editor-state id] ted/update-editor-current-inline-styles-fn update-node-fn))
|
||||
(d/update-in-when state [:workspace-editor-state id] ted/update-editor-current-inline-styles-fn (comp update-node-fn migrate-node)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
|
@ -245,10 +268,7 @@
|
|||
(let [objects (wsh/lookup-page-objects state)
|
||||
shape (get objects id)
|
||||
|
||||
update-node?
|
||||
(fn [node]
|
||||
(or (txt/is-text-node? node)
|
||||
(txt/is-paragraph-node? node)))
|
||||
update-node? (some-fn txt/is-text-node? txt/is-paragraph-node?)
|
||||
|
||||
shape-ids
|
||||
(cond
|
||||
|
|
|
@ -48,11 +48,10 @@
|
|||
(mf/set-ref-val! prev-obs-ref mutation-obs)
|
||||
(.observe mutation-obs node options))))))]
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
(fn []
|
||||
(when-let [^js prev-obs (mf/ref-val prev-obs-ref)]
|
||||
(.disconnect prev-obs)
|
||||
(mf/set-ref-val! prev-obs-ref nil)))))
|
||||
(mf/with-effect
|
||||
(fn []
|
||||
(when-let [^js prev-obs (mf/ref-val prev-obs-ref)]
|
||||
(.disconnect prev-obs)
|
||||
(mf/set-ref-val! prev-obs-ref nil))))
|
||||
|
||||
[node-ref set-node]))
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
(ns app.main.ui.render
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
|
@ -92,12 +93,11 @@
|
|||
(mf/with-memo [objects]
|
||||
(render/shape-wrapper-factory objects))
|
||||
|
||||
text-shapes
|
||||
(->> objects
|
||||
(filter (fn [[_ shape]] (= :text (:type shape))))
|
||||
(mapv second))
|
||||
is-text? (fn [shape] (= :text (:type shape)))
|
||||
|
||||
render-texts? (and render-texts? (some #(nil? (:position-data %)) text-shapes))]
|
||||
text-shapes (sequence (comp (map second) (filter is-text?)) objects)
|
||||
|
||||
render-texts? (and render-texts? (d/seek (comp nil? :position-data) text-shapes))]
|
||||
|
||||
(mf/with-effect [width height]
|
||||
(dom/set-page-style {:size (str (mth/ceil width) "px "
|
||||
|
|
|
@ -89,11 +89,11 @@
|
|||
(cond
|
||||
(contains? shape :fill-image)
|
||||
(let [fill-image-id (str "fill-image-" render-id)]
|
||||
{:fill (str/format "url(#%s)" fill-image-id)})
|
||||
{:fill (str "url(#" fill-image-id ")")})
|
||||
|
||||
(contains? shape :fill-color-gradient)
|
||||
(let [fill-color-gradient-id (str "fill-color-gradient_" render-id (if index (str "_" index) ""))]
|
||||
{:fill (str/format "url(#%s)" fill-color-gradient-id)})
|
||||
{:fill (str "url(#" fill-color-gradient-id ")")})
|
||||
|
||||
(contains? shape :fill-color)
|
||||
{:fill (:fill-color shape)}
|
||||
|
|
|
@ -45,19 +45,18 @@
|
|||
(= :path (:type shape))
|
||||
(obj/set! "patternTransform" transform))]
|
||||
|
||||
[:*
|
||||
(for [[_shape-index shape] (d/enumerate (or (:position-data shape) [shape]))]
|
||||
(for [[shape-index shape] (d/enumerate (or (:position-data shape) [shape]))]
|
||||
[:*
|
||||
(for [[fill-index value] (-> (d/enumerate (:fills shape [])) reverse)]
|
||||
(cond (some? (:fill-color-gradient value))
|
||||
(case (d/name (:type (:fill-color-gradient value)))
|
||||
"linear" [:> grad/linear-gradient #js {:id (str "fill-color-gradient_" render-id "_" fill-index)
|
||||
:gradient (:fill-color-gradient value)
|
||||
:shape shape}]
|
||||
"radial" [:> grad/radial-gradient #js {:id (str "fill-color-gradient_" render-id "_" fill-index)
|
||||
:gradient (:fill-color-gradient value)
|
||||
:shape shape}]))))
|
||||
(when (some? (:fill-color-gradient value))
|
||||
(let [props #js {:id (str "fill-color-gradient_" render-id "_" fill-index)
|
||||
:gradient (:fill-color-gradient value)
|
||||
:shape shape}]
|
||||
(case (d/name (:type (:fill-color-gradient value)))
|
||||
"linear" [:> grad/linear-gradient props]
|
||||
"radial" [:> grad/radial-gradient props]))))
|
||||
|
||||
|
||||
(for [[shape-index shape] (d/enumerate (or (:position-data shape) [shape]))]
|
||||
(let [fill-id (str "fill-" shape-index "-" render-id)]
|
||||
[:> :pattern (-> (obj/clone pattern-attrs)
|
||||
(obj/set! "id" fill-id))
|
||||
|
@ -70,4 +69,4 @@
|
|||
(when has-image
|
||||
[:image {:xlinkHref (get embed uri uri)
|
||||
:width width
|
||||
:height height}])]]))]))))
|
||||
:height height}])]])])))))
|
||||
|
|
|
@ -87,11 +87,22 @@
|
|||
:caretColor (or text-color "black")
|
||||
:overflowWrap "initial"}
|
||||
|
||||
base (-> base
|
||||
(obj/set! "--fills" (transit/encode-str (:fills data)))
|
||||
#_(obj/set! "--fill-color" fill-color)
|
||||
#_(obj/set! "--fill-color-gradient" (transit/encode-str (:fill-color-gradient data)))
|
||||
#_(obj/set! "--fill-opacity" fill-opacity))]
|
||||
fills
|
||||
(cond
|
||||
(some? (:fills data))
|
||||
(:fills data)
|
||||
|
||||
(or (some? (:fill-color data))
|
||||
(some? (:fill-opacity data))
|
||||
(some? (:fill-color-gradient data)))
|
||||
[(d/without-nils (select-keys data [:fill-color :fill-opacity :fill-color-gradient :fill-color-ref-id :fill-color-ref-file]))]
|
||||
|
||||
(nil? (:fills data))
|
||||
[{:fill-color "#000000" :fill-opacity 1}])
|
||||
|
||||
base (cond-> base
|
||||
(some? fills)
|
||||
(obj/set! "--fills" (transit/encode-str fills)))]
|
||||
|
||||
(when (and (string? letter-spacing)
|
||||
(pos? (alength letter-spacing)))
|
||||
|
|
|
@ -57,10 +57,9 @@
|
|||
:textTransform (:text-transform data)
|
||||
:textDecoration (:text-decoration data)
|
||||
:fontStyle (:font-style data)
|
||||
:direction (if (:rtl? data) "rtl" "ltr")
|
||||
:direction (if (:rtl data) "rtl" "ltr")
|
||||
:whiteSpace "pre"}
|
||||
(obj/set! "fill" (str "url(#fill-" index "-" render-id ")"))
|
||||
#_(attrs/add-fill data (get-gradient-id index)))})]
|
||||
(obj/set! "fill" (str "url(#fill-" index "-" render-id ")")))})]
|
||||
[:& shape-custom-stroke {:shape shape :index index}
|
||||
[:> :text props (:text data)]]))]]))
|
||||
|
||||
|
|
|
@ -131,25 +131,26 @@
|
|||
sid-ref (mf/use-ref nil)
|
||||
|
||||
handle-change-foreign-object
|
||||
(fn [node]
|
||||
(when-let [position-data (utp/calc-position-data node)]
|
||||
(let [parent (dom/get-parent node)
|
||||
parent-transform (dom/get-attribute parent "transform")
|
||||
node-transform (dom/get-attribute node "transform")
|
||||
(mf/use-callback
|
||||
(fn [node]
|
||||
(when-let [position-data (utp/calc-position-data node)]
|
||||
(let [parent (dom/get-parent node)
|
||||
parent-transform (dom/get-attribute parent "transform")
|
||||
node-transform (dom/get-attribute node "transform")
|
||||
|
||||
parent-mtx (usvg/parse-transform parent-transform)
|
||||
node-mtx (usvg/parse-transform node-transform)
|
||||
parent-mtx (usvg/parse-transform parent-transform)
|
||||
node-mtx (usvg/parse-transform node-transform)
|
||||
|
||||
;; We need to see what transformation is applied in the DOM to reverse it
|
||||
;; before calculating the position data
|
||||
mtx (-> (gmt/multiply parent-mtx node-mtx)
|
||||
(gmt/inverse))
|
||||
;; We need to see what transformation is applied in the DOM to reverse it
|
||||
;; before calculating the position data
|
||||
mtx (-> (gmt/multiply parent-mtx node-mtx)
|
||||
(gmt/inverse))
|
||||
|
||||
position-data
|
||||
(->> position-data
|
||||
(mapv #(merge % (-> (select-keys % [:x :y :width :height])
|
||||
(gsh/transform-rect mtx)))))]
|
||||
(reset! local-position-data position-data))))
|
||||
position-data
|
||||
(->> position-data
|
||||
(mapv #(merge % (-> (select-keys % [:x :y :width :height])
|
||||
(gsh/transform-rect mtx)))))]
|
||||
(reset! local-position-data position-data)))))
|
||||
|
||||
[node-ref on-change-node] (use-mutable-observer handle-change-foreign-object)
|
||||
|
||||
|
|
|
@ -22,9 +22,10 @@
|
|||
(.setEnd range node end-i)
|
||||
(.getClientRects range)))
|
||||
|
||||
;; TODO: Evaluate to change this function to Javascript
|
||||
(defn parse-text-nodes
|
||||
"Given a text node retrieves the rectangles for everyone of its paragraphs and its text."
|
||||
[parent-node rtl? text-node]
|
||||
[parent-node rtl text-node]
|
||||
|
||||
(let [content (.-textContent text-node)
|
||||
text-size (.-length content)]
|
||||
|
@ -45,7 +46,7 @@
|
|||
;; If the rects increase means we're in a new paragraph
|
||||
(if (> (.-length rects) 1)
|
||||
(let [entry {:node parent-node
|
||||
:position (dom/bounding-rect->rect (if rtl? (second rects) (first rects)))
|
||||
:position (dom/bounding-rect->rect (if rtl (second rects) (first rects)))
|
||||
:text current}]
|
||||
(recur to-i to-i "" (conj result entry)))
|
||||
(recur from-i (inc to-i) (str current (nth content to-i)) result)))))))
|
||||
|
@ -86,9 +87,9 @@
|
|||
(->> text-nodes
|
||||
(mapcat
|
||||
(fn [parent-node]
|
||||
(let [rtl? (= "rtl" (.-dir (.-parentElement parent-node)))]
|
||||
(let [rtl (= "rtl" (.-dir (.-parentElement parent-node)))]
|
||||
(->> (.-childNodes parent-node)
|
||||
(mapcat #(parse-text-nodes parent-node rtl? %))))))
|
||||
(mapcat #(parse-text-nodes parent-node rtl %))))))
|
||||
(mapv #(update % :position translate-rect))))))
|
||||
|
||||
(defn calc-position-data
|
||||
|
@ -101,15 +102,15 @@
|
|||
(->> text-data
|
||||
(mapv (fn [{:keys [node position text]}]
|
||||
(let [{:keys [x y width height]} position
|
||||
rtl? (= "rtl" (.-dir (.-parentElement ^js node)))
|
||||
rtl (= "rtl" (.-dir (.-parentElement ^js node)))
|
||||
styles (js/getComputedStyle ^js node)
|
||||
get (fn [prop]
|
||||
(let [value (.getPropertyValue styles prop)]
|
||||
(when (and value (not= value ""))
|
||||
value)))]
|
||||
(d/without-nils
|
||||
{:rtl? rtl?
|
||||
:x (if rtl? (+ x width) x)
|
||||
{:rtl rtl
|
||||
:x (if rtl (+ x width) x)
|
||||
:y (+ y height)
|
||||
:width width
|
||||
:height height
|
||||
|
|
Loading…
Add table
Reference in a new issue