mirror of
https://github.com/penpot/penpot.git
synced 2025-06-11 00:21:39 +02:00
🎉 Add PathData data type
🎉 Add PathData data type
This commit is contained in:
commit
06bfb1ad26
6 changed files with 443 additions and 82 deletions
|
@ -40,76 +40,3 @@
|
||||||
(map (fn [segment]
|
(map (fn [segment]
|
||||||
(.toPersistentMap ^js segment)))
|
(.toPersistentMap ^js segment)))
|
||||||
(parser/parse path-str)))))
|
(parser/parse path-str)))))
|
||||||
|
|
||||||
#?(:cljs
|
|
||||||
(defn content->buffer
|
|
||||||
"Converts the path content into binary format."
|
|
||||||
[content]
|
|
||||||
(let [total (count content)
|
|
||||||
ssize 28
|
|
||||||
buffer (new js/ArrayBuffer (* total ssize))
|
|
||||||
dview (new js/DataView buffer)]
|
|
||||||
(loop [index 0]
|
|
||||||
(when (< index total)
|
|
||||||
(let [segment (nth content index)
|
|
||||||
offset (* index ssize)]
|
|
||||||
(case (:command segment)
|
|
||||||
:move-to
|
|
||||||
(let [{:keys [x y]} (:params segment)]
|
|
||||||
(.setInt16 dview (+ offset 0) 1)
|
|
||||||
(.setFloat32 dview (+ offset 20) x)
|
|
||||||
(.setFloat32 dview (+ offset 24) y))
|
|
||||||
:line-to
|
|
||||||
(let [{:keys [x y]} (:params segment)]
|
|
||||||
(.setInt16 dview (+ offset 0) 2)
|
|
||||||
(.setFloat32 dview (+ offset 20) x)
|
|
||||||
(.setFloat32 dview (+ offset 24) y))
|
|
||||||
:curve-to
|
|
||||||
(let [{:keys [c1x c1y c2x c2y x y]} (:params segment)]
|
|
||||||
(.setInt16 dview (+ offset 0) 3)
|
|
||||||
(.setFloat32 dview (+ offset 4) c1x)
|
|
||||||
(.setFloat32 dview (+ offset 8) c1y)
|
|
||||||
(.setFloat32 dview (+ offset 12) c2x)
|
|
||||||
(.setFloat32 dview (+ offset 16) c2y)
|
|
||||||
(.setFloat32 dview (+ offset 20) x)
|
|
||||||
(.setFloat32 dview (+ offset 24) y))
|
|
||||||
|
|
||||||
:close-path
|
|
||||||
(.setInt16 dview (+ offset 0) 4))
|
|
||||||
(recur (inc index)))))
|
|
||||||
buffer)))
|
|
||||||
|
|
||||||
#?(:cljs
|
|
||||||
(defn buffer->content
|
|
||||||
"Converts the a buffer to a path content vector"
|
|
||||||
[buffer]
|
|
||||||
(assert (instance? js/ArrayBuffer buffer) "expected ArrayBuffer instance")
|
|
||||||
(let [ssize 28
|
|
||||||
total (/ (.-byteLength buffer) ssize)
|
|
||||||
dview (new js/DataView buffer)]
|
|
||||||
(loop [index 0
|
|
||||||
result []]
|
|
||||||
(if (< index total)
|
|
||||||
(let [offset (* index ssize)
|
|
||||||
type (.getInt16 dview (+ offset 0))
|
|
||||||
command (case type
|
|
||||||
1 :move-to
|
|
||||||
2 :line-to
|
|
||||||
3 :curve-to
|
|
||||||
4 :close-path)
|
|
||||||
params (case type
|
|
||||||
1 {:x (.getFloat32 dview (+ offset 20))
|
|
||||||
:y (.getFloat32 dview (+ offset 24))}
|
|
||||||
2 {:x (.getFloat32 dview (+ offset 20))
|
|
||||||
:y (.getFloat32 dview (+ offset 24))}
|
|
||||||
3 {:c1x (.getFloat32 dview (+ offset 4))
|
|
||||||
:c1y (.getFloat32 dview (+ offset 8))
|
|
||||||
:c2x (.getFloat32 dview (+ offset 12))
|
|
||||||
:c2y (.getFloat32 dview (+ offset 16))
|
|
||||||
:x (.getFloat32 dview (+ offset 20))
|
|
||||||
:y (.getFloat32 dview (+ offset 24))}
|
|
||||||
4 {})]
|
|
||||||
(recur (inc index)
|
|
||||||
(conj result {:command command
|
|
||||||
:params params})))
|
|
||||||
result)))))
|
|
||||||
|
|
|
@ -6,7 +6,16 @@
|
||||||
|
|
||||||
(ns app.common.types.shape.path
|
(ns app.common.types.shape.path
|
||||||
(:require
|
(:require
|
||||||
[app.common.schema :as sm]))
|
[app.common.schema :as sm])
|
||||||
|
(:import
|
||||||
|
#?(:cljs [goog.string StringBuffer]
|
||||||
|
:clj [java.nio ByteBuffer])))
|
||||||
|
|
||||||
|
#?(:clj (set! *warn-on-reflection* true))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; SCHEMA: PLAIN FORMAT
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(def schema:line-to-segment
|
(def schema:line-to-segment
|
||||||
[:map
|
[:map
|
||||||
|
@ -52,5 +61,371 @@
|
||||||
(def schema:path-content
|
(def schema:path-content
|
||||||
[:vector schema:path-segment])
|
[:vector schema:path-segment])
|
||||||
|
|
||||||
|
(def check-path-content
|
||||||
|
(sm/check-fn schema:path-content))
|
||||||
|
|
||||||
(sm/register! ::segment schema:path-segment)
|
(sm/register! ::segment schema:path-segment)
|
||||||
(sm/register! ::content schema:path-content)
|
(sm/register! ::content schema:path-content)
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; TYPE: PATH-DATA
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(def ^:const SEGMENT-BYTE-SIZE 28)
|
||||||
|
|
||||||
|
(defprotocol IPathData
|
||||||
|
(-write-to [_ buffer offset] "write the content to the specified buffer"))
|
||||||
|
|
||||||
|
(defrecord PathSegment [command params])
|
||||||
|
|
||||||
|
(defn- get-path-string
|
||||||
|
"Format the path data structure to string"
|
||||||
|
[buffer size]
|
||||||
|
(let [builder #?(:clj (java.lang.StringBuilder. (int (* size 4)))
|
||||||
|
:cljs (StringBuffer.))]
|
||||||
|
(loop [index 0]
|
||||||
|
(when (< index size)
|
||||||
|
(let [offset (* index SEGMENT-BYTE-SIZE)
|
||||||
|
type #?(:clj (.getShort ^ByteBuffer buffer offset)
|
||||||
|
:cljs (.getInt16 buffer offset))]
|
||||||
|
(case (long type)
|
||||||
|
1 (let [x #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 20))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 20)))
|
||||||
|
y #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 24))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 24)))]
|
||||||
|
(doto builder
|
||||||
|
(.append "M")
|
||||||
|
(.append x)
|
||||||
|
(.append ",")
|
||||||
|
(.append y)))
|
||||||
|
2 (let [x #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 20))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 20)))
|
||||||
|
y #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 24))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 24)))]
|
||||||
|
(doto builder
|
||||||
|
(.append "L")
|
||||||
|
(.append x)
|
||||||
|
(.append ",")
|
||||||
|
(.append y)))
|
||||||
|
|
||||||
|
3 (let [c1x #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 4))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 4)))
|
||||||
|
c1y #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 8))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 8)))
|
||||||
|
c2x #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 12))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 12)))
|
||||||
|
c2y #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 16))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 16)))
|
||||||
|
x #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 20))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 20)))
|
||||||
|
y #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 24))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 24)))]
|
||||||
|
(doto builder
|
||||||
|
(.append "C")
|
||||||
|
(.append c1x)
|
||||||
|
(.append ",")
|
||||||
|
(.append c1y)
|
||||||
|
(.append ",")
|
||||||
|
(.append c2x)
|
||||||
|
(.append ",")
|
||||||
|
(.append c2y)
|
||||||
|
(.append ",")
|
||||||
|
(.append x)
|
||||||
|
(.append ",")
|
||||||
|
(.append y)))
|
||||||
|
4 (doto builder
|
||||||
|
(.append "Z")))
|
||||||
|
(recur (inc index)))))
|
||||||
|
|
||||||
|
(.toString builder)))
|
||||||
|
|
||||||
|
(defn- read-segment
|
||||||
|
[buffer index]
|
||||||
|
(let [offset (* index SEGMENT-BYTE-SIZE)
|
||||||
|
type #?(:clj (.getShort ^ByteBuffer buffer offset)
|
||||||
|
:cljs (.getInt16 buffer offset))]
|
||||||
|
(case (long type)
|
||||||
|
1 (let [x #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 20))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 20)))
|
||||||
|
y #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 24))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 24)))]
|
||||||
|
(->PathSegment :move-to {:x x :y y}))
|
||||||
|
|
||||||
|
2 (let [x #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 20))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 20)))
|
||||||
|
y #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 24))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 24)))]
|
||||||
|
(->PathSegment :line-to {:x x :y y}))
|
||||||
|
|
||||||
|
3 (let [c1x #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 4))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 4)))
|
||||||
|
c1y #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 8))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 8)))
|
||||||
|
c2x #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 12))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 12)))
|
||||||
|
c2y #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 16))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 16)))
|
||||||
|
x #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 20))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 20)))
|
||||||
|
y #?(:clj (.getFloat ^ByteBuffer buffer (+ offset 24))
|
||||||
|
:cljs (.getFloat32 buffer (+ offset 24)))]
|
||||||
|
|
||||||
|
(->PathSegment :curve-to {:x x :y y :c1x c1x :c1y c1y :c2x c2x :c2y c2y}))
|
||||||
|
|
||||||
|
4 (->PathSegment :close-path {}))))
|
||||||
|
|
||||||
|
(defn- in-range?
|
||||||
|
[size i]
|
||||||
|
(and (< i size) (>= i 0)))
|
||||||
|
|
||||||
|
#?(:clj
|
||||||
|
(deftype PathData [size buffer]
|
||||||
|
Object
|
||||||
|
(toString [_]
|
||||||
|
(get-path-string buffer size))
|
||||||
|
|
||||||
|
clojure.lang.Sequential
|
||||||
|
clojure.lang.IPersistentCollection
|
||||||
|
|
||||||
|
(empty [_]
|
||||||
|
(throw (ex-info "not implemented" {})))
|
||||||
|
(equiv [_ other]
|
||||||
|
(if (instance? PathData other)
|
||||||
|
(.equals ^ByteBuffer buffer (.-buffer ^PathData other))
|
||||||
|
false))
|
||||||
|
|
||||||
|
(seq [this]
|
||||||
|
(when (pos? size)
|
||||||
|
(->> (range size)
|
||||||
|
(map (fn [i] (nth this i))))))
|
||||||
|
|
||||||
|
(cons [_ _val]
|
||||||
|
(throw (ex-info "not implemented" {})))
|
||||||
|
|
||||||
|
clojure.lang.IReduceInit
|
||||||
|
(reduce [_ f start]
|
||||||
|
(loop [index 0
|
||||||
|
result start]
|
||||||
|
(if (< index size)
|
||||||
|
(let [result (f result (read-segment buffer index))]
|
||||||
|
(if (reduced? result)
|
||||||
|
@result
|
||||||
|
(recur (inc index) result)))
|
||||||
|
result)))
|
||||||
|
|
||||||
|
clojure.lang.Indexed
|
||||||
|
(nth [_ i]
|
||||||
|
(if (in-range? size i)
|
||||||
|
(read-segment buffer i)
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(nth [_ i default]
|
||||||
|
(if (in-range? size i)
|
||||||
|
(read-segment buffer i)
|
||||||
|
default))
|
||||||
|
|
||||||
|
clojure.lang.Counted
|
||||||
|
(count [_] size))
|
||||||
|
|
||||||
|
:cljs
|
||||||
|
(deftype PathData [size buffer dview]
|
||||||
|
Object
|
||||||
|
(toString [_]
|
||||||
|
(get-path-string dview size))
|
||||||
|
|
||||||
|
IPathData
|
||||||
|
(-write-to [_ into-buffer offset]
|
||||||
|
(assert (instance? js/ArrayBuffer into-buffer) "expected an instance of Uint32Array")
|
||||||
|
(let [size (.-byteLength buffer)
|
||||||
|
mem (js/Uint32Array. into-buffer offset size)]
|
||||||
|
(.set mem (js/Uint32Array. buffer))))
|
||||||
|
|
||||||
|
cljs.core/ISequential
|
||||||
|
cljs.core/IEquiv
|
||||||
|
(-equiv [_ other]
|
||||||
|
(if (instance? PathData other)
|
||||||
|
(let [obuffer (.-buffer other)
|
||||||
|
osize (.-byteLength obuffer)
|
||||||
|
csize (.-byteLength buffer)]
|
||||||
|
(if (= osize csize)
|
||||||
|
(let [cb (js/Uint32Array. buffer)
|
||||||
|
ob (js/Uint32Array. obuffer)]
|
||||||
|
(loop [i 0]
|
||||||
|
(if (< i osize)
|
||||||
|
(if (= (aget ob i)
|
||||||
|
(aget cb i))
|
||||||
|
(recur (inc i))
|
||||||
|
false)
|
||||||
|
true)))
|
||||||
|
false))
|
||||||
|
false))
|
||||||
|
|
||||||
|
cljs.core/IReduce
|
||||||
|
(-reduce [_ f]
|
||||||
|
(loop [index 1
|
||||||
|
result (if (pos? size)
|
||||||
|
(read-segment dview 0)
|
||||||
|
nil)]
|
||||||
|
(if (< index size)
|
||||||
|
(let [result (f result (read-segment dview index))]
|
||||||
|
(if (reduced? result)
|
||||||
|
@result
|
||||||
|
(recur (inc index) result)))
|
||||||
|
result)))
|
||||||
|
|
||||||
|
(-reduce [_ f start]
|
||||||
|
(loop [index 0
|
||||||
|
result start]
|
||||||
|
(if (< index size)
|
||||||
|
(let [result (f result (read-segment dview index))]
|
||||||
|
(if (reduced? result)
|
||||||
|
@result
|
||||||
|
(recur (inc index) result)))
|
||||||
|
result)))
|
||||||
|
|
||||||
|
cljs.core/IHash
|
||||||
|
(-hash [_]
|
||||||
|
(throw (ex-info "not-implemented" {})))
|
||||||
|
|
||||||
|
cljs.core/ICounted
|
||||||
|
(-count [_] size)
|
||||||
|
|
||||||
|
cljs.core/IIndexed
|
||||||
|
(-nth [_ i]
|
||||||
|
(if (in-range? size i)
|
||||||
|
(read-segment dview i)
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(-nth [_ i default]
|
||||||
|
(if (in-range? i size)
|
||||||
|
(read-segment dview i)
|
||||||
|
default))
|
||||||
|
|
||||||
|
cljs.core/ISeqable
|
||||||
|
(-seq [this]
|
||||||
|
(when (pos? size)
|
||||||
|
(->> (range size)
|
||||||
|
(map (fn [i] (cljs.core/-nth this i))))))))
|
||||||
|
|
||||||
|
(defn- from-bytes
|
||||||
|
[buffer]
|
||||||
|
#?(:clj
|
||||||
|
(cond
|
||||||
|
(instance? ByteBuffer buffer)
|
||||||
|
(let [size (.capacity ^ByteBuffer buffer)
|
||||||
|
count (long (/ size SEGMENT-BYTE-SIZE))]
|
||||||
|
(PathData. count buffer))
|
||||||
|
|
||||||
|
(bytes? buffer)
|
||||||
|
(let [size (alength ^bytes buffer)
|
||||||
|
count (long (/ size SEGMENT-BYTE-SIZE))]
|
||||||
|
(PathData. count
|
||||||
|
(ByteBuffer/wrap buffer)))
|
||||||
|
|
||||||
|
:else
|
||||||
|
(throw (java.lang.IllegalArgumentException. "invalid data provided")))
|
||||||
|
|
||||||
|
:cljs
|
||||||
|
(cond
|
||||||
|
(instance? js/ArrayBuffer buffer)
|
||||||
|
(let [size (.-byteLength buffer)
|
||||||
|
count (long (/ size SEGMENT-BYTE-SIZE))]
|
||||||
|
(PathData. count
|
||||||
|
buffer
|
||||||
|
(js/DataView. buffer)))
|
||||||
|
|
||||||
|
(instance? js/DataView buffer)
|
||||||
|
(let [dview buffer
|
||||||
|
buffer (.-buffer dview)
|
||||||
|
size (.-byteLength buffer)
|
||||||
|
count (long (/ size SEGMENT-BYTE-SIZE))]
|
||||||
|
(PathData. count buffer dview))
|
||||||
|
|
||||||
|
:else
|
||||||
|
(throw (js/Error. "invalid data provided")))))
|
||||||
|
|
||||||
|
;; FIXME: consider implementing with reduce
|
||||||
|
;; FIXME: consider ensure fixed precision for avoid doing it on formatting
|
||||||
|
|
||||||
|
(defn- from-plain
|
||||||
|
"Create a PathData instance from plain data structures"
|
||||||
|
[content]
|
||||||
|
(assert (check-path-content content))
|
||||||
|
|
||||||
|
(let [content (vec content)
|
||||||
|
total (count content)
|
||||||
|
#?@(:cljs [buffer (new js/ArrayBuffer (* total SEGMENT-BYTE-SIZE))
|
||||||
|
dview (new js/DataView buffer)]
|
||||||
|
:clj [buffer (ByteBuffer/allocate (* total SEGMENT-BYTE-SIZE))])]
|
||||||
|
(loop [index 0]
|
||||||
|
(when (< index total)
|
||||||
|
(let [segment (nth content index)
|
||||||
|
offset (* index SEGMENT-BYTE-SIZE)]
|
||||||
|
(case (get segment :command)
|
||||||
|
:move-to
|
||||||
|
(let [params (get segment :params)
|
||||||
|
x (float (get params :x))
|
||||||
|
y (float (get params :y))]
|
||||||
|
#?(:clj (.putShort buffer (int offset) (short 1))
|
||||||
|
:cljs (.setInt16 dview offset 1))
|
||||||
|
#?(:clj (.putFloat buffer (+ offset 20) x)
|
||||||
|
:cljs (.setFloat32 dview (+ offset 20) x))
|
||||||
|
#?(:clj (.putFloat buffer (+ offset 24) y)
|
||||||
|
:cljs (.setFloat32 dview (+ offset 24) y)))
|
||||||
|
|
||||||
|
:line-to
|
||||||
|
(let [params (get segment :params)
|
||||||
|
x (float (get params :x))
|
||||||
|
y (float (get params :y))]
|
||||||
|
#?(:clj (.putShort buffer (int offset) (short 2))
|
||||||
|
:cljs (.setInt16 dview offset 2))
|
||||||
|
#?(:clj (.putFloat buffer (+ offset 20) x)
|
||||||
|
:cljs (.setFloat32 dview (+ offset 20) x))
|
||||||
|
#?(:clj (.putFloat buffer (+ offset 24) y)
|
||||||
|
:cljs (.setFloat32 dview (+ offset 24) y)))
|
||||||
|
|
||||||
|
:curve-to
|
||||||
|
(let [params (get segment :params)
|
||||||
|
x (float (get params :x))
|
||||||
|
y (float (get params :y))
|
||||||
|
c1x (float (get params :c1x x))
|
||||||
|
c1y (float (get params :c1y y))
|
||||||
|
c2x (float (get params :c2x x))
|
||||||
|
c2y (float (get params :c2y y))]
|
||||||
|
|
||||||
|
#?(:clj (.putShort buffer (int offset) (short 3))
|
||||||
|
:cljs (.setInt16 dview offset 3))
|
||||||
|
#?(:clj (.putFloat buffer (+ offset 4) c1x)
|
||||||
|
:cljs (.setFloat32 dview (+ offset 4) c1x))
|
||||||
|
#?(:clj (.putFloat buffer (+ offset 8) c1y)
|
||||||
|
:cljs (.setFloat32 dview (+ offset 8) c1y))
|
||||||
|
#?(:clj (.putFloat buffer (+ offset 12) c2x)
|
||||||
|
:cljs (.setFloat32 dview (+ offset 12) c2x))
|
||||||
|
#?(:clj (.putFloat buffer (+ offset 16) c2y)
|
||||||
|
:cljs (.setFloat32 dview (+ offset 16) c2y))
|
||||||
|
#?(:clj (.putFloat buffer (+ offset 20) x)
|
||||||
|
:cljs (.setFloat32 dview (+ offset 20) x))
|
||||||
|
#?(:clj (.putFloat buffer (+ offset 24) y)
|
||||||
|
:cljs (.setFloat32 dview (+ offset 24) y)))
|
||||||
|
|
||||||
|
:close-path
|
||||||
|
#?(:clj (.putShort buffer (int offset) (short 4))
|
||||||
|
:cljs (.setInt16 dview offset 4)))
|
||||||
|
(recur (inc index)))))
|
||||||
|
|
||||||
|
#?(:cljs (from-bytes dview)
|
||||||
|
:clj (from-bytes buffer))))
|
||||||
|
|
||||||
|
(defn path-data
|
||||||
|
"Create an instance of PathData, returns itself if it is already
|
||||||
|
PathData instance"
|
||||||
|
[data]
|
||||||
|
(cond
|
||||||
|
(instance? PathData data)
|
||||||
|
data
|
||||||
|
|
||||||
|
(sequential? data)
|
||||||
|
(from-plain data)
|
||||||
|
|
||||||
|
:else
|
||||||
|
(from-bytes data)))
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
[common-tests.types.modifiers-test]
|
[common-tests.types.modifiers-test]
|
||||||
[common-tests.types.shape-decode-encode-test]
|
[common-tests.types.shape-decode-encode-test]
|
||||||
[common-tests.types.shape-interactions-test]
|
[common-tests.types.shape-interactions-test]
|
||||||
|
[common-tests.types.shape-path-data-test]
|
||||||
[common-tests.types.tokens-lib-test]
|
[common-tests.types.tokens-lib-test]
|
||||||
[common-tests.uuid-test]))
|
[common-tests.uuid-test]))
|
||||||
|
|
||||||
|
@ -90,4 +91,5 @@
|
||||||
'common-tests.types.tokens-lib-test
|
'common-tests.types.tokens-lib-test
|
||||||
'common-tests.types.components-test
|
'common-tests.types.components-test
|
||||||
'common-tests.types.absorb-assets-test
|
'common-tests.types.absorb-assets-test
|
||||||
|
'common-tests.types.shape-path-data-test
|
||||||
'common-tests.uuid-test))
|
'common-tests.uuid-test))
|
||||||
|
|
|
@ -547,4 +547,3 @@
|
||||||
|
|
||||||
;; FOR POSSIBLE FUTURE TEST CASES
|
;; FOR POSSIBLE FUTURE TEST CASES
|
||||||
;; (str "M259.958 89.134c-6.88-.354-10.484-1.241-12.44-3.064-1.871-1.743-6.937-3.098-15.793-4.226-7.171-.913-17.179-2.279-22.24-3.034-5.06-.755-15.252-2.016-22.648-2.8-18.685-1.985-35.63-4.223-38.572-5.096-3.655-1.084-3.016-3.548.708-2.726 1.751.387 13.376 1.701 25.833 2.922 12.456 1.22 29.018 3.114 36.803 4.208 29.94 4.206 29.433 4.204 34.267.136 3.787-3.186 5.669-3.669 14.303-3.669 14.338 0 17.18 1.681 12.182 7.205-2.053 2.268-1.994 2.719.707 5.42 3.828 3.827 3.74 5.846-.238 5.5-1.752-.153-7.544-.502-12.872-.776zm7.563-3.194c0-.778-1.751-1.352-3.892-1.274l-3.893.141 3.539 1.133c1.946.624 3.698 1.197 3.893 1.275.194.077.354-.496.354-1.275zm-15.899-8.493c1.43-2.29 1.414-2.83-.084-2.83-2.05 0-5.25 2.76-5.25 4.529 0 2.226 3.599 1.08 5.334-1.699zm8.114 0c2.486-2.746 2.473-2.83-.438-2.83-1.65 0-3.683 1.273-4.516 2.83-1.175 2.196-1.077 2.831.438 2.831 1.075 0 3.107-1.274 4.516-2.83zm7.814.674c2.858-3.444.476-4.085-3.033-.816-2.451 2.284-2.677 2.973-.975 2.973 1.22 0 3.023-.97 4.008-2.157zm-49.571-4.509c-1.168-.43-3.294-1.802-4.725-3.051-2.112-1.843-9.304-2.595-38.219-3.994-46.474-2.25-63-4.077-60.27-6.665.324-.308 9.507.261 20.406 1.264 10.9 1.003 31.16 2.258 45.024 2.789l25.207.964 4.625-3.527c4.313-3.29 5.41-3.474 16.24-2.732 6.389.438 11.981 1.388 12.428 2.111.447.723-.517 2.73-2.141 4.46l-2.954 3.144c1.607 1.697 3.308 3.289 5.049 4.845 3.248 2.189-5.438 1.289-8.678 1.284-5.428-.061-10.825-.463-11.992-.892zm12.74-3.242c-1.123-.694-2.36-.943-2.75-.554-.389.39.21 1.275 1.334 1.97 1.122.693 2.36.942 2.749.553.389-.39-.21-1.275-1.334-1.97zm-5.663 0a1.42 1.42 0 00-1.415-1.416 1.42 1.42 0 00-1.416 1.416 1.42 1.42 0 001.416 1.415 1.42 1.42 0 001.415-1.415zm-8.464-6.404c.984-1.187 1.35-2.598.813-3.135-1.181-1.18-5.408 1.297-6.184 3.624-.806 2.42 3.265 2.048 5.37-.49zm6.863.258c.867-1.045 1.163-2.313.658-2.819-1.063-1.062-4.719 1.631-4.719 3.476 0 1.864 2.274 1.496 4.061-.657zm8.792-.36c1.637-1.972 1.448-2.197-1.486-1.77-1.848.27-3.622 1.287-3.943 2.26-.838 2.547 3.212 2.181 5.429-.49zm32.443-4.11c-6.156-2.228-67.1-6.138-119.124-7.642-39.208-1.134-72.072-.928-94.618.593-6.617.446-19.681 1.16-29.03 1.587-15.798.72-17.183.573-19.588-2.085-4.498-4.97-2.544-7.857 6.39-9.44 4.394-.778 9.164-2.436 10.6-3.685 5.44-4.729 20.332-14.06 31.14-19.509C65.717 11.88 78.955 7.79 103.837 3.08 121.686-.3 125.552-.642 129.318.82c2.44.948 12.4 1.948 22.132 2.221 15.37.432 20.004 1.18 35.294 5.698 22.36 6.606 39.732 15.1 56.55 27.653 7.307 5.452 14.086 9.913 15.066 9.913.98 0 2.148.956 2.596 2.124.55 1.432 2.798 2.123 6.914 2.123 6.213 0 12.4 3.046 12.38 6.096-.012 1.75-6.502 5.353-9.118 5.063-.818-.09-3.717-.972-6.442-1.958zm-16.986-7.436c0-1.575-33.326-18.118-43.173-21.43-23.008-7.739-54.084-12.922-77.136-12.866-16.863.041-37.877 3.628-52.465 8.956-18.062 6.596-26.563 10.384-29.181 13.002-1.205 1.205-5.306 3.769-9.112 5.698-7.754 3.929-8.841 5.482-3.029 4.325 13.494-2.685 66.794-3.773 110.913-2.264 38.005 1.3 96.812 4.435 102.122 5.443.584.111 1.061-.277 1.061-.864zm-236.39-3.18c0-.78-1.592-1.416-3.539-1.416-1.946 0-3.538.637-3.538 1.415 0 .779 1.592 1.416 3.538 1.416 1.947 0 3.54-.637 3.54-1.416zm7.078-1.416c0-.779-.956-1.416-2.124-1.416-1.167 0-2.123.637-2.123 1.416 0 .778.956 1.415 2.123 1.415 1.168 0 2.124-.637 2.124-1.415zm11.734-4.437c3.278-1.661 6.278-3.483 6.667-4.048 1.366-1.98 20.645-11.231 32.557-15.622 11.862-4.372 36.546-9.865 44.327-9.865 3.485 0 3.867-.404 3.012-3.185-.538-1.752-1.177-3.41-1.42-3.685-.907-1.026-36.72 7.16-45.065 10.302-17.226 6.484-47.566 24.27-47.566 27.886 0 1.786.845 1.585 7.488-1.783zm206.254-5.577c-12.298-10.518-53.842-27.166-70.896-28.41-5.526-.404-6.3-.097-6.695 2.655-.33 2.307.402 3.275 2.831 3.742 32.436 6.237 52.205 12.315 66.975 20.594 11.904 6.673 14.477 7.141 7.785 1.419zM150.1 11.04c-1.949-3.64-7.568-4.078-6.886-.538.256 1.329 2.054 2.817 3.997 3.309 4.498 1.137 4.816.832 2.888-2.771zm6.756.94c-.248-1.752-1.026-3.185-1.727-3.185-.7 0-1.493 1.433-1.76 3.185-.328 2.152.232 3.185 1.727 3.185 1.485 0 2.064-1.047 1.76-3.185zm-30.178-2.458c0-2.303-.908-3.694-2.627-4.025-3.6-.694-5.23 1.301-4.22 5.166 1.216 4.647 6.847 3.709 6.847-1.14zm12.544 2.104c-.448-1.168-1.224-2.132-1.725-2.142-.5-.013-2.343-.404-4.095-.873-2.569-.689-3.185-.274-3.185 2.142 0 2.476.854 2.996 4.91 2.996 3.783 0 4.723-.487 4.095-2.123z")
|
;; (str "M259.958 89.134c-6.88-.354-10.484-1.241-12.44-3.064-1.871-1.743-6.937-3.098-15.793-4.226-7.171-.913-17.179-2.279-22.24-3.034-5.06-.755-15.252-2.016-22.648-2.8-18.685-1.985-35.63-4.223-38.572-5.096-3.655-1.084-3.016-3.548.708-2.726 1.751.387 13.376 1.701 25.833 2.922 12.456 1.22 29.018 3.114 36.803 4.208 29.94 4.206 29.433 4.204 34.267.136 3.787-3.186 5.669-3.669 14.303-3.669 14.338 0 17.18 1.681 12.182 7.205-2.053 2.268-1.994 2.719.707 5.42 3.828 3.827 3.74 5.846-.238 5.5-1.752-.153-7.544-.502-12.872-.776zm7.563-3.194c0-.778-1.751-1.352-3.892-1.274l-3.893.141 3.539 1.133c1.946.624 3.698 1.197 3.893 1.275.194.077.354-.496.354-1.275zm-15.899-8.493c1.43-2.29 1.414-2.83-.084-2.83-2.05 0-5.25 2.76-5.25 4.529 0 2.226 3.599 1.08 5.334-1.699zm8.114 0c2.486-2.746 2.473-2.83-.438-2.83-1.65 0-3.683 1.273-4.516 2.83-1.175 2.196-1.077 2.831.438 2.831 1.075 0 3.107-1.274 4.516-2.83zm7.814.674c2.858-3.444.476-4.085-3.033-.816-2.451 2.284-2.677 2.973-.975 2.973 1.22 0 3.023-.97 4.008-2.157zm-49.571-4.509c-1.168-.43-3.294-1.802-4.725-3.051-2.112-1.843-9.304-2.595-38.219-3.994-46.474-2.25-63-4.077-60.27-6.665.324-.308 9.507.261 20.406 1.264 10.9 1.003 31.16 2.258 45.024 2.789l25.207.964 4.625-3.527c4.313-3.29 5.41-3.474 16.24-2.732 6.389.438 11.981 1.388 12.428 2.111.447.723-.517 2.73-2.141 4.46l-2.954 3.144c1.607 1.697 3.308 3.289 5.049 4.845 3.248 2.189-5.438 1.289-8.678 1.284-5.428-.061-10.825-.463-11.992-.892zm12.74-3.242c-1.123-.694-2.36-.943-2.75-.554-.389.39.21 1.275 1.334 1.97 1.122.693 2.36.942 2.749.553.389-.39-.21-1.275-1.334-1.97zm-5.663 0a1.42 1.42 0 00-1.415-1.416 1.42 1.42 0 00-1.416 1.416 1.42 1.42 0 001.416 1.415 1.42 1.42 0 001.415-1.415zm-8.464-6.404c.984-1.187 1.35-2.598.813-3.135-1.181-1.18-5.408 1.297-6.184 3.624-.806 2.42 3.265 2.048 5.37-.49zm6.863.258c.867-1.045 1.163-2.313.658-2.819-1.063-1.062-4.719 1.631-4.719 3.476 0 1.864 2.274 1.496 4.061-.657zm8.792-.36c1.637-1.972 1.448-2.197-1.486-1.77-1.848.27-3.622 1.287-3.943 2.26-.838 2.547 3.212 2.181 5.429-.49zm32.443-4.11c-6.156-2.228-67.1-6.138-119.124-7.642-39.208-1.134-72.072-.928-94.618.593-6.617.446-19.681 1.16-29.03 1.587-15.798.72-17.183.573-19.588-2.085-4.498-4.97-2.544-7.857 6.39-9.44 4.394-.778 9.164-2.436 10.6-3.685 5.44-4.729 20.332-14.06 31.14-19.509C65.717 11.88 78.955 7.79 103.837 3.08 121.686-.3 125.552-.642 129.318.82c2.44.948 12.4 1.948 22.132 2.221 15.37.432 20.004 1.18 35.294 5.698 22.36 6.606 39.732 15.1 56.55 27.653 7.307 5.452 14.086 9.913 15.066 9.913.98 0 2.148.956 2.596 2.124.55 1.432 2.798 2.123 6.914 2.123 6.213 0 12.4 3.046 12.38 6.096-.012 1.75-6.502 5.353-9.118 5.063-.818-.09-3.717-.972-6.442-1.958zm-16.986-7.436c0-1.575-33.326-18.118-43.173-21.43-23.008-7.739-54.084-12.922-77.136-12.866-16.863.041-37.877 3.628-52.465 8.956-18.062 6.596-26.563 10.384-29.181 13.002-1.205 1.205-5.306 3.769-9.112 5.698-7.754 3.929-8.841 5.482-3.029 4.325 13.494-2.685 66.794-3.773 110.913-2.264 38.005 1.3 96.812 4.435 102.122 5.443.584.111 1.061-.277 1.061-.864zm-236.39-3.18c0-.78-1.592-1.416-3.539-1.416-1.946 0-3.538.637-3.538 1.415 0 .779 1.592 1.416 3.538 1.416 1.947 0 3.54-.637 3.54-1.416zm7.078-1.416c0-.779-.956-1.416-2.124-1.416-1.167 0-2.123.637-2.123 1.416 0 .778.956 1.415 2.123 1.415 1.168 0 2.124-.637 2.124-1.415zm11.734-4.437c3.278-1.661 6.278-3.483 6.667-4.048 1.366-1.98 20.645-11.231 32.557-15.622 11.862-4.372 36.546-9.865 44.327-9.865 3.485 0 3.867-.404 3.012-3.185-.538-1.752-1.177-3.41-1.42-3.685-.907-1.026-36.72 7.16-45.065 10.302-17.226 6.484-47.566 24.27-47.566 27.886 0 1.786.845 1.585 7.488-1.783zm206.254-5.577c-12.298-10.518-53.842-27.166-70.896-28.41-5.526-.404-6.3-.097-6.695 2.655-.33 2.307.402 3.275 2.831 3.742 32.436 6.237 52.205 12.315 66.975 20.594 11.904 6.673 14.477 7.141 7.785 1.419zM150.1 11.04c-1.949-3.64-7.568-4.078-6.886-.538.256 1.329 2.054 2.817 3.997 3.309 4.498 1.137 4.816.832 2.888-2.771zm6.756.94c-.248-1.752-1.026-3.185-1.727-3.185-.7 0-1.493 1.433-1.76 3.185-.328 2.152.232 3.185 1.727 3.185 1.485 0 2.064-1.047 1.76-3.185zm-30.178-2.458c0-2.303-.908-3.694-2.627-4.025-3.6-.694-5.23 1.301-4.22 5.166 1.216 4.647 6.847 3.709 6.847-1.14zm12.544 2.104c-.448-1.168-1.224-2.132-1.725-2.142-.5-.013-2.343-.404-4.095-.873-2.569-.689-3.185-.274-3.185 2.142 0 2.476.854 2.996 4.91 2.996 3.783 0 4.723-.487 4.095-2.123z")
|
||||||
|
|
||||||
|
|
59
common/test/common_tests/types/shape_path_data_test.cljc
Normal file
59
common/test/common_tests/types/shape_path_data_test.cljc
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns common-tests.types.shape-path-data-test
|
||||||
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.common.math :as mth]
|
||||||
|
[app.common.pprint :as pp]
|
||||||
|
[app.common.types.shape.path :as path]
|
||||||
|
[clojure.test :as t]))
|
||||||
|
|
||||||
|
(def sample-content
|
||||||
|
[{:command :move-to, :params {:x 480.0, :y 839.0}}
|
||||||
|
{:command :line-to, :params {:x 439.0, :y 802.0}}
|
||||||
|
{:command :curve-to, :params {:c1x 368.0, :c1y 737.0, :c2x 310.0, :c2y 681.0, :x 264.0, :y 634.0}}
|
||||||
|
{:command :close-path :params {}}])
|
||||||
|
|
||||||
|
(def sample-bytes
|
||||||
|
[0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 67 -16 0 0 68 81 -64 0
|
||||||
|
0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 67 -37 -128 0 68 72 -128 0
|
||||||
|
0 3 0 0 67 -72 0 0 68 56 64 0 67 -101 0 0 68 42 64 0 67 -124 0 0 68 30 -128 0
|
||||||
|
0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0])
|
||||||
|
|
||||||
|
;; This means it implements IReduceInit/IReduce protocols
|
||||||
|
(t/deftest path-data-to-vector
|
||||||
|
(let [pdata (path/path-data sample-content)
|
||||||
|
result (vec pdata)]
|
||||||
|
(t/is (= 4 (count result)))
|
||||||
|
(t/is (= (get-in sample-content [0 :command])
|
||||||
|
(get-in result [0 :command])))
|
||||||
|
(t/is (= (get-in sample-content [1 :command])
|
||||||
|
(get-in result [1 :command])))
|
||||||
|
(t/is (= (get-in sample-content [2 :command])
|
||||||
|
(get-in result [2 :command])))
|
||||||
|
(t/is (= (get-in sample-content [3 :command])
|
||||||
|
(get-in result [3 :command])))
|
||||||
|
|
||||||
|
(t/is (= (get-in sample-content [0 :params])
|
||||||
|
(get-in result [0 :params])))
|
||||||
|
(t/is (= (get-in sample-content [1 :params])
|
||||||
|
(get-in result [1 :params])))
|
||||||
|
(t/is (= (get-in sample-content [2 :params])
|
||||||
|
(get-in result [2 :params])))
|
||||||
|
(t/is (= (get-in sample-content [3 :params])
|
||||||
|
(get-in result [3 :params])))))
|
||||||
|
|
||||||
|
(t/deftest path-data-plain-to-binary
|
||||||
|
(let [pdata (path/path-data sample-content)]
|
||||||
|
(t/is (= sample-bytes
|
||||||
|
(vec
|
||||||
|
#?(:cljs (js/Int8Array. (.-buffer pdata))
|
||||||
|
:clj (.array (.-buffer pdata))))))
|
||||||
|
(t/is (= (->> sample-content
|
||||||
|
(mapv path/map->PathSegment))
|
||||||
|
(vec pdata)))))
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.svg.path :as path]
|
|
||||||
[app.common.types.shape.layout :as ctl]
|
[app.common.types.shape.layout :as ctl]
|
||||||
|
[app.common.types.shape.path :as path]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
@ -373,12 +373,11 @@
|
||||||
|
|
||||||
(defn set-shape-path-content
|
(defn set-shape-path-content
|
||||||
[content]
|
[content]
|
||||||
(let [buffer (path/content->buffer content)
|
(let [pdata (path/path-data content)
|
||||||
size (.-byteLength buffer)
|
size (* (count pdata) path/SEGMENT-BYTE-SIZE)
|
||||||
ptr (h/call internal-module "_alloc_bytes" size)
|
offset (h/call internal-module "_alloc_bytes" size)
|
||||||
heap (gobj/get ^js internal-module "HEAPU8")
|
heap (gobj/get ^js internal-module "HEAPU8")]
|
||||||
mem (js/Uint8Array. (.-buffer heap) ptr size)]
|
(path/-write-to pdata (.-buffer heap) offset)
|
||||||
(.set mem (js/Uint8Array. buffer))
|
|
||||||
(h/call internal-module "_set_shape_path_content")))
|
(h/call internal-module "_set_shape_path_content")))
|
||||||
|
|
||||||
(defn set-shape-svg-raw-content
|
(defn set-shape-svg-raw-content
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue