mirror of
https://github.com/penpot/penpot.git
synced 2025-03-13 00:01:51 -05:00
✨ Performance improvements
This commit is contained in:
parent
7b2f0303e8
commit
efc1b87ab0
10 changed files with 292 additions and 129 deletions
|
@ -263,3 +263,10 @@
|
|||
matrix
|
||||
(translate-matrix (gpt/negate center))))
|
||||
point))
|
||||
|
||||
(defn move?
|
||||
[{:keys [a b c d _ _]}]
|
||||
(and (mth/almost-zero? (- a 1))
|
||||
(mth/almost-zero? b)
|
||||
(mth/almost-zero? c)
|
||||
(mth/almost-zero? (- d 1))))
|
||||
|
|
|
@ -175,7 +175,6 @@
|
|||
(dm/export gtr/transform-selrect-matrix)
|
||||
(dm/export gtr/transform-bounds)
|
||||
(dm/export gtr/move-position-data)
|
||||
(dm/export gtr/apply-transform)
|
||||
(dm/export gtr/apply-objects-modifiers)
|
||||
(dm/export gtr/parent-coords-rect)
|
||||
(dm/export gtr/parent-coords-points)
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]))
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.rect :as gpr]))
|
||||
|
||||
(defn center-rect
|
||||
[{:keys [x y width height]}]
|
||||
|
@ -31,6 +32,22 @@
|
|||
(gpt/point (/ (+ minx maxx) 2.0)
|
||||
(/ (+ miny maxy) 2.0))))
|
||||
|
||||
(defn center-bounds [[a b c d]]
|
||||
(let [xa (:x a)
|
||||
ya (:y a)
|
||||
xb (:x b)
|
||||
yb (:y b)
|
||||
xc (:x c)
|
||||
yc (:y c)
|
||||
xd (:x d)
|
||||
yd (:y d)
|
||||
minx (min xa xb xc xd)
|
||||
miny (min ya yb yc yd)
|
||||
maxx (max xa xb xc xd)
|
||||
maxy (max ya yb yc yd)]
|
||||
(gpt/point (/ (+ minx maxx) 2.0)
|
||||
(/ (+ miny maxy) 2.0))))
|
||||
|
||||
(defn center-shape
|
||||
"Calculate the center of the shape."
|
||||
[shape]
|
||||
|
@ -49,3 +66,8 @@
|
|||
(gpt/transform point (gmt/multiply prev matrix post)))]
|
||||
(mapv tr-point points))
|
||||
points)))
|
||||
|
||||
(defn transform-selrect
|
||||
[{:keys [x1 y1 x2 y2] :as sr} matrix]
|
||||
(let [[c1 c2] (transform-points [(gpt/point x1 y1) (gpt/point x2 y2)] matrix)]
|
||||
(gpr/corners->selrect c1 c2)))
|
||||
|
|
|
@ -91,20 +91,30 @@
|
|||
|
||||
(defn- set-children-modifiers
|
||||
"Propagates the modifiers from a parent too its children applying constraints if necesary"
|
||||
[modif-tree objects parent transformed-parent ignore-constraints snap-pixel?]
|
||||
(let [children (map (d/getf objects) (:shapes parent))
|
||||
modifiers (dm/get-in modif-tree [(:id parent) :modifiers])
|
||||
parent (gtr/transform-shape parent (ctm/select-parent-modifiers modifiers))
|
||||
[modif-tree objects parent transformed-parent ignore-constraints]
|
||||
(let [children (:shapes parent)
|
||||
modifiers (dm/get-in modif-tree [(:id parent) :modifiers])]
|
||||
|
||||
set-child
|
||||
(fn [modif-tree child]
|
||||
(let [child-modifiers (gct/calc-child-modifiers parent child modifiers ignore-constraints transformed-parent)
|
||||
child-modifiers (cond-> child-modifiers snap-pixel? (gpp/set-pixel-precision child))]
|
||||
(cond-> modif-tree
|
||||
(not (ctm/empty? child-modifiers))
|
||||
(update-in [(:id child) :modifiers] ctm/add-modifiers child-modifiers))))]
|
||||
(if (ctm/only-move? modifiers)
|
||||
;; Move modifiers don't need to calculate constraints
|
||||
(loop [modif-tree modif-tree
|
||||
children (seq children)]
|
||||
(if-let [current (first children)]
|
||||
(recur (update-in modif-tree [current :modifiers] ctm/add-modifiers modifiers)
|
||||
(rest children))
|
||||
modif-tree))
|
||||
|
||||
(reduce set-child modif-tree children)))
|
||||
;; Check the constraints, then resize
|
||||
(let [parent (gtr/transform-shape parent (ctm/select-parent-modifiers modifiers))]
|
||||
(loop [modif-tree modif-tree
|
||||
children (seq children)]
|
||||
(if-let [current (first children)]
|
||||
(let [child-modifiers (gct/calc-child-modifiers parent (get objects current) modifiers ignore-constraints transformed-parent)]
|
||||
(recur (cond-> modif-tree
|
||||
(not (ctm/empty? child-modifiers))
|
||||
(update-in [current :modifiers] ctm/add-modifiers child-modifiers))
|
||||
(rest children)))
|
||||
modif-tree))))))
|
||||
|
||||
(defn- process-layout-children
|
||||
[modif-tree objects parent transformed-parent]
|
||||
|
@ -210,17 +220,11 @@
|
|||
(assoc-in modif-tree [(:id parent) :modifiers] modifiers))))
|
||||
|
||||
(defn- propagate-modifiers
|
||||
[objects snap-pixel? ignore-constraints [modif-tree recalculate] parent]
|
||||
"Propagate modifiers to its children"
|
||||
[objects ignore-constraints [modif-tree recalculate] parent]
|
||||
(let [parent-id (:id parent)
|
||||
root? (= uuid/zero parent-id)
|
||||
modifiers (dm/get-in modif-tree [parent-id :modifiers])
|
||||
|
||||
modifiers (cond-> modifiers
|
||||
(and (not root?) (ctm/has-geometry? modifiers) snap-pixel?)
|
||||
(gpp/set-pixel-precision parent))
|
||||
|
||||
modif-tree (-> modif-tree (assoc-in [parent-id :modifiers] modifiers))
|
||||
|
||||
transformed-parent (gtr/transform-shape parent modifiers)
|
||||
|
||||
has-modifiers? (ctm/child-modifiers? modifiers)
|
||||
|
@ -233,7 +237,7 @@
|
|||
|
||||
[(cond-> modif-tree
|
||||
(and (not is-layout?) has-modifiers? is-parent? (not root?))
|
||||
(set-children-modifiers objects parent transformed-parent (or ignore-constraints is-inside-layout?) snap-pixel?)
|
||||
(set-children-modifiers objects parent transformed-parent (or ignore-constraints is-inside-layout?))
|
||||
|
||||
is-layout?
|
||||
(-> (process-layout-children objects parent transformed-parent)
|
||||
|
@ -266,7 +270,7 @@
|
|||
(let [shapes-tree (resolve-tree-sequence (-> modif-tree keys set) objects)
|
||||
|
||||
[modif-tree recalculate]
|
||||
(reduce (partial propagate-modifiers objects snap-pixel? ignore-constraints) [modif-tree #{}] shapes-tree)
|
||||
(reduce (partial propagate-modifiers objects ignore-constraints) [modif-tree #{}] shapes-tree)
|
||||
|
||||
shapes-tree (resolve-tree-sequence recalculate objects)
|
||||
|
||||
|
@ -281,7 +285,11 @@
|
|||
modif-tree
|
||||
(->> shapes-tree
|
||||
(filter ctl/layout?)
|
||||
(reduce (partial calculate-reflow-layout objects) modif-tree ))]
|
||||
(reduce (partial calculate-reflow-layout objects) modif-tree))
|
||||
|
||||
modif-tree
|
||||
(cond-> modif-tree
|
||||
snap-pixel? (gpp/adjust-pixel-precision objects))]
|
||||
|
||||
;;#?(:cljs
|
||||
;; (.log js/console ">result" (modif->js modif-tree objects)))
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
(ns app.common.geom.shapes.pixel-precision
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.geom.shapes.rect :as gpr]
|
||||
|
@ -15,9 +17,8 @@
|
|||
[app.common.types.modifiers :as ctm]))
|
||||
|
||||
(defn size-pixel-precision
|
||||
[modifiers shape]
|
||||
(let [{:keys [points transform transform-inverse] :as shape} (gtr/transform-shape shape modifiers)
|
||||
origin (gpo/origin points)
|
||||
[modifiers {:keys [points transform transform-inverse] :as shape}]
|
||||
(let [origin (gpo/origin points)
|
||||
curr-width (gpo/width-points points)
|
||||
curr-height (gpo/height-points points)
|
||||
|
||||
|
@ -35,9 +36,8 @@
|
|||
(ctm/resize scalev origin transform transform-inverse))))
|
||||
|
||||
(defn position-pixel-precision
|
||||
[modifiers shape]
|
||||
(let [{:keys [points]} (gtr/transform-shape shape modifiers)
|
||||
bounds (gpr/points->rect points)
|
||||
[modifiers {:keys [points]}]
|
||||
(let [bounds (gpr/points->rect points)
|
||||
corner (gpt/point bounds)
|
||||
target-corner (gpt/round corner)
|
||||
deltav (gpt/to-vec corner target-corner)]
|
||||
|
@ -47,7 +47,25 @@
|
|||
(defn set-pixel-precision
|
||||
"Adjust modifiers so they adjust to the pixel grid"
|
||||
[modifiers shape]
|
||||
|
||||
(-> modifiers
|
||||
(let [move? (ctm/only-move? modifiers)]
|
||||
(cond-> modifiers
|
||||
(not move?)
|
||||
(size-pixel-precision shape)
|
||||
(position-pixel-precision shape)))
|
||||
|
||||
:always
|
||||
(position-pixel-precision shape))))
|
||||
|
||||
(defn adjust-pixel-precision
|
||||
[modif-tree objects]
|
||||
(let [update-modifiers
|
||||
(fn [modif-tree shape]
|
||||
(let [modifiers (dm/get-in modif-tree [(:id shape) :modifiers])]
|
||||
(if-not (ctm/has-geometry? modifiers)
|
||||
modif-tree
|
||||
(let [shape (gtr/transform-shape shape modifiers)]
|
||||
(-> modif-tree
|
||||
(update-in [(:id shape) :modifiers] set-pixel-precision shape))))))]
|
||||
|
||||
(->> (keys modif-tree)
|
||||
(map (d/getf objects))
|
||||
(reduce update-modifiers modif-tree))))
|
||||
|
|
|
@ -192,3 +192,10 @@
|
|||
(>= (:y1 sr2) (:y1 sr1))
|
||||
(<= (:y2 sr2) (:y2 sr1))))
|
||||
|
||||
(defn corners->selrect
|
||||
[p1 p2]
|
||||
(let [xp1 (:x p1)
|
||||
xp2 (:x p2)
|
||||
yp1 (:y p1)
|
||||
yp2 (:y p2)]
|
||||
(make-selrect (min xp1 xp2) (min yp1 yp2) (abs (- xp1 xp2)) (abs (- yp1 yp2)))))
|
||||
|
|
|
@ -188,55 +188,52 @@
|
|||
"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-path-temp`.
|
||||
This is compose of three transformations: skew, resize and rotation"
|
||||
([points-temp points-rec]
|
||||
(calculate-adjust-matrix points-temp points-rec false false))
|
||||
[points-temp points-rec flip-x flip-y]
|
||||
(let [center (gco/center-bounds 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
|
||||
;; skew-angle (if (neg? (* (:x resize-vector) (:y resize-vector))) (- skew-angle) skew-angle )
|
||||
skew-angle (if (and (or flip-x flip-y)
|
||||
(not (and flip-x flip-y))) (- skew-angle) skew-angle )
|
||||
skew-angle (if (mth/nan? skew-angle) 0 skew-angle)
|
||||
|
||||
;; 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 (and (or flip-x flip-y)
|
||||
(not (and flip-x flip-y))) (- skew-angle) 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))
|
||||
h2 (max 1 (calculate-height (gco/transform-points points-rec center stretch-matrix)))
|
||||
h3 (if-not (mth/almost-zero? h2) (/ h1 h2) 1)
|
||||
h3 (if (mth/nan? h3) 1 h3)
|
||||
|
||||
h1 (max 1 (calculate-height points-temp))
|
||||
h2 (max 1 (calculate-height (gco/transform-points points-rec center stretch-matrix)))
|
||||
h3 (if-not (mth/almost-zero? h2) (/ h1 h2) 1)
|
||||
h3 (if (mth/nan? h3) 1 h3)
|
||||
w1 (max 1 (calculate-width points-temp))
|
||||
w2 (max 1 (calculate-width (gco/transform-points points-rec center stretch-matrix)))
|
||||
w3 (if-not (mth/almost-zero? w2) (/ w1 w2) 1)
|
||||
w3 (if (mth/nan? w3) 1 w3)
|
||||
|
||||
w1 (max 1 (calculate-width points-temp))
|
||||
w2 (max 1 (calculate-width (gco/transform-points points-rec center stretch-matrix)))
|
||||
w3 (if-not (mth/almost-zero? w2) (/ w1 w2) 1)
|
||||
w3 (if (mth/nan? w3) 1 w3)
|
||||
stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point w3 h3)))
|
||||
|
||||
stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point w3 h3)))
|
||||
rotation-angle (calculate-rotation
|
||||
center
|
||||
(gco/transform-points points-rec (gco/center-points points-rec) stretch-matrix)
|
||||
points-temp
|
||||
flip-x
|
||||
flip-y)
|
||||
|
||||
rotation-angle (calculate-rotation
|
||||
center
|
||||
(gco/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)
|
||||
|
||||
stretch-matrix (gmt/multiply (gmt/rotate-matrix rotation-angle) stretch-matrix)
|
||||
|
||||
;; This is the inverse to be able to remove the transformation
|
||||
stretch-matrix-inverse
|
||||
(gmt/multiply (gmt/scale-matrix (gpt/point (/ 1 w3) (/ 1 h3)))
|
||||
(gmt/skew-matrix (- skew-angle) 0)
|
||||
(gmt/rotate-matrix (- rotation-angle)))]
|
||||
[stretch-matrix stretch-matrix-inverse rotation-angle])))
|
||||
;; This is the inverse to be able to remove the transformation
|
||||
stretch-matrix-inverse
|
||||
(gmt/multiply (gmt/scale-matrix (gpt/point (/ 1 w3) (/ 1 h3)))
|
||||
(gmt/skew-matrix (- skew-angle) 0)
|
||||
(gmt/rotate-matrix (- rotation-angle)))]
|
||||
[stretch-matrix stretch-matrix-inverse rotation-angle]))
|
||||
|
||||
(defn- adjust-rotated-transform
|
||||
[{:keys [transform transform-inverse flip-x flip-y]} points]
|
||||
(let [center (gco/center-points points)
|
||||
(let [center (gco/center-bounds points)
|
||||
|
||||
points-temp (cond-> points
|
||||
(some? transform-inverse)
|
||||
|
@ -280,7 +277,28 @@
|
|||
(-> (update :flip-y not)
|
||||
(update :rotation -)))))
|
||||
|
||||
(defn apply-transform
|
||||
(defn- apply-transform-move
|
||||
"Given a new set of points transformed, set up the rectangle so it keeps
|
||||
its properties. We adjust de x,y,width,height and create a custom transform"
|
||||
[shape transform-mtx]
|
||||
(let [bool? (= (:type shape) :bool)
|
||||
path? (= (:type shape) :path)
|
||||
points (gco/transform-points (:points shape) transform-mtx)
|
||||
selrect (gco/transform-selrect (:selrect shape) transform-mtx)]
|
||||
(-> shape
|
||||
(cond-> bool?
|
||||
(update :bool-content gpa/transform-content transform-mtx))
|
||||
(cond-> path?
|
||||
(update :content gpa/transform-content transform-mtx))
|
||||
(cond-> (not path?)
|
||||
(assoc :x (:x selrect)
|
||||
:y (:y selrect)
|
||||
:width (:width selrect)
|
||||
:height (:height selrect)))
|
||||
(assoc :selrect selrect)
|
||||
(assoc :points points))))
|
||||
|
||||
(defn- apply-transform-generic
|
||||
"Given a new set of points transformed, set up the rectangle so it keeps
|
||||
its properties. We adjust de x,y,width,height and create a custom transform"
|
||||
[shape transform-mtx]
|
||||
|
@ -303,7 +321,10 @@
|
|||
(cond-> path?
|
||||
(update :content gpa/transform-content transform-mtx))
|
||||
(cond-> (not path?)
|
||||
(-> (merge (select-keys selrect [:x :y :width :height]))))
|
||||
(assoc :x (:x selrect)
|
||||
:y (:y selrect)
|
||||
:width (:width selrect)
|
||||
:height (:height selrect)))
|
||||
(cond-> transform
|
||||
(-> (assoc :transform transform)
|
||||
(assoc :transform-inverse transform-inverse)))
|
||||
|
@ -316,6 +337,14 @@
|
|||
(assoc :points points))
|
||||
(assoc :rotation rotation))))
|
||||
|
||||
(defn- apply-transform
|
||||
"Given a new set of points transformed, set up the rectangle so it keeps
|
||||
its properties. We adjust de x,y,width,height and create a custom transform"
|
||||
[shape transform-mtx]
|
||||
(if (gmt/move? transform-mtx)
|
||||
(apply-transform-move shape transform-mtx)
|
||||
(apply-transform-generic shape transform-mtx)))
|
||||
|
||||
(defn- update-group-viewbox
|
||||
"Updates the viewbox for groups imported from SVG's"
|
||||
[{:keys [selrect svg-viewbox] :as group} new-selrect]
|
||||
|
@ -376,24 +405,6 @@
|
|||
(assoc :flip-x (-> mask :flip-x))
|
||||
(assoc :flip-y (-> mask :flip-y)))))
|
||||
|
||||
(defn apply-modifiers
|
||||
[shape modifiers]
|
||||
(let [transform (ctm/modifiers->transform modifiers)]
|
||||
(cond-> shape
|
||||
(and (some? transform)
|
||||
;; Never transform the root frame
|
||||
(not= uuid/zero (:id shape)))
|
||||
(apply-transform transform)
|
||||
|
||||
:always
|
||||
(ctm/apply-structure-modifiers modifiers))))
|
||||
|
||||
(defn apply-objects-modifiers
|
||||
[objects modifiers]
|
||||
(letfn [(process-shape [objects [id modifier]]
|
||||
(d/update-when objects id apply-modifiers (:modifiers modifier)))]
|
||||
(reduce process-shape objects modifiers)))
|
||||
|
||||
(defn transform-shape
|
||||
([shape]
|
||||
(let [modifiers (:modifiers shape)]
|
||||
|
@ -402,9 +413,35 @@
|
|||
(transform-shape modifiers))))
|
||||
|
||||
([shape modifiers]
|
||||
(cond-> shape
|
||||
(and (some? modifiers) (not (ctm/empty? modifiers)))
|
||||
(apply-modifiers modifiers))))
|
||||
(letfn [(apply-modifiers
|
||||
[shape modifiers]
|
||||
(if (ctm/empty? modifiers)
|
||||
shape
|
||||
(let [transform (ctm/modifiers->transform modifiers)]
|
||||
(cond-> shape
|
||||
(and (some? transform) (not= uuid/zero (:id shape))) ;; Never transform the root frame
|
||||
(apply-transform transform)
|
||||
|
||||
(ctm/has-structure? modifiers)
|
||||
(ctm/apply-structure-modifiers modifiers)))))]
|
||||
|
||||
(cond-> shape
|
||||
(and (some? modifiers) (not (ctm/empty? modifiers)))
|
||||
(apply-modifiers modifiers)))))
|
||||
|
||||
(defn apply-objects-modifiers
|
||||
[objects modifiers]
|
||||
|
||||
(loop [objects objects
|
||||
entry (first modifiers)
|
||||
modifiers (rest modifiers)]
|
||||
|
||||
(if (nil? entry)
|
||||
objects
|
||||
(let [[id modifier] entry]
|
||||
(recur (d/update-when objects id transform-shape (:modifiers modifier))
|
||||
(first modifiers)
|
||||
(rest modifiers))))))
|
||||
|
||||
(defn transform-bounds
|
||||
([points modifiers]
|
||||
|
@ -412,7 +449,9 @@
|
|||
|
||||
([points center modifiers]
|
||||
(let [transform (ctm/modifiers->transform modifiers)]
|
||||
(gco/transform-points points center transform))))
|
||||
(cond-> points
|
||||
(some? transform)
|
||||
(gco/transform-points center transform)))))
|
||||
|
||||
(defn transform-selrect
|
||||
[selrect modifiers]
|
||||
|
|
|
@ -156,7 +156,7 @@
|
|||
(if (> num to) to num)))
|
||||
|
||||
(defn almost-zero? [num]
|
||||
(< (abs (double num)) 1e-5))
|
||||
(< (abs (double num)) 1e-4))
|
||||
|
||||
(defonce float-equal-precision 0.001)
|
||||
|
||||
|
|
|
@ -38,21 +38,79 @@
|
|||
;; * rotation
|
||||
;; * change-properties
|
||||
|
||||
;; Private aux functions
|
||||
|
||||
(def conjv (fnil conj []))
|
||||
|
||||
(defn- move-vec? [vector]
|
||||
(or (not (mth/almost-zero? (:x vector)))
|
||||
(not (mth/almost-zero? (:y vector)))))
|
||||
|
||||
(defn- resize-vec? [vector]
|
||||
(or (not (mth/almost-zero? (- (:x vector) 1)))
|
||||
(not (mth/almost-zero? (- (:y vector) 1)))))
|
||||
|
||||
|
||||
(defn- mergeable-move?
|
||||
[op1 op2]
|
||||
(and (= :move (:type op1))
|
||||
(= :move (:type op2))))
|
||||
|
||||
(defn- mergeable-resize?
|
||||
[op1 op2]
|
||||
(and (= :resize (:type op1))
|
||||
(= :resize (:type op2))
|
||||
|
||||
;; Same transforms
|
||||
(gmt/close? (or (:transform op1) (gmt/matrix)) (or (:transform op2) (gmt/matrix)))
|
||||
(gmt/close? (or (:transform-inverse op1) (gmt/matrix)) (or (:transform-inverse op2) (gmt/matrix)))
|
||||
|
||||
;; Same origin
|
||||
(gpt/close? (:origin op1) (:origin op2))))
|
||||
|
||||
(defn- merge-move
|
||||
[op1 op2]
|
||||
{:type :move
|
||||
:vector (gpt/add (:vector op1) (:vector op2))})
|
||||
|
||||
(defn- merge-resize
|
||||
[op1 op2]
|
||||
(let [vector (gpt/point (* (-> op1 :vector :x) (-> op2 :vector :x))
|
||||
(* (-> op1 :vector :y) (-> op2 :vector :y)))]
|
||||
(assoc op1 :vector vector)))
|
||||
|
||||
(defn- maybe-add-move
|
||||
"Check the last operation to check if we can stack it over the last one"
|
||||
[operations op]
|
||||
(if (c/empty? operations)
|
||||
[op]
|
||||
(let [head (peek operations)]
|
||||
(if (mergeable-move? head op)
|
||||
(let [item (merge-move head op)]
|
||||
(cond-> (pop operations)
|
||||
(move-vec? (:vector item))
|
||||
(conj item)))
|
||||
(conj operations op)))))
|
||||
|
||||
(defn- maybe-add-resize
|
||||
"Check the last operation to check if we can stack it over the last one"
|
||||
[operations op]
|
||||
|
||||
(if (c/empty? operations)
|
||||
[op]
|
||||
(let [head (peek operations)]
|
||||
(if (mergeable-resize? head op)
|
||||
(let [item (merge-resize head op)]
|
||||
(cond-> (pop operations)
|
||||
(resize-vec? (:vector item))
|
||||
(conj item)))
|
||||
(conj operations op)))))
|
||||
|
||||
;; Public builder API
|
||||
|
||||
(defn empty []
|
||||
{})
|
||||
|
||||
(defn move-vec? [vector]
|
||||
(or (not (mth/almost-zero? (:x vector)))
|
||||
(not (mth/almost-zero? (:y vector)))))
|
||||
|
||||
(defn resize-vec? [vector]
|
||||
(or (not (mth/almost-zero? (- (:x vector) 1)))
|
||||
(not (mth/almost-zero? (- (:y vector) 1)))))
|
||||
|
||||
(defn move-parent
|
||||
([modifiers x y]
|
||||
(move-parent modifiers (gpt/point x y)))
|
||||
|
@ -66,18 +124,18 @@
|
|||
([modifiers vector origin]
|
||||
(cond-> modifiers
|
||||
(resize-vec? vector)
|
||||
(update :geometry-parent conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin})))
|
||||
(update :geometry-parent maybe-add-resize {:type :resize
|
||||
:vector vector
|
||||
:origin origin})))
|
||||
|
||||
([modifiers vector origin transform transform-inverse]
|
||||
(cond-> modifiers
|
||||
(resize-vec? vector)
|
||||
(update :geometry-parent conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin
|
||||
:transform transform
|
||||
:transform-inverse transform-inverse}))))
|
||||
(update :geometry-parent maybe-add-resize {:type :resize
|
||||
:vector vector
|
||||
:origin origin
|
||||
:transform transform
|
||||
:transform-inverse transform-inverse}))))
|
||||
(defn move
|
||||
([modifiers x y]
|
||||
(move modifiers (gpt/point x y)))
|
||||
|
@ -85,24 +143,24 @@
|
|||
([modifiers vector]
|
||||
(cond-> modifiers
|
||||
(move-vec? vector)
|
||||
(update :geometry-child conjv {:type :move :vector vector}))))
|
||||
(update :geometry-child maybe-add-move {:type :move :vector vector}))))
|
||||
|
||||
(defn resize
|
||||
([modifiers vector origin]
|
||||
(cond-> modifiers
|
||||
(resize-vec? vector)
|
||||
(update :geometry-child conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin})))
|
||||
(update :geometry-child maybe-add-resize {:type :resize
|
||||
:vector vector
|
||||
:origin origin})))
|
||||
|
||||
([modifiers vector origin transform transform-inverse]
|
||||
(cond-> modifiers
|
||||
(resize-vec? vector)
|
||||
(update :geometry-child conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin
|
||||
:transform transform
|
||||
:transform-inverse transform-inverse}))))
|
||||
(update :geometry-child maybe-add-resize {:type :resize
|
||||
:vector vector
|
||||
:origin origin
|
||||
:transform transform
|
||||
:transform-inverse transform-inverse}))))
|
||||
|
||||
(defn rotation
|
||||
[modifiers center angle]
|
||||
|
@ -296,17 +354,20 @@
|
|||
|
||||
(defn only-move?
|
||||
"Returns true if there are only move operations"
|
||||
[modifier]
|
||||
(or (and (= 1 (-> modifier :geometry-child count))
|
||||
(= :move (-> modifier :geometry-child first :type)))
|
||||
(and (= 1 (-> modifier :geometry-parent count))
|
||||
(= :move (-> modifier :geometry-parent first :type)))))
|
||||
[{:keys [geometry-child geometry-parent]}]
|
||||
(and (every? #(= :move (:type %)) geometry-child)
|
||||
(every? #(= :move (:type %)) geometry-parent)))
|
||||
|
||||
(defn has-geometry?
|
||||
[{:keys [geometry-parent geometry-child]}]
|
||||
(or (d/not-empty? geometry-parent)
|
||||
(d/not-empty? geometry-child)))
|
||||
|
||||
(defn has-structure?
|
||||
[{:keys [structure-parent structure-child]}]
|
||||
(or (d/not-empty? structure-parent)
|
||||
(d/not-empty? structure-child)))
|
||||
|
||||
;; Extract subsets of modifiers
|
||||
|
||||
(defn select-child-modifiers
|
||||
|
@ -374,8 +435,9 @@
|
|||
(let [modifiers (if (d/not-empty? (:geometry-parent modifiers))
|
||||
(d/concat-vec (:geometry-parent modifiers) (:geometry-child modifiers))
|
||||
(:geometry-child modifiers))]
|
||||
(->> modifiers
|
||||
(reduce apply-modifier (gmt/matrix))))))
|
||||
(when (d/not-empty? modifiers)
|
||||
(->> modifiers
|
||||
(reduce apply-modifier (gmt/matrix)))))))
|
||||
|
||||
(defn apply-structure-modifiers
|
||||
"Apply structure changes to a shape"
|
||||
|
|
|
@ -200,8 +200,8 @@
|
|||
(when (some? modifiers)
|
||||
(d/mapm (fn [id {modifiers :modifiers}]
|
||||
(let [shape (get objects id)
|
||||
text? (= :text (:type shape))
|
||||
modifiers (cond-> modifiers text? (adapt-text-modifiers shape))]
|
||||
adapt-text? (and (= :text (:type shape)) (not (ctm/only-move? modifiers)))
|
||||
modifiers (cond-> modifiers adapt-text? (adapt-text-modifiers shape))]
|
||||
(ctm/modifiers->transform modifiers)))
|
||||
modifiers))))
|
||||
|
||||
|
@ -214,6 +214,7 @@
|
|||
(mf/deps transforms)
|
||||
(fn []
|
||||
(->> (keys transforms)
|
||||
(filter #(some? (get transforms %)))
|
||||
(mapv (d/getf objects)))))
|
||||
|
||||
prev-shapes (mf/use-var nil)
|
||||
|
|
Loading…
Add table
Reference in a new issue