mirror of
https://github.com/penpot/penpot.git
synced 2025-07-14 06:37:18 +02:00
🐛 Fix problem when exporting texts with gradients or opacity
This commit is contained in:
parent
bce0e9194c
commit
214c64c49e
7 changed files with 271 additions and 62 deletions
|
@ -23,7 +23,7 @@
|
|||
[app.renderer.bitmap :refer [create-cookie]]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(log/set-level "app.http.export-svg" :trace)
|
||||
(log/set-level "app.renderer.svg" :trace)
|
||||
|
||||
(defn- xml->clj
|
||||
[data]
|
||||
|
@ -129,7 +129,7 @@
|
|||
svgpath (path/join basepath (str basename ".svg"))]
|
||||
(-> (sh/run-cmd! (str "potrace --flat -b svg " pbmpath " -o " svgpath))
|
||||
(p/then (constantly svgpath)))))
|
||||
|
||||
|
||||
(generate-color-layer [ppmpath color]
|
||||
(log/trace :fn :generate-color-layer :ppmpath ppmpath :color color)
|
||||
(let [basepath (path/dirname ppmpath)
|
||||
|
@ -146,15 +146,61 @@
|
|||
{:color color
|
||||
:svgdata data}))))))
|
||||
|
||||
(join-color-layers [{:keys [x y width height] :as node} layers]
|
||||
(log/trace :fn :join-color-layers)
|
||||
(set-path-color [id color mapping node]
|
||||
(let [color-mapping (get mapping color)]
|
||||
(cond
|
||||
(and (some? color-mapping)
|
||||
(= "transparent" (get color-mapping "type")))
|
||||
(update node "attributes" assoc
|
||||
"fill" (get color-mapping "hex")
|
||||
"fill-opacity" (get color-mapping "opacity"))
|
||||
|
||||
(and (some? color-mapping)
|
||||
(= "gradient" (get color-mapping "type")))
|
||||
(update node "attributes" assoc
|
||||
"fill" (str "url(#gradient-" id "-" (subs color 1) ")"))
|
||||
|
||||
:else
|
||||
(update node "attributes" assoc "fill" color))))
|
||||
|
||||
(get-stops [data]
|
||||
(->> (get-in data ["gradient" "stops"])
|
||||
(mapv (fn [stop-data]
|
||||
{"type" "element"
|
||||
"name" "stop"
|
||||
"attributes" {"offset" (get stop-data "offset")
|
||||
"stop-color" (get stop-data "color")
|
||||
"stop-opacity" (get stop-data "opacity")}}))))
|
||||
|
||||
(data->gradient-def [id [color data]]
|
||||
(let [id (str "gradient-" id "-" (subs color 1))]
|
||||
(if (= type "linear")
|
||||
{"type" "element"
|
||||
"name" "linearGradient"
|
||||
"attributes" {"id" id "x1" "0.5" "y1" "1" "x2" "0.5" "y2" "0"}
|
||||
"elements" (get-stops data)}
|
||||
|
||||
{"type" "element"
|
||||
"name" "radialGradient"
|
||||
"attributes" {"id" id "cx" "0.5" "cy" "0.5" "r" "0.5"}
|
||||
"elements" (get-stops data)}
|
||||
)))
|
||||
|
||||
(get-gradients [id mapping]
|
||||
(->> mapping
|
||||
(filter (fn [[color data]]
|
||||
(= (get data "type") "gradient")))
|
||||
(mapv (partial data->gradient-def id))))
|
||||
|
||||
(join-color-layers [{:keys [id x y width height mapping] :as node} layers]
|
||||
(log/trace :fn :join-color-layers :mapping mapping)
|
||||
(loop [result (-> (:svgdata (first layers))
|
||||
(assoc "elements" []))
|
||||
layers (seq layers)]
|
||||
(if-let [{:keys [color svgdata]} (first layers)]
|
||||
(recur (->> (get svgdata "elements")
|
||||
(filter #(= (get % "name") "g"))
|
||||
(map #(update % "attributes" assoc "fill" color))
|
||||
(map (partial set-path-color id color mapping))
|
||||
(update result "elements" d/concat))
|
||||
(rest layers))
|
||||
|
||||
|
@ -166,22 +212,33 @@
|
|||
(parse-viewbox))
|
||||
transform (str/fmt "translate(%s, %s) scale(%s, %s)" x y
|
||||
(/ width (:width vbox))
|
||||
(/ height (:height vbox)))]
|
||||
(/ height (:height vbox)))
|
||||
|
||||
gradient-defs (get-gradients id mapping)
|
||||
|
||||
elements
|
||||
(->> (get result "elements")
|
||||
(mapv (fn [group]
|
||||
(let [paths (get group "elements")]
|
||||
(if (= 1 (count paths))
|
||||
(let [path (first paths)]
|
||||
(update path "attributes"
|
||||
(fn [attrs]
|
||||
(-> attrs
|
||||
(d/merge (get group "attributes"))
|
||||
(update "transform" #(str transform " " %))))))
|
||||
(update-in group ["attributes" "transform"] #(str transform " " %)))))))
|
||||
|
||||
|
||||
elements (cond->> elements
|
||||
(not (empty? gradient-defs))
|
||||
(d/concat [{"type" "element" "name" "defs" "attributes" {}
|
||||
"elements" gradient-defs}]))]
|
||||
|
||||
(-> result
|
||||
(assoc "name" "g")
|
||||
(assoc "attributes" {})
|
||||
(update "elements" (fn [elements]
|
||||
(mapv (fn [group]
|
||||
(let [paths (get group "elements")]
|
||||
(if (= 1 (count paths))
|
||||
(let [path (first paths)]
|
||||
(update path "attributes"
|
||||
(fn [attrs]
|
||||
(-> attrs
|
||||
(d/merge (get group "attributes"))
|
||||
(update "transform" #(str transform " " %))))))
|
||||
(update-in group ["attributes" "transform"] #(str transform " " %)))))
|
||||
elements))))))))
|
||||
(assoc "elements" elements))))))
|
||||
|
||||
(convert-to-svg [ppmpath {:keys [colors] :as node}]
|
||||
(log/trace :fn :convert-to-svg :ppmpath ppmpath :colors colors)
|
||||
|
@ -201,25 +258,28 @@
|
|||
:svgdata svgdata))))
|
||||
|
||||
(extract-element-attrs [^js element]
|
||||
(let [^js attrs (.. element -attributes)
|
||||
^js colors (.. element -dataset -colors)]
|
||||
#js {:id (.. attrs -id -value)
|
||||
:x (.. attrs -x -value)
|
||||
:y (.. attrs -y -value)
|
||||
:width (.. attrs -width -value)
|
||||
:height (.. attrs -height -value)
|
||||
:colors (.split colors ",")}))
|
||||
(let [^js attrs (.. element -attributes)
|
||||
^js colors (.. element -dataset -colors)
|
||||
^js mapping (.. element -dataset -mapping)]
|
||||
#js {:id (.. attrs -id -value)
|
||||
:x (.. attrs -x -value)
|
||||
:y (.. attrs -y -value)
|
||||
:width (.. attrs -width -value)
|
||||
:height (.. attrs -height -value)
|
||||
:colors (.split colors ",")
|
||||
:mapping (js/JSON.parse mapping)}))
|
||||
|
||||
(extract-single-node [[shot node]]
|
||||
(log/trace :fn :extract-single-node)
|
||||
|
||||
(p/let [attrs (bw/eval! node extract-element-attrs)]
|
||||
{:id (unchecked-get attrs "id")
|
||||
:x (unchecked-get attrs "x")
|
||||
:y (unchecked-get attrs "y")
|
||||
:width (unchecked-get attrs "width")
|
||||
:height (unchecked-get attrs "height")
|
||||
:colors (vec (unchecked-get attrs "colors"))
|
||||
{:id (unchecked-get attrs "id")
|
||||
:x (unchecked-get attrs "x")
|
||||
:y (unchecked-get attrs "y")
|
||||
:width (unchecked-get attrs "width")
|
||||
:height (unchecked-get attrs "height")
|
||||
:colors (vec (unchecked-get attrs "colors"))
|
||||
:mapping (js->clj (unchecked-get attrs "mapping"))
|
||||
:data shot}))
|
||||
|
||||
(resolve-text-node [page node]
|
||||
|
@ -313,3 +373,4 @@
|
|||
".svg"))
|
||||
:length (alength content)
|
||||
:mime-type "image/svg+xml"}))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue