From dd15bf732805c52c04364fad9196555c8beb40e4 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 11 Jun 2021 15:47:51 +0200 Subject: [PATCH] :sparkles: Adds flip,proportion and rotation --- common/src/app/common/geom/shapes/path.cljc | 3 +- frontend/src/app/main/ui/shapes/export.cljs | 76 +++++++----- frontend/src/app/util/import/parser.cljc | 129 +++++++++++++------- 3 files changed, 130 insertions(+), 78 deletions(-) diff --git a/common/src/app/common/geom/shapes/path.cljc b/common/src/app/common/geom/shapes/path.cljc index ae2d1d6f3..ff39fa7db 100644 --- a/common/src/app/common/geom/shapes/path.cljc +++ b/common/src/app/common/geom/shapes/path.cljc @@ -156,7 +156,8 @@ (mapv #(update % :params transform-params) content))) -(defn transform-content [content transform] +(defn transform-content + [content transform] (let [set-tr (fn [params px py] (let [tr-point (-> (gpt/point (get params px) (get params py)) (gpt/transform transform))] diff --git a/frontend/src/app/main/ui/shapes/export.cljs b/frontend/src/app/main/ui/shapes/export.cljs index 196061efb..6cda48b11 100644 --- a/frontend/src/app/main/ui/shapes/export.cljs +++ b/frontend/src/app/main/ui/shapes/export.cljs @@ -8,6 +8,7 @@ (:require [app.common.data :as d] [app.common.geom.matrix :as gmt] + [app.common.geom.shapes :as gsh] [app.util.json :as json] [app.util.object :as obj] [app.util.svg :as usvg] @@ -29,43 +30,58 @@ :else nil)) +(defn bool->str [val] + (when (some? val) (str val))) + (defn add-data "Adds as metadata properties that we cannot deduce from the exported SVG" [props shape] - (let [add! - (fn [props attr val] - (let [ns-attr (str "penpot:" (-> attr d/name))] - (-> props - (obj/set! ns-attr val)))) - frame? (= :frame (:type shape)) - group? (= :group (:type shape)) - rect? (= :rect (:type shape)) - text? (= :text (:type shape)) - mask? (and group? (:masked-group? shape))] - (-> props - (add! :name (-> shape :name)) - (add! :blocked (-> shape (:blocked false) str)) - (add! :hidden (-> shape (:hidden false) str)) - (add! :type (-> shape :type d/name)) + (letfn [(add! + ([props attr] + (add! props attr str)) - (add! :stroke-style (-> shape (:stroke-style :none) d/name)) - (add! :stroke-alignment (-> shape (:stroke-alignment :center) d/name)) + ([props attr trfn] + (let [val (get shape attr) + val (if (keyword? val) (d/name val) val) + ns-attr (str "penpot:" (-> attr d/name))] + (cond-> props + (some? val) + (obj/set! ns-attr (trfn val))))))] + (let [frame? (= :frame (:type shape)) + group? (= :group (:type shape)) + rect? (= :rect (:type shape)) + text? (= :text (:type shape)) + mask? (and group? (:masked-group? shape)) + center (gsh/center-shape shape)] + (-> props + (add! :name) + (add! :blocked) + (add! :hidden) + (add! :type) + (add! :stroke-style) + (add! :stroke-alignment) + (add! :transform) + (add! :transform-inverse) + (add! :flip-x) + (add! :flip-y) + (add! :proportion) + (add! :proportion-lock) + (add! :rotation) + (obj/set! "penpot:center-x" (-> center :x str)) + (obj/set! "penpot:center-y" (-> center :y str)) - (add! :transform (-> shape (:transform (gmt/matrix)) str)) - (add! :transform-inverse (-> shape (:transform-inverse (gmt/matrix)) str)) + (cond-> (and rect? (some? (:r1 shape))) + (-> (add! :r1) + (add! :r2) + (add! :r3) + (add! :r4))) - (cond-> (and rect? (some? (:r1 shape))) - (-> (add! :r1 (-> shape (:r1 0) str)) - (add! :r2 (-> shape (:r2 0) str)) - (add! :r3 (-> shape (:r3 0) str)) - (add! :r4 (-> shape (:r4 0) str)))) + (cond-> text? + (-> (add! :grow-type) + (add! :content json/encode))) - (cond-> text? - (-> (add! :grow-type (-> shape :grow-type)) - (add! :content (-> shape :content json/encode)))) - - (cond-> mask? - (add! :masked-group "true"))))) + (cond-> mask? + (obj/set! "penpot:masked-group" "true")))))) (mf/defc export-data [{:keys [shape]}] diff --git a/frontend/src/app/util/import/parser.cljc b/frontend/src/app/util/import/parser.cljc index e207ecdeb..97f811321 100644 --- a/frontend/src/app/util/import/parser.cljc +++ b/frontend/src/app/util/import/parser.cljc @@ -9,6 +9,7 @@ [app.common.data :as d] [app.common.geom.matrix :as gmt] [app.common.geom.shapes :as gsh] + [app.common.geom.point :as gpt] [app.common.uuid :as uuid] [app.util.color :as uc] [app.util.json :as json] @@ -50,6 +51,10 @@ (or (close? node) (some? (get-data node)))) +(defn str->bool + [val] + (when (some? val) (= val "true"))) + (defn get-meta ([m att] (get-meta m att identity)) @@ -133,16 +138,32 @@ :height (* (:ry values) 2)})) (defn parse-path - [props svg-data] - (let [content (upp/parse-path (:d svg-data)) - selrect (gsh/content->selrect content) - points (gsh/rect->points selrect)] - + [props center svg-data] + (let [transform-inverse (:transform-inverse props (gmt/matrix)) + transform (:transform props (gmt/matrix)) + content (upp/parse-path (:d svg-data)) + content-tr (gsh/transform-content + content + (gmt/transform-in center transform-inverse)) + selrect (gsh/content->selrect content-tr) + points (-> (gsh/rect->points selrect) + (gsh/transform-points center transform))] (-> props (assoc :content content) (assoc :selrect selrect) (assoc :points points)))) +(defn setup-selrect [props] + (let [data (select-keys props [:x :y :width :height]) + transform (:transform props (gmt/matrix)) + selrect (gsh/rect->selrect data) + points (gsh/rect->points data) + center (gsh/center-rect data)] + + (assoc props + :selrect selrect + :points (gsh/transform-points points center transform)))) + (def url-regex #"url\(#([^\)]*)\)") (defn seek-node @@ -198,23 +219,52 @@ (contains? (:attrs svg-content) :penpot:height) (assoc :height (-> svg-content :attrs :penpot:height d/parse-double))))) +(defn add-common-data + [props node] + + (let [name (get-meta node :name) + blocked (get-meta node :blocked str->bool) + hidden (get-meta node :hidden str->bool) + transform (get-meta node :transform gmt/str->matrix) + transform-inverse (get-meta node :transform-inverse gmt/str->matrix) + flip-x (get-meta node :flip-x str->bool) + flip-y (get-meta node :flip-y str->bool) + proportion (get-meta node :proportion d/parse-double) + proportion-lock (get-meta node :proportion-lock str->bool) + rotation (get-meta node :rotation d/parse-double)] + + (-> props + (assoc :name name) + (assoc :blocked blocked) + (assoc :hidden hidden) + (assoc :transform transform) + (assoc :transform-inverse transform-inverse) + (assoc :flip-x flip-x) + (assoc :flip-y flip-y) + (assoc :proportion proportion) + (assoc :proportion-lock proportion-lock) + (assoc :rotation rotation)))) + (defn add-position [props type node svg-data] - (cond-> props - (has-position? type) - (-> (parse-position svg-data) - (gsh/setup-selrect)) + (let [center-x (get-meta node :center-x d/parse-double) + center-y (get-meta node :center-y d/parse-double) + center (gpt/point center-x center-y)] + (cond-> props + (has-position? type) + (parse-position svg-data) - (= type :svg-raw) - (-> (add-svg-position node) - (gsh/setup-selrect)) + (= type :svg-raw) + (add-svg-position node) - (= type :circle) - (-> (parse-circle svg-data) - (gsh/setup-selrect)) + (= type :circle) + (parse-circle svg-data) - (= type :path) - (parse-path svg-data))) + (= type :path) + (parse-path center svg-data) + + (or (has-position? type) (= type :svg-raw) (= type :circle)) + (setup-selrect)))) (defn add-fill [props node svg-data] @@ -293,10 +343,6 @@ (assoc :grow-type (get-meta node :grow-type keyword)) (assoc :content (get-meta node :content json/decode)))) -(defn str->bool - [val] - (= val "true")) - (defn add-group-data [props node] (let [mask? (get-meta node :masked-group str->bool)] @@ -462,16 +508,19 @@ (let [svg-content (get-data node :penpot:svg-content) attrs (-> (:attrs svg-content) (without-penpot-prefix)) tag (-> svg-content :attrs :penpot:tag keyword) - content {:attrs attrs - :tag tag - :content (cond - (= tag :svg) - (->> node :content last :content last :content fix-style-attr) - (= tag :text) - (-> node :content last :content))}] - (-> props - (assoc :content content)))) + node-content + (cond + (= tag :svg) + (->> node :content last :content last :content fix-style-attr) + + (= tag :text) + (-> node :content last :content))] + (assoc + props :content + {:attrs attrs + :tag tag + :content node-content}))) (defn get-image-name [node] @@ -486,17 +535,9 @@ [type node] (when-not (close? node) - (let [name (get-meta node :name) - blocked (get-meta node :blocked str->bool) - hidden (get-meta node :hidden str->bool) - transform (get-meta node :transform gmt/str->matrix) - transform-inverse (get-meta node :transform-inverse gmt/str->matrix) - svg-data (get-svg-data type node)] - + (let [svg-data (get-svg-data type node)] (-> {} - (assoc :name name) - (assoc :blocked blocked) - (assoc :hidden hidden) + (add-common-data node) (add-position type node svg-data) (add-fill node svg-data) (add-stroke node svg-data) @@ -519,10 +560,4 @@ (add-image-data node)) (cond-> (= :text type) - (add-text-data node)) - - (cond-> (some? transform) - (assoc :transform transform)) - - (cond-> (some? transform-inverse) - (assoc :transform-inverse transform-inverse)))))) + (add-text-data node))))))