Adds imported rectangles SVGs

This commit is contained in:
alonso.torres 2021-02-26 22:06:54 +01:00 committed by Andrey Antukh
parent 59022904fb
commit 6e88d3a04c
10 changed files with 194 additions and 143 deletions

File diff suppressed because one or more lines are too long

View file

@ -281,6 +281,7 @@
(d/export gtr/transform-rect) (d/export gtr/transform-rect)
(d/export gtr/update-group-selrect) (d/export gtr/update-group-selrect)
(d/export gtr/transform-points) (d/export gtr/transform-points)
(d/export gtr/calculate-adjust-matrix)
;; PATHS ;; PATHS
(d/export gsp/content->points) (d/export gsp/content->points)

View file

@ -139,11 +139,15 @@
(defn- calculate-height (defn- calculate-height
"Calculates the height of a paralelogram given by the points" "Calculates the height of a paralelogram given by the points"
[[p1 _ p3 p4]] [[p1 _ _ p4]]
(let [v1 (gpt/to-vec p3 p4) (-> (gpt/to-vec p4 p1)
v2 (gpt/to-vec p4 p1) (gpt/length)))
angle (gpt/angle-with-other v1 v2)]
(* (gpt/length v2) (mth/sin (mth/radians angle))))) (defn- calculate-width
"Calculates the width of a paralelogram given by the points"
[[p1 p2 _ _]]
(-> (gpt/to-vec p1 p2)
(gpt/length)))
(defn- calculate-rotation (defn- calculate-rotation
"Calculates the rotation between two shapes given the resize vector direction" "Calculates the rotation between two shapes given the resize vector direction"
@ -173,44 +177,49 @@
"Calculates a matrix that is a series of transformations we have to do to the transformed rectangle so that "Calculates a matrix that is a series of transformations we have to do to the transformed rectangle so that
after applying them the end result is the `shape-pathn-temp`. after applying them the end result is the `shape-pathn-temp`.
This is compose of three transformations: skew, resize and rotation" This is compose of three transformations: skew, resize and rotation"
[points-temp points-rec flip-x flip-y] ([points-temp points-rec] (calculate-adjust-matrix points-temp points-rec false false))
(let [center (gco/center-points points-temp) ([points-temp points-rec flip-x flip-y]
(let [center (gco/center-points points-temp)
stretch-matrix (gmt/matrix) stretch-matrix (gmt/matrix)
skew-angle (calculate-skew-angle points-temp) skew-angle (calculate-skew-angle points-temp)
;; When one of the axis is flipped we have to reverse the skew ;; When one of the axis is flipped we have to reverse the skew
;; skew-angle (if (neg? (* (:x resize-vector) (:y resize-vector))) (- skew-angle) skew-angle ) ;; skew-angle (if (neg? (* (:x resize-vector) (:y resize-vector))) (- skew-angle) skew-angle )
skew-angle (if (and (or flip-x flip-y) skew-angle (if (and (or flip-x flip-y)
(not (and flip-x flip-y))) (- skew-angle) skew-angle ) (not (and flip-x flip-y))) (- skew-angle) skew-angle )
skew-angle (if (mth/nan? skew-angle) 0 skew-angle) skew-angle (if (mth/nan? skew-angle) 0 skew-angle)
stretch-matrix (gmt/multiply stretch-matrix (gmt/skew-matrix skew-angle 0)) stretch-matrix (gmt/multiply stretch-matrix (gmt/skew-matrix skew-angle 0))
h1 (max 1 (calculate-height points-temp)) h1 (max 1 (calculate-height points-temp))
h2 (max 1 (calculate-height (transform-points points-rec center stretch-matrix))) h2 (max 1 (calculate-height (transform-points points-rec center stretch-matrix)))
h3 (if-not (mth/almost-zero? h2) (/ h1 h2) 1) h3 (if-not (mth/almost-zero? h2) (/ h1 h2) 1)
h3 (if (mth/nan? h3) 1 h3) h3 (if (mth/nan? h3) 1 h3)
stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point 1 h3))) w1 (max 1 (calculate-width points-temp))
w2 (max 1 (calculate-width (transform-points points-rec center stretch-matrix)))
w3 (if-not (mth/almost-zero? w2) (/ w1 w2) 1)
w3 (if (mth/nan? w3) 1 w3)
rotation-angle (calculate-rotation stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point w3 h3)))
center
(transform-points points-rec (gco/center-points points-rec) stretch-matrix)
points-temp
flip-x
flip-y)
stretch-matrix (gmt/multiply (gmt/rotate-matrix rotation-angle) stretch-matrix) rotation-angle (calculate-rotation
center
(transform-points points-rec (gco/center-points points-rec) stretch-matrix)
points-temp
flip-x
flip-y)
stretch-matrix (gmt/multiply (gmt/rotate-matrix rotation-angle) stretch-matrix)
;; This is the inverse to be able to remove the transformation ;; This is the inverse to be able to remove the transformation
stretch-matrix-inverse (-> (gmt/matrix) stretch-matrix-inverse (-> (gmt/matrix)
(gmt/scale (gpt/point 1 (/ 1 h3))) (gmt/scale (gpt/point (/ 1 w3) (/ 1 h3)))
(gmt/skew (- skew-angle) 0) (gmt/skew (- skew-angle) 0)
(gmt/rotate (- rotation-angle)))] (gmt/rotate (- rotation-angle)))]
[stretch-matrix stretch-matrix-inverse])) [stretch-matrix stretch-matrix-inverse rotation-angle])))
(defn apply-transform (defn apply-transform
"Given a new set of points transformed, set up the rectangle so it keeps "Given a new set of points transformed, set up the rectangle so it keeps

File diff suppressed because one or more lines are too long

View file

@ -17,8 +17,8 @@
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.data.workspace.common :as dwc] [app.main.data.workspace.common :as dwc]
[app.util.color :as uc] [app.util.color :as uc]
[app.util.data :as ud]
[app.util.geom.path :as ugp] [app.util.geom.path :as ugp]
[app.util.object :as obj]
[app.util.svg :as usvg] [app.util.svg :as usvg]
[beicon.core :as rx] [beicon.core :as rx]
[cuerdas.core :as str] [cuerdas.core :as str]
@ -58,12 +58,12 @@
(get-in shape [:svg-attrs :fill-opacity]) (get-in shape [:svg-attrs :fill-opacity])
(-> (update :svg-attrs dissoc :fill-opacity) (-> (update :svg-attrs dissoc :fill-opacity)
(assoc :fill-opacity (-> (get-in shape [:svg-attrs :fill-opacity]) (assoc :fill-opacity (-> (get-in shape [:svg-attrs :fill-opacity])
(ud/parse-float)))) (d/parse-double))))
(get-in shape [:svg-attrs :style :fill-opacity]) (get-in shape [:svg-attrs :style :fill-opacity])
(-> (update :svg-attrs dissoc :fill-opacity) (-> (update :svg-attrs dissoc :fill-opacity)
(assoc :fill-opacity (-> (get-in shape [:svg-attrs :style :fill-opacity]) (assoc :fill-opacity (-> (get-in shape [:svg-attrs :style :fill-opacity])
(ud/parse-float)))))) (d/parse-double))))))
(defonce default-stroke {:stroke-color "#000000" (defonce default-stroke {:stroke-color "#000000"
:stroke-opacity 1 :stroke-opacity 1
@ -84,12 +84,12 @@
(get-in shape [:svg-attrs :stroke-width]) (get-in shape [:svg-attrs :stroke-width])
(-> (update :svg-attrs dissoc :stroke-width) (-> (update :svg-attrs dissoc :stroke-width)
(assoc :stroke-width (-> (get-in shape [:svg-attrs :stroke-width]) (assoc :stroke-width (-> (get-in shape [:svg-attrs :stroke-width])
(ud/parse-float)))) (d/parse-double))))
(get-in shape [:svg-attrs :style :stroke-width]) (get-in shape [:svg-attrs :style :stroke-width])
(-> (update-in [:svg-attrs :style] dissoc :stroke-width) (-> (update-in [:svg-attrs :style] dissoc :stroke-width)
(assoc :stroke-width (-> (get-in shape [:svg-attrs :style :stroke-width]) (assoc :stroke-width (-> (get-in shape [:svg-attrs :style :stroke-width])
(ud/parse-float)))))] (d/parse-double)))))]
shape shape
#_(if (d/any-key? shape :stroke-color :stroke-opacity :stroke-width) #_(if (d/any-key? shape :stroke-color :stroke-opacity :stroke-width)
(merge default-stroke shape) (merge default-stroke shape)
@ -131,10 +131,12 @@
svg-transform svg-transform
(gsh/transform-content svg-transform)) (gsh/transform-content svg-transform))
attrs (d/update-when attrs :transform #(-> (usvg/parse-transform %) str)) ;; attrs (d/update-when attrs :transform #(-> (usvg/parse-transform %) str))
selrect (gsh/content->selrect content) selrect (gsh/content->selrect content)
points (gsh/rect->points selrect)] points (gsh/rect->points selrect)
origin (gpt/negate (gpt/point svg-data))]
(-> {:id (uuid/next) (-> {:id (uuid/next)
:type :path :type :path
:name name :name name
@ -145,7 +147,78 @@
(assoc :svg-viewbox (select-keys selrect [:x :y :width :height])) (assoc :svg-viewbox (select-keys selrect [:x :y :width :height]))
(assoc :svg-attrs (dissoc attrs :d :transform)) (assoc :svg-attrs (dissoc attrs :d :transform))
(assoc :svg-transform svg-transform) (assoc :svg-transform svg-transform)
(gsh/translate-to-frame svg-data)))) (gsh/translate-to-frame origin))))
(defn inverse-matrix [{:keys [a b c d e f]}]
(let [dom-matrix (-> (js/DOMMatrix.)
(obj/set! "a" a)
(obj/set! "b" b)
(obj/set! "c" c)
(obj/set! "d" d)
(obj/set! "e" e)
(obj/set! "f" f)
(.inverse))]
(gmt/matrix (obj/get dom-matrix "a")
(obj/get dom-matrix "b")
(obj/get dom-matrix "c")
(obj/get dom-matrix "d")
(obj/get dom-matrix "e")
(obj/get dom-matrix "f"))))
(defn calculate-rect-metadata [rect-data transform]
(let [points (-> (gsh/rect->points rect-data)
(gsh/transform-points transform))
center (gsh/center-points points)
rect-shape (-> (gsh/make-centered-rect center (:width rect-data) (:height rect-data))
(update :width max 1)
(update :height max 1))
selrect (gsh/rect->selrect rect-shape)
rect-points (gsh/rect->points rect-shape)
[shape-transform shape-transform-inv rotation]
(gsh/calculate-adjust-matrix points rect-points)]
(merge rect-shape
{:selrect selrect
:points points
:rotation rotation
:transform shape-transform
:transform-inverse shape-transform-inv})))
(def default-rect {:x 0 :y 0 :width 1 :height 1 :rx 0 :ry 0})
(defn create-rect-shape [name frame-id svg-data {:keys [attrs] :as data}]
(let [svg-transform (usvg/parse-transform (:transform attrs))
transform (->> svg-transform
(gmt/transform-in (gpt/point svg-data)))
rect (->> (select-keys attrs [:x :y :width :height])
(d/mapm #(d/parse-double %2)))
origin (gpt/negate (gpt/point svg-data))
rect-data (-> (merge default-rect rect)
(update :x - (:x origin))
(update :y - (:y origin)))
metadata (calculate-rect-metadata rect-data transform)]
(-> {:id (uuid/next)
:type :rect
:name name
:frame-id frame-id}
(cond->
(contains? attrs :rx) (:rx attrs)
(contains? attrs :rx) (:rx attrs))
(merge metadata)
(assoc :svg-transform transform)
(assoc :svg-viewbox (select-keys rect [:x :y :width :height]))
(assoc :svg-attrs (dissoc attrs :x :y :width :height :rx :ry :transform)))))
(defn create-group [name frame-id svg-data {:keys [attrs]}] (defn create-group [name frame-id svg-data {:keys [attrs]}]
(let [{:keys [x y width height]} svg-data] (let [{:keys [x y width height]} svg-data]
@ -167,11 +240,13 @@
att-refs (usvg/find-attr-references attrs) att-refs (usvg/find-attr-references attrs)
references (usvg/find-def-references (:defs svg-data) att-refs)] references (usvg/find-def-references (:defs svg-data) att-refs)]
;; SVG graphic elements
;; :circle :ellipse :image :line :path :polygon :polyline :rect :text :use
(-> (case tag (-> (case tag
:g (create-group name frame-id svg-data element-data) :g (create-group name frame-id svg-data element-data)
;; :rect (parse-rect data) :rect (create-rect-shape name frame-id svg-data element-data)
:path (create-path-shape name frame-id (gpt/negate (gpt/point svg-data)) element-data) :path (create-path-shape name frame-id svg-data element-data)
(create-raw-svg name frame-id svg-data element-data)) #_other (create-raw-svg name frame-id svg-data element-data))
(assoc :svg-defs (select-keys (:defs svg-data) references)) (assoc :svg-defs (select-keys (:defs svg-data) references))
(setup-fill) (setup-fill)

View file

@ -27,7 +27,8 @@
(def svg-ids-ctx (mf/create-context nil)) (def svg-ids-ctx (mf/create-context nil))
(defn set-styles [attrs shape] (defn set-styles [attrs shape]
(let [custom-attrs (usa/extract-style-attrs shape) (let [custom-attrs (-> (usa/extract-style-attrs shape)
(obj/without ["transform"]))
attrs (cond-> attrs attrs (cond-> attrs
(string? (:style attrs)) usvg/clean-attrs) (string? (:style attrs)) usvg/clean-attrs)
style (obj/merge! (clj->js (:style attrs {})) style (obj/merge! (clj->js (:style attrs {}))

View file

@ -44,8 +44,6 @@
:style {:stroke color :style {:stroke color
:fill "transparent" :fill "transparent"
:stroke-width "1px" :stroke-width "1px"
:stroke-opacity 0.5
:stroke-dasharray 4
:pointer-events "none"}}]) :pointer-events "none"}}])
(mf/defc render-rect-points [{:keys [points color]}] (mf/defc render-rect-points [{:keys [points color]}]
@ -62,7 +60,7 @@
[props] [props]
(let [shape (-> (unchecked-get props "shape")) (let [shape (-> (unchecked-get props "shape"))
frame (unchecked-get props "frame") frame (unchecked-get props "frame")
selrect (gsh/points->selrect (-> shape :points)) bounding-box (gsh/points->selrect (-> shape :points))
shape-center (gsh/center-shape shape) shape-center (gsh/center-shape shape)
line-color (rdcolor #js {:seed (str (:id shape))}) line-color (rdcolor #js {:seed (str (:id shape))})
zoom (mf/deref refs/selected-zoom) zoom (mf/deref refs/selected-zoom)
@ -71,25 +69,30 @@
(map gsh/transform-shape))] (map gsh/transform-shape))]
[:g.bounding-box [:g.bounding-box
[:text {:x (:x selrect) [:text {:x (:x bounding-box)
:y (- (:y selrect) 5) :y (- (:y bounding-box) 5)
:font-size 10 :font-size 10
:fill line-color :fill line-color
:stroke "white" :stroke "white"
:stroke-width 0.1} :stroke-width 0.1}
(str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fixed (:x selrect)) (fixed (:y selrect)))] (str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fixed (:x bounding-box)) (fixed (:y bounding-box)))]
[:& cross-point {:point shape-center [:g.center
:zoom zoom [:& cross-point {:point shape-center
:color line-color}] :zoom zoom
:color line-color}]]
(for [point (:points shape)] [:g.points
[:& cross-point {:point point (for [point (:points shape)]
:zoom zoom [:& cross-point {:point point
:color line-color}]) :zoom zoom
:color line-color}])
#_[:& render-rect-points {:points (:points shape)
:color line-color}]]
[:& render-rect-points {:points (:points shape) [:g.selrect
:color line-color}] [:& render-rect {:rect (:selrect shape)
;; :transform (gsh/transform-matrix shape)
[:& render-rect {:rect selrect :color line-color}]
:color line-color}]])) #_[:& render-rect {:rect bounding-box
:color line-color}]]]))

View file

@ -225,7 +225,7 @@
"skewY" (apply gmt/skew-matrix (format-skew-y-params params)))) "skewY" (apply gmt/skew-matrix (format-skew-y-params params))))
(defn parse-transform [transform-attr] (defn parse-transform [transform-attr]
(when transform-attr (if transform-attr
(let [process-matrix (let [process-matrix
(fn [[_ type params]] (fn [[_ type params]]
(let [params (->> (re-seq params-regex params) (let [params (->> (re-seq params-regex params)
@ -236,5 +236,6 @@
matrices (->> (re-seq matrices-regex transform-attr) matrices (->> (re-seq matrices-regex transform-attr)
(map process-matrix) (map process-matrix)
(map to-matrix))] (map to-matrix))]
(reduce gmt/multiply (gmt/matrix) matrices)))) (reduce gmt/multiply (gmt/matrix) matrices))
(gmt/matrix)))

View file

@ -1,75 +1,39 @@
/*
const plugins = [
{removeDimensions: true},
{removeScriptElement: true},
{removeViewBox: false},
{moveElemsAttrsToGroup: false},
{convertStyleToAttrs: false},
{removeUselessDefs: false},
{convertPathData: {
lineShorthands: false,
curveSmoothShorthands: false,
forceAbsolutePath: true,
}}
];
*/
const plugins = [ const plugins = [
// 'removeDoctype', { "minifyStyles" : false },
// 'removeXMLProcInst', { "convertStyleToAttrs" : false },
// 'removeComments', {
// 'removeMetadata', "cleanupIDs" : {
// 'removeXMLNS', remove: false,
// 'removeEditorsNSData', minify: false,
// 'cleanupAttrs', force: false
// 'inlineStyles', }
// 'minifyStyles', },
// 'convertStyleToAttrs' { "cleanupListOfValues" : true },
// 'cleanupIDs', { "removeUnknownsAndDefaults" : false },
// 'prefixIds', { "removeViewBox" : false },
// 'removeRasterImages', { "convertShapeToPath" : false },
// 'removeUselessDefs', { "convertEllipseToCircle" : false },
// 'cleanupNumericValues', { "moveElemsAttrsToGroup" : false },
// 'cleanupListOfValues', { "collapseGroups" : false },
// 'convertColors', {
// 'removeUnknownsAndDefaults', "convertPathData" : {
// 'removeNonInheritableGroupAttrs', lineShorthands: false,
// 'removeUselessStrokeAndFill', curveSmoothShorthands: false,
// 'removeViewBox', forceAbsolutePath: true,
// 'cleanupEnableBackground', }
// 'removeHiddenElems', },
// 'removeEmptyText', { "convertTransform" : false },
// 'convertShapeToPath', { "removeEmptyContainers" : false },
// 'convertEllipseToCircle', { "mergePaths" : false },
// 'moveElemsAttrsToGroup', { "sortDefsChildren" : false },
// 'moveGroupAttrsToElems', { "removeDimensions" : true },
// 'collapseGroups', { "removeStyleElement" : true },
// {'convertPathData': { { "removeScriptElement" : true },
// 'lineShorthands': false, { "removeOffCanvasPaths" : true },
// 'curveSmoothShorthands': false,
// 'forceAbsolutePath': true,
// }},
// 'convertTransform',
// 'removeEmptyAttrs',
// 'removeEmptyContainers',
// 'mergePaths',
// 'removeUnusedNS',
// 'sortAttrs',
// 'sortDefsChildren',
// 'removeTitle',
// 'removeDesc',
// 'removeDimensions',
// 'removeAttrs',
// 'removeAttributesBySelector',
// 'removeElementsByAttr',
// 'addClassesToSVGElement',
// 'removeStyleElement',
// 'removeScriptElement',
// 'addAttributesToSVGElement',
// 'removeOffCanvasPaths',
// 'reusePaths',
]; ];
const svgc = require("./src/svgclean.js"); const svgc = require("./src/svgclean.js");
const inst = svgc.configure({plugins}); const inst = svgc.configure({plugins});

View file

@ -38,9 +38,6 @@ exports.fn = function(item) {
!item.isEmpty() && !item.isEmpty() &&
!item.someAttr(function(attr) { !item.someAttr(function(attr) {
return ~referencesProps.indexOf(attr.name) && ~attr.value.indexOf('url('); return ~referencesProps.indexOf(attr.name) && ~attr.value.indexOf('url(');
}) &&
item.content.every(function(inner) {
return inner.isElem(pathElems) && !inner.hasAttr('id');
}) })
) { ) {
item.content.forEach(function(inner) { item.content.forEach(function(inner) {