0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-13 16:21:57 -05:00

🐛 Some fixes to SVG imports

This commit is contained in:
alonso.torres 2022-03-28 16:32:56 +02:00 committed by Andrés Moya
parent 3301148da6
commit 61c111d5ae
9 changed files with 162 additions and 74 deletions

View file

@ -65,6 +65,7 @@
- Fix paste ordering for frames not being respected [Taiga #3097](https://tree.taiga.io/project/penpot/issue/3097)
- Improved command support for MacOS [Taiga #2789](https://tree.taiga.io/project/penpot/issue/2789)
- Fix shift+2 shortcut in MacOS with non-english keyboards [Taiga #3038](https://tree.taiga.io/project/penpot/issue/3038)
- Some fixes to SVG imports [Taiga #3122](https://tree.taiga.io/project/penpot/issue/3122) [#1720](https://github.com/penpot/penpot/issues/1720) [Taiga #2884](https://tree.taiga.io/project/penpot/issue/2884)
### :arrow_up: Deps updates
### :heart: Community contributions by (Thank you!)

View file

@ -105,6 +105,7 @@
(dm/export gco/transform-points)
(dm/export gpr/make-rect)
(dm/export gpr/make-selrect)
(dm/export gpr/rect->selrect)
(dm/export gpr/rect->points)
(dm/export gpr/points->selrect)

View file

@ -70,32 +70,30 @@
:else (str tag))))
(defn setup-fill [shape]
(if (some? (:fills shape))
shape
(cond-> shape
;; Color present as attribute
(uc/color? (str/trim (get-in shape [:svg-attrs :fill])))
(-> (update :svg-attrs dissoc :fill)
(assoc-in [:fills 0 :fill-color] (-> (get-in shape [:svg-attrs :fill])
(str/trim)
(uc/parse-color))))
(cond-> shape
;; Color present as attribute
(uc/color? (str/trim (get-in shape [:svg-attrs :fill])))
(-> (update :svg-attrs dissoc :fill)
(assoc-in [:fills 0 :fill-color] (-> (get-in shape [:svg-attrs :fill])
(str/trim)
(uc/parse-color))))
;; Color present as style
(uc/color? (str/trim (get-in shape [:svg-attrs :style :fill])))
(-> (update-in [:svg-attrs :style] dissoc :fill)
(assoc-in [:fills 0 :fill-color] (-> (get-in shape [:svg-attrs :style :fill])
(str/trim)
(uc/parse-color))))
;; Color present as style
(uc/color? (str/trim (get-in shape [:svg-attrs :style :fill])))
(-> (update-in [:svg-attrs :style] dissoc :fill)
(assoc-in [:fills 0 :fill-color] (-> (get-in shape [:svg-attrs :style :fill])
(str/trim)
(uc/parse-color))))
(get-in shape [:svg-attrs :fill-opacity])
(-> (update :svg-attrs dissoc :fill-opacity)
(assoc-in [:fills 0 :fill-opacity] (-> (get-in shape [:svg-attrs :fill-opacity])
(d/parse-double))))
(get-in shape [:svg-attrs :fill-opacity])
(-> (update :svg-attrs dissoc :fill-opacity)
(assoc-in [:fills 0 :fill-opacity] (-> (get-in shape [:svg-attrs :fill-opacity])
(d/parse-double))))
(get-in shape [:svg-attrs :style :fill-opacity])
(-> (update-in [:svg-attrs :style] dissoc :fill-opacity)
(assoc-in [:fills 0 :fill-opacity] (-> (get-in shape [:svg-attrs :style :fill-opacity])
(d/parse-double)))))))
(get-in shape [:svg-attrs :style :fill-opacity])
(-> (update-in [:svg-attrs :style] dissoc :fill-opacity)
(assoc-in [:fills 0 :fill-opacity] (-> (get-in shape [:svg-attrs :style :fill-opacity])
(d/parse-double))))))
(defn setup-stroke [shape]
(let [stroke-linecap (-> (or (get-in shape [:svg-attrs :stroke-linecap])

View file

@ -6,9 +6,9 @@
(ns app.main.ui.shapes.svg-defs
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]
[app.main.ui.shapes.filters :as f]
[app.util.object :as obj]
[app.util.svg :as usvg]
[rumext.alpha :as mf]))
@ -21,24 +21,7 @@
(str transform-matrix " " val)
(str transform-matrix)))))
(defn transform-region [attrs transform]
(let [{x-str :x y-str :y width-str :width height-str :height} attrs
data (map d/parse-double [x-str y-str width-str height-str])]
(if (every? (comp not nil?) data)
(let [[x y width height] data
p1 (-> (gpt/point x y)
(gpt/transform transform))
p2 (-> (gpt/point (+ x width) (+ y height))
(gpt/transform transform))]
(assoc attrs
:x (:x p1)
:y (:y p1)
:width (- (:x p2) (:x p1))
:height (- (:y p2) (:y p1))))
attrs)))
(mf/defc svg-node [{:keys [node prefix-id transform]}]
(mf/defc svg-node [{:keys [type node prefix-id transform bounds]}]
(cond
(string? node) node
@ -63,23 +46,34 @@
attrs (-> attrs
(usvg/update-attr-ids prefix-id)
(usvg/clean-attrs)
;; This clasname will be used to change the transform on the viewport
;; only necessary for groups because shapes have their own transform
(cond-> (and (or transform-gradient?
transform-pattern?
transform-clippath?
transform-filter?
transform-mask?)
(= :group type))
(update :className #(if % (dm/str % " svg-def") "svg-def")))
(cond->
transform-gradient? (add-matrix :gradientTransform transform)
transform-pattern? (add-matrix :patternTransform transform)
transform-clippath? (add-matrix :transform transform)
(or transform-filter?
transform-mask?) (transform-region transform)))
transform-mask?) (merge attrs bounds)))
[wrapper wrapper-props] (if (= tag :mask)
["g" #js {:transform (str transform)}]
["g" #js {:className "svg-mask-wrapper"
:transform (str transform)}]
[mf/Fragment (obj/new)])]
[:> (name tag) (clj->js attrs)
[:> wrapper wrapper-props
(for [node content] [:& svg-node {:node node
(for [node content] [:& svg-node {:type type
:node node
:prefix-id prefix-id
:transform transform}])]])))
:transform transform
:bounds bounds}])]])))
(mf/defc svg-defs [{:keys [shape render-id]}]
(let [svg-defs (:svg-defs shape)
@ -91,8 +85,8 @@
(usvg/svg-transform-matrix shape)))
;; Paths doesn't have transform so we have to transform its gradients
transform (if (contains? shape :svg-transform)
(gmt/multiply transform (or (:svg-transform shape) (gmt/matrix)))
transform (if (some? (:svg-transform shape))
(gmt/multiply transform (:svg-transform shape))
transform)
prefix-id
@ -103,7 +97,9 @@
;; TODO: no key?
(when (seq svg-defs)
(for [svg-def (vals svg-defs)]
[:& svg-node {:node svg-def
[:& svg-node {:type (:type shape)
:node svg-def
:prefix-id prefix-id
:transform transform}]))))
:transform transform
:bounds (f/get-filters-bounds shape)}]))))

