mirror of
https://github.com/penpot/penpot.git
synced 2025-06-02 11:31:39 +02:00
♻️ Use LITTLE_ENDIAN instead of BIG_ENDIAND for path encoding
This commit is contained in:
parent
b48faf8fe0
commit
c6f68e6ed1
4 changed files with 59 additions and 56 deletions
|
@ -22,7 +22,7 @@
|
||||||
[app.common.types.path :as-alias path])
|
[app.common.types.path :as-alias path])
|
||||||
(:import
|
(:import
|
||||||
#?(:cljs [goog.string StringBuffer]
|
#?(:cljs [goog.string StringBuffer]
|
||||||
:clj [java.nio ByteBuffer])))
|
:clj [java.nio ByteBuffer ByteOrder])))
|
||||||
|
|
||||||
#?(:clj (set! *warn-on-reflection* true))
|
#?(:clj (set! *warn-on-reflection* true))
|
||||||
|
|
||||||
|
@ -45,33 +45,29 @@
|
||||||
(defmacro read-short
|
(defmacro read-short
|
||||||
[target offset]
|
[target offset]
|
||||||
(if (:ns &env)
|
(if (:ns &env)
|
||||||
`(.getInt16 ~target ~offset)
|
`(.getInt16 ~target ~offset true)
|
||||||
(let [target (with-meta target {:tag 'java.nio.ByteBuffer})
|
(let [target (with-meta target {:tag 'java.nio.ByteBuffer})]
|
||||||
offset (with-meta target {:tag 'int})]
|
|
||||||
`(.getShort ~target ~offset))))
|
`(.getShort ~target ~offset))))
|
||||||
|
|
||||||
(defmacro read-float
|
(defmacro read-float
|
||||||
[target offset]
|
[target offset]
|
||||||
(if (:ns &env)
|
(if (:ns &env)
|
||||||
`(.getFloat32 ~target ~offset)
|
`(.getFloat32 ~target ~offset true)
|
||||||
(let [target (with-meta target {:tag 'java.nio.ByteBuffer})
|
(let [target (with-meta target {:tag 'java.nio.ByteBuffer})]
|
||||||
offset (with-meta target {:tag 'int})]
|
`(double (.getFloat ~target ~offset)))))
|
||||||
`(.getFloat ~target ~offset))))
|
|
||||||
|
|
||||||
(defmacro write-float
|
(defmacro write-float
|
||||||
[target offset value]
|
[target offset value]
|
||||||
(if (:ns &env)
|
(if (:ns &env)
|
||||||
`(.setFloat32 ~target ~offset ~value)
|
`(.setFloat32 ~target ~offset ~value true)
|
||||||
(let [target (with-meta target {:tag 'java.nio.ByteBuffer})
|
(let [target (with-meta target {:tag 'java.nio.ByteBuffer})]
|
||||||
offset (with-meta target {:tag 'int})]
|
|
||||||
`(.putFloat ~target ~offset ~value))))
|
`(.putFloat ~target ~offset ~value))))
|
||||||
|
|
||||||
(defmacro write-short
|
(defmacro write-short
|
||||||
[target offset value]
|
[target offset value]
|
||||||
(if (:ns &env)
|
(if (:ns &env)
|
||||||
`(.setInt16 ~target ~offset ~value)
|
`(.setInt16 ~target ~offset ~value true)
|
||||||
(let [target (with-meta target {:tag 'java.nio.ByteBuffer})
|
(let [target (with-meta target {:tag 'java.nio.ByteBuffer})]
|
||||||
offset (with-meta target {:tag 'int})]
|
|
||||||
`(.putShort ~target ~offset ~value))))
|
`(.putShort ~target ~offset ~value))))
|
||||||
|
|
||||||
(defmacro with-cache
|
(defmacro with-cache
|
||||||
|
@ -91,6 +87,28 @@
|
||||||
~'result))))
|
~'result))))
|
||||||
`(do ~@expr)))
|
`(do ~@expr)))
|
||||||
|
|
||||||
|
(defn- allocate
|
||||||
|
[n-segments]
|
||||||
|
#?(:clj (let [buffer (ByteBuffer/allocate (* n-segments SEGMENT-BYTE-SIZE))]
|
||||||
|
(.order buffer ByteOrder/LITTLE_ENDIAN))
|
||||||
|
:cljs (new js/ArrayBuffer (* n-segments SEGMENT-BYTE-SIZE))))
|
||||||
|
|
||||||
|
(defn- clone-buffer
|
||||||
|
[buffer]
|
||||||
|
#?(:clj
|
||||||
|
(let [src (.array ^ByteBuffer buffer)
|
||||||
|
len (alength ^bytes src)
|
||||||
|
dst (byte-array len)]
|
||||||
|
(System/arraycopy src 0 dst 0 len)
|
||||||
|
(let [buffer (ByteBuffer/wrap dst)]
|
||||||
|
(.order buffer ByteOrder/LITTLE_ENDIAN)))
|
||||||
|
:cljs
|
||||||
|
(let [src-view (js/Uint32Array. buffer)
|
||||||
|
dst-buff (js/ArrayBuffer. (.-byteLength buffer))
|
||||||
|
dst-view (js/Uint32Array. dst-buff)]
|
||||||
|
(.set dst-view src-view)
|
||||||
|
dst-buff)))
|
||||||
|
|
||||||
(defn- impl-transform-segment
|
(defn- impl-transform-segment
|
||||||
"Apply a transformation to a segment located under specified offset"
|
"Apply a transformation to a segment located under specified offset"
|
||||||
[buffer offset a b c d e f]
|
[buffer offset a b c d e f]
|
||||||
|
@ -302,21 +320,6 @@
|
||||||
[size i]
|
[size i]
|
||||||
(and (< i size) (>= i 0)))
|
(and (< i size) (>= i 0)))
|
||||||
|
|
||||||
(defn- clone-buffer
|
|
||||||
[buffer]
|
|
||||||
#?(:clj
|
|
||||||
(let [src (.array ^ByteBuffer buffer)
|
|
||||||
len (alength ^bytes src)
|
|
||||||
dst (byte-array len)]
|
|
||||||
(System/arraycopy src 0 dst 0 len)
|
|
||||||
(ByteBuffer/wrap dst))
|
|
||||||
:cljs
|
|
||||||
(let [src-view (js/Uint32Array. buffer)
|
|
||||||
dst-buff (js/ArrayBuffer. (.-byteLength buffer))
|
|
||||||
dst-view (js/Uint32Array. dst-buff)]
|
|
||||||
(.set dst-view src-view)
|
|
||||||
dst-buff)))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; TYPE: PATH-DATA
|
;; TYPE: PATH-DATA
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -628,17 +631,18 @@
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(cond
|
(cond
|
||||||
(instance? ByteBuffer buffer)
|
(instance? ByteBuffer buffer)
|
||||||
(let [size (.capacity ^ByteBuffer buffer)
|
(let [size (.capacity ^ByteBuffer buffer)
|
||||||
count (long (/ size SEGMENT-BYTE-SIZE))]
|
count (long (/ size SEGMENT-BYTE-SIZE))
|
||||||
|
buffer (.order ^ByteBuffer buffer ByteOrder/LITTLE_ENDIAN)]
|
||||||
(PathData. count buffer nil))
|
(PathData. count buffer nil))
|
||||||
|
|
||||||
(bytes? buffer)
|
(bytes? buffer)
|
||||||
(let [size (alength ^bytes buffer)
|
(let [size (alength ^bytes buffer)
|
||||||
count (long (/ size SEGMENT-BYTE-SIZE))]
|
count (long (/ size SEGMENT-BYTE-SIZE))
|
||||||
|
buffer (ByteBuffer/wrap buffer)]
|
||||||
(PathData. count
|
(PathData. count
|
||||||
(ByteBuffer/wrap buffer)
|
(.order buffer ByteOrder/LITTLE_ENDIAN)
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(throw (java.lang.IllegalArgumentException. "invalid data provided")))
|
(throw (java.lang.IllegalArgumentException. "invalid data provided")))
|
||||||
|
|
||||||
|
@ -678,9 +682,9 @@
|
||||||
(assert (check-segments segments))
|
(assert (check-segments segments))
|
||||||
|
|
||||||
(let [total (count segments)
|
(let [total (count segments)
|
||||||
#?@(:cljs [buffer' (new js/ArrayBuffer (* total SEGMENT-BYTE-SIZE))
|
#?@(:cljs [buffer' (allocate total)
|
||||||
buffer (new js/DataView buffer')]
|
buffer (new js/DataView buffer')]
|
||||||
:clj [buffer (ByteBuffer/allocate (* total SEGMENT-BYTE-SIZE))])]
|
:clj [buffer (allocate total)])]
|
||||||
(loop [index 0]
|
(loop [index 0]
|
||||||
(when (< index total)
|
(when (< index total)
|
||||||
(let [segment (nth segments index)
|
(let [segment (nth segments index)
|
||||||
|
|
|
@ -69,10 +69,10 @@
|
||||||
{:command :close-path :params {}}])
|
{:command :close-path :params {}}])
|
||||||
|
|
||||||
(def sample-bytes
|
(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
|
[1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -16 67 0 -64 81 68
|
||||||
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
|
2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -128 -37 67 0 -128 72 68
|
||||||
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
|
3 0 0 0 0 0 -72 67 0 64 56 68 0 0 -101 67 0 64 42 68 0 0 -124 67 0 -128 30 68
|
||||||
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])
|
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 0])
|
||||||
|
|
||||||
;; This means it implements IReduceInit/IReduce protocols
|
;; This means it implements IReduceInit/IReduce protocols
|
||||||
(t/deftest path-data-to-vector
|
(t/deftest path-data-to-vector
|
||||||
|
@ -116,10 +116,11 @@
|
||||||
(t/deftest path-data-transit-roundtrip
|
(t/deftest path-data-transit-roundtrip
|
||||||
(let [pdata (path/content sample-content)
|
(let [pdata (path/content sample-content)
|
||||||
result1 (trans/encode-str pdata)
|
result1 (trans/encode-str pdata)
|
||||||
expected (str "[\"~#penpot/path-data\",\"~bAAEAAAAAAAAAAAAAAAAAAAAAAA"
|
expected (str "[\"~#penpot/path-data\",\"~bAQAAAAAAAAAAAAA"
|
||||||
"BD8AAARFHAAAACAAAAAAAAAAAAAAAAAAAAAAAAQ9uAAERIgAAAAwAA"
|
"AAAAAAAAAAAAAAPBDAMBRRAIAAAAAAAAAAAAAAAAAAA"
|
||||||
"Q7gAAEQ4QABDmwAARCpAAEOEAABEHoAAAAQAAAAAAAAAAAAAAAAAAA"
|
"AAAAAAAIDbQwCASEQDAAAAAAC4QwBAOEQAAJtDAEAqR"
|
||||||
"AAAAAAAAAAAAAAAA==\"]")
|
"AAAhEMAgB5EBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||||
|
"AAAAAA==\"]")
|
||||||
result2 (trans/decode-str result1)]
|
result2 (trans/decode-str result1)]
|
||||||
(t/is (= expected result1))
|
(t/is (= expected result1))
|
||||||
(t/is (= pdata result2))))
|
(t/is (= pdata result2))))
|
||||||
|
@ -352,7 +353,6 @@
|
||||||
(t/is (= result5 expect2))
|
(t/is (= result5 expect2))
|
||||||
(t/is (= result6 expect3))))
|
(t/is (= result6 expect3))))
|
||||||
|
|
||||||
|
|
||||||
(defn get-handlers
|
(defn get-handlers
|
||||||
"Retrieve a map where for every point will retrieve a list of
|
"Retrieve a map where for every point will retrieve a list of
|
||||||
the handlers that are associated with that point.
|
the handlers that are associated with that point.
|
||||||
|
@ -375,7 +375,6 @@
|
||||||
|
|
||||||
(t/deftest content-to-handlers
|
(t/deftest content-to-handlers
|
||||||
(let [content (path/content sample-content-large)
|
(let [content (path/content sample-content-large)
|
||||||
result1 (get-handlers content)
|
result1 (get-handlers sample-content-large)
|
||||||
result2 (path.segment/get-handlers content)]
|
result2 (path.segment/get-handlers content)]
|
||||||
|
|
||||||
(t/is (= result1 result2))))
|
(t/is (= result1 result2))))
|
||||||
|
|
|
@ -448,7 +448,7 @@
|
||||||
},
|
},
|
||||||
"~:rotation": 0,
|
"~:rotation": 0,
|
||||||
"~:grow-type": "~:fixed",
|
"~:grow-type": "~:fixed",
|
||||||
"~:content": ["~#penpot/path-data","~bAAEAAAAAAAAAAAAAAAAAAAAAAABEjCAARAqAAAACAAAAAAAAAAAAAAAAAAAAAAAARJmgAEPlAAAAAwAARJmgAEPlAABEpQAAQ/YAAESi4ABEAYAAAAMAAESgwABECAAARJ1AAEQPAABEmGAARBIAAAADAABEk4AARBUAAESMIABECoAARIwgAEQKgAA="],
|
"~:content": ["~#penpot/path-data","~bAQAAAAAAAAAAAAAAAAAAAAAAAAAAIIxEAIAKRAIAAAAAAAAAAAAAAAAAAAAAAAAAAKCZRAAA5UMDAAAAAKCZRAAA5UMAAKVEAAD2QwDgokQAgAFEAwAAAADAoEQAAAhEAECdRAAAD0QAYJhEAAASRAMAAAAAgJNEAAAVRAAgjEQAgApEACCMRACACkQ="],
|
||||||
"~:name": "Path",
|
"~:name": "Path",
|
||||||
"~:width": null,
|
"~:width": null,
|
||||||
"~:type": "~:path",
|
"~:type": "~:path",
|
||||||
|
|
|
@ -14,26 +14,26 @@ pub struct RawPathData {
|
||||||
|
|
||||||
impl RawPathData {
|
impl RawPathData {
|
||||||
fn command(&self) -> Result<u16, String> {
|
fn command(&self) -> Result<u16, String> {
|
||||||
let cmd = u16::from_be_bytes(self.data[0..2].try_into().map_err(stringify_slice_err)?);
|
let cmd = u16::from_le_bytes(self.data[0..2].try_into().map_err(stringify_slice_err)?);
|
||||||
Ok(cmd)
|
Ok(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn xy(&self) -> Result<Point, String> {
|
fn xy(&self) -> Result<Point, String> {
|
||||||
let x = f32::from_be_bytes(self.data[20..24].try_into().map_err(stringify_slice_err)?);
|
let x = f32::from_le_bytes(self.data[20..24].try_into().map_err(stringify_slice_err)?);
|
||||||
let y = f32::from_be_bytes(self.data[24..].try_into().map_err(stringify_slice_err)?);
|
let y = f32::from_le_bytes(self.data[24..].try_into().map_err(stringify_slice_err)?);
|
||||||
Ok((x, y))
|
Ok((x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn c1(&self) -> Result<Point, String> {
|
fn c1(&self) -> Result<Point, String> {
|
||||||
let c1_x = f32::from_be_bytes(self.data[4..8].try_into().map_err(stringify_slice_err)?);
|
let c1_x = f32::from_le_bytes(self.data[4..8].try_into().map_err(stringify_slice_err)?);
|
||||||
let c1_y = f32::from_be_bytes(self.data[8..12].try_into().map_err(stringify_slice_err)?);
|
let c1_y = f32::from_le_bytes(self.data[8..12].try_into().map_err(stringify_slice_err)?);
|
||||||
|
|
||||||
Ok((c1_x, c1_y))
|
Ok((c1_x, c1_y))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn c2(&self) -> Result<Point, String> {
|
fn c2(&self) -> Result<Point, String> {
|
||||||
let c2_x = f32::from_be_bytes(self.data[12..16].try_into().map_err(stringify_slice_err)?);
|
let c2_x = f32::from_le_bytes(self.data[12..16].try_into().map_err(stringify_slice_err)?);
|
||||||
let c2_y = f32::from_be_bytes(self.data[16..20].try_into().map_err(stringify_slice_err)?);
|
let c2_y = f32::from_le_bytes(self.data[16..20].try_into().map_err(stringify_slice_err)?);
|
||||||
|
|
||||||
Ok((c2_x, c2_y))
|
Ok((c2_x, c2_y))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue