0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-10 08:50:57 -05:00

Implement svg transform/matrix attribute calculation.

This commit is contained in:
Andrey Antukh 2016-01-17 23:32:28 +02:00
parent 669cdd1395
commit 0f9742a83b

View file

@ -1,17 +1,78 @@
(ns uxbox.svg)
(ns uxbox.svg
"A svg related utils."
(:require [cuerdas.core :as str]
[uxbox.matrix :as mtx]
[uxbox.math :as mth]
[uxbox.util.data :refer (without-keys)]))
(defn translate
[x y]
(str "translate(" x "," y ")"))
(defn translate-matrix
([x]
(translate-matrix x x))
([x y]
(mtx/matrix [[1 0 x]
[0 1 y]
[0 0 1]])))
(defn rotate
[d]
(str "rotate(" d ")"))
(defn scale-matrix
([w]
(scale-matrix w w))
([w h]
(mtx/matrix [[w 0 0]
[0 h 0]
[0 0 1]])))
(defn transform
[{:keys [center] :as opts}]
(let [r (get opts :rotate 0)
{:keys [x y]} center]
(str (translate x y)
(rotate r)
(translate (- x) (- y)))))
(defn rotation-matrix
[^number degrees]
(let [v1 (mth/cos (mth/radiants degrees))
v2 (mth/sin (mth/radiants degrees))
v3 (mth/neg v2)]
(mtx/matrix [[v1 v3 0]
[v2 v1 0]
[0 0 1]])))
(defn apply-translate
[{:keys [x y]}]
(translate-matrix x y))
(defn apply-scale
[{:keys [width height view-box]}]
(if (and width height)
(let [orig-width (nth view-box 2)
orig-height (nth view-box 3)
scale-x (/ width orig-width)
scale-y (/ height orig-height)]
(scale-matrix scale-x scale-y))
(scale-matrix 1 1)))
(defn apply-rotation
[{:keys [rotation x y width height view-box] :or {rotation 0}}]
(let [width (nth view-box 2)
height (nth view-box 3)
x (- width (/ width 2))
y (- height (/ height 2))]
(mtx/multiply (translate-matrix x y)
(rotation-matrix rotation)
(translate-matrix (- x)
(- y)))))
(def interpret-attrs (juxt apply-translate
apply-scale
apply-rotation))
(defn calculate-transform
[attrs]
(let [result (->> (interpret-attrs attrs)
(apply mtx/multiply)
(deref)
(take 6)
(flatten))]
(->> (map #(nth result %) [0 3 1 4 2 5])
(str/join ",")
(str/format "matrix(%s)"))))
(defn apply-transform
[attrs]
(let [transform (calculate-transform attrs)]
(-> attrs
(without-keys [:rotation :width :height :x :y :view-box])
(assoc :transform transform))))