View file

@ -117,8 +117,8 @@
;; Note that the "indeterminate" attribute only may be set by code, not as a static attribute.
;; See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#attr-indeterminate
(if (= hide-fill-on-export? :multiple)
(dom/set-attribute checkbox "indeterminate" true)
(dom/remove-attribute checkbox "indeterminate")))))
(dom/set-attribute! checkbox "indeterminate" true)
(dom/remove-attribute! checkbox "indeterminate")))))
[:div.element-set
[:div.element-set-title

View file

@ -201,25 +201,43 @@
(mf/use-memo
(mf/deps modifiers)
(fn []
(d/mapm (fn [id {modifiers :modifiers}]
(let [center (gsh/center-shape (get objects id))]
(gsh/modifiers->transform center modifiers)))
modifiers)))
(when (some? modifiers)
(d/mapm (fn [id {modifiers :modifiers}]
(let [center (gsh/center-shape (get objects id))]
(gsh/modifiers->transform center modifiers)))
modifiers))))
shapes
(mf/use-memo
(mf/deps transforms)
(fn []
(->> (keys transforms)
(mapv (d/getf objects)))))]
(mapv (d/getf objects)))))
prev-shapes (mf/use-var nil)
prev-modifiers (mf/use-var nil)
prev-transforms (mf/use-var nil)]
;; Layout effect is important so the code is executed before the modifiers
;; are applied to the shape
(mf/use-layout-effect
(mf/deps transforms)
(fn []
(utils/update-transform shapes transforms modifiers)
#(utils/remove-transform shapes)))))
(when (and (nil? @prev-transforms)
(some? transforms))
(utils/start-transform! shapes))
(when (some? modifiers)
(utils/update-transform! shapes transforms modifiers))
(when (and (some? @prev-modifiers)
(not (some? modifiers)))
(utils/remove-transform! @prev-shapes))
(reset! prev-modifiers modifiers)
(reset! prev-transforms transforms)
(reset! prev-shapes shapes)))))
(defn inside-vbox [vbox objects frame-id]
(let [frame (get objects frame-id)]

View file

@ -10,6 +10,7 @@
[app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.main.ui.cursors :as cur]
[app.util.dom :as dom]))
@ -100,7 +101,10 @@
(dom/query shape-node ".mask-shape")]
group?
[]
(let [shape-defs (dom/query shape-node "defs")]
(d/concat-vec
(dom/query-all shape-defs ".svg-def")
(dom/query-all shape-defs ".svg-mask-wrapper")))
text?
[shape-node
@ -112,7 +116,59 @@
:else
[shape-node])))
(defn update-transform [shapes transforms modifiers]
(defn transform-region!
[node modifiers]
(let [{:keys [x y width height]}
(-> (gsh/make-selrect
(-> (dom/get-attribute node "data-old-x") d/parse-double)
(-> (dom/get-attribute node "data-old-y") d/parse-double)
(-> (dom/get-attribute node "data-old-width") d/parse-double)
(-> (dom/get-attribute node "data-old-height") d/parse-double))
(gsh/transform-selrect modifiers))]
(dom/set-attribute! node "x" x)
(dom/set-attribute! node "y" y)
(dom/set-attribute! node "width" width)
(dom/set-attribute! node "height" height)))
(defn start-transform!
[shapes]
(doseq [shape shapes]
(when-let [nodes (get-nodes shape)]
(doseq [node nodes]
(let [old-transform (dom/get-attribute node "transform")]
(when (some? old-transform)
(dom/set-attribute! node "data-old-transform" old-transform))
(when (or (= (dom/get-tag-name node) "linearGradient")
(= (dom/get-tag-name node) "radialGradient"))
(let [gradient-transform (dom/get-attribute node "gradientTransform")]
(when (some? gradient-transform)
(dom/set-attribute! node "data-old-gradientTransform" gradient-transform))))
(when (= (dom/get-tag-name node) "pattern")
(let [pattern-transform (dom/get-attribute node "patternTransform")]
(when (some? pattern-transform)
(dom/set-attribute! node "data-old-patternTransform" pattern-transform))))
(when (or (= (dom/get-tag-name node) "mask")
(= (dom/get-tag-name node) "filter"))
(dom/set-attribute! node "data-old-x" (dom/get-attribute node "x"))
(dom/set-attribute! node "data-old-y" (dom/get-attribute node "y"))
(dom/set-attribute! node "data-old-width" (dom/get-attribute node "width"))
(dom/set-attribute! node "data-old-height" (dom/get-attribute node "height"))))))))
(defn set-transform-att!
[node att value]
(let [old-att (dom/get-attribute node (dm/str "data-old-" att))
new-value (if (some? old-att)
(dm/str value " " old-att)
(str value))]
(dom/set-attribute! node att (str new-value))))
(defn update-transform!
[shapes transforms modifiers]
(doseq [{:keys [id type] :as shape} shapes]
(when-let [nodes (get-nodes shape)]
(let [transform (get transforms id)
@ -127,24 +183,38 @@
(doseq [node nodes]
(cond
(or (dom/class? node "text-shape") (dom/class? node "text-svg"))
;; Text shapes need special treatment because their resize only change
;; the text area, not the change size/position
(or (dom/class? node "text-shape")
(dom/class? node "text-svg"))
(when (some? text-transform)
(dom/set-attribute node "transform" (str text-transform)))
(set-transform-att! node "transform" text-transform))
(or (= (dom/get-tag-name node) "foreignObject")
(dom/class? node "text-clip"))
(let [cur-width (dom/get-attribute node "width")
cur-height (dom/get-attribute node "height")]
(when (and (some? text-width) (not= cur-width text-width))
(dom/set-attribute node "width" text-width))
(dom/set-attribute! node "width" text-width))
(when (and (some? text-height) (not= cur-height text-height))
(dom/set-attribute node "height" text-height)))
(dom/set-attribute! node "height" text-height)))
(or (= (dom/get-tag-name node) "mask")
(= (dom/get-tag-name node) "filter"))
(transform-region! node modifiers)
(or (= (dom/get-tag-name node) "linearGradient")
(= (dom/get-tag-name node) "radialGradient"))
(set-transform-att! node "gradientTransform" transform)
(= (dom/get-tag-name node) "pattern")
(set-transform-att! node "patternTransform" transform)
(and (some? transform) (some? node))
(dom/set-attribute node "transform" (str transform))))))))
(set-transform-att! node "transform" transform)))))))
(defn remove-transform [shapes]
(defn remove-transform!
[shapes]
(doseq [shape shapes]
(when-let [nodes (get-nodes shape)]
(doseq [node nodes]
@ -155,7 +225,10 @@
nil
:else
(dom/remove-attribute node "transform")))))))
(let [old-transform (dom/get-attribute node "data-old-transform")]
(when-not (some? old-transform)
(dom/remove-attribute! node "data-old-transform")
(dom/remove-attribute! node "transform")))))))))
(defn format-viewbox [vbox]
(dm/str (:x vbox 0) " "

View file

@ -415,11 +415,11 @@
"application/pdf" "pdf"
nil))
(defn set-attribute [^js node ^string attr value]
(defn set-attribute! [^js node ^string attr value]
(when (some? node)
(.setAttribute node attr value)))
(defn remove-attribute [^js node ^string attr]
(defn remove-attribute! [^js node ^string attr]
(when (some? node)
(.removeAttribute node attr)))

View file

@ -715,7 +715,8 @@
(gmt/matrix)
;; Paths doesn't have transform so we have to transform its gradients
(if (= :path (:type shape))
(if (or (= :path (:type shape))
(= :group (:type shape)))
(gsh/transform-matrix shape)
(gmt/matrix))