diff --git a/common/src/app/common/types/path/impl.cljc b/common/src/app/common/types/path/impl.cljc index b65f496e7..1845f446f 100644 --- a/common/src/app/common/types/path/impl.cljc +++ b/common/src/app/common/types/path/impl.cljc @@ -22,7 +22,7 @@ [app.common.types.path :as-alias path]) (:import #?(:cljs [goog.string StringBuffer] - :clj [java.nio ByteBuffer]))) + :clj [java.nio ByteBuffer ByteOrder]))) #?(:clj (set! *warn-on-reflection* true)) @@ -45,33 +45,29 @@ (defmacro read-short [target offset] (if (:ns &env) - `(.getInt16 ~target ~offset) - (let [target (with-meta target {:tag 'java.nio.ByteBuffer}) - offset (with-meta target {:tag 'int})] + `(.getInt16 ~target ~offset true) + (let [target (with-meta target {:tag 'java.nio.ByteBuffer})] `(.getShort ~target ~offset)))) (defmacro read-float [target offset] (if (:ns &env) - `(.getFloat32 ~target ~offset) - (let [target (with-meta target {:tag 'java.nio.ByteBuffer}) - offset (with-meta target {:tag 'int})] - `(.getFloat ~target ~offset)))) + `(.getFloat32 ~target ~offset true) + (let [target (with-meta target {:tag 'java.nio.ByteBuffer})] + `(double (.getFloat ~target ~offset))))) (defmacro write-float [target offset value] (if (:ns &env) - `(.setFloat32 ~target ~offset ~value) - (let [target (with-meta target {:tag 'java.nio.ByteBuffer}) - offset (with-meta target {:tag 'int})] + `(.setFloat32 ~target ~offset ~value true) + (let [target (with-meta target {:tag 'java.nio.ByteBuffer})] `(.putFloat ~target ~offset ~value)))) (defmacro write-short [target offset value] (if (:ns &env) - `(.setInt16 ~target ~offset ~value) - (let [target (with-meta target {:tag 'java.nio.ByteBuffer}) - offset (with-meta target {:tag 'int})] + `(.setInt16 ~target ~offset ~value true) + (let [target (with-meta target {:tag 'java.nio.ByteBuffer})] `(.putShort ~target ~offset ~value)))) (defmacro with-cache @@ -91,6 +87,28 @@ ~'result)))) `(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 "Apply a transformation to a segment located under specified offset" [buffer offset a b c d e f] @@ -302,21 +320,6 @@ [size i] (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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -628,17 +631,18 @@ #?(:clj (cond (instance? ByteBuffer buffer) - (let [size (.capacity ^ByteBuffer buffer) - count (long (/ size SEGMENT-BYTE-SIZE))] + (let [size (.capacity ^ByteBuffer buffer) + count (long (/ size SEGMENT-BYTE-SIZE)) + buffer (.order ^ByteBuffer buffer ByteOrder/LITTLE_ENDIAN)] (PathData. count buffer nil)) (bytes? buffer) - (let [size (alength ^bytes buffer) - count (long (/ size SEGMENT-BYTE-SIZE))] + (let [size (alength ^bytes buffer) + count (long (/ size SEGMENT-BYTE-SIZE)) + buffer (ByteBuffer/wrap buffer)] (PathData. count - (ByteBuffer/wrap buffer) + (.order buffer ByteOrder/LITTLE_ENDIAN) nil)) - :else (throw (java.lang.IllegalArgumentException. "invalid data provided"))) @@ -678,9 +682,9 @@ (assert (check-segments segments)) (let [total (count segments) - #?@(:cljs [buffer' (new js/ArrayBuffer (* total SEGMENT-BYTE-SIZE)) + #?@(:cljs [buffer' (allocate total) buffer (new js/DataView buffer')] - :clj [buffer (ByteBuffer/allocate (* total SEGMENT-BYTE-SIZE))])] + :clj [buffer (allocate total)])] (loop [index 0] (when (< index total) (let [segment (nth segments index) diff --git a/common/test/common_tests/types/path_data_test.cljc b/common/test/common_tests/types/path_data_test.cljc index 074216f49..b283dd9f5 100644 --- a/common/test/common_tests/types/path_data_test.cljc +++ b/common/test/common_tests/types/path_data_test.cljc @@ -69,10 +69,10 @@ {: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]) + [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 + 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 + 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 + 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 (t/deftest path-data-to-vector @@ -116,10 +116,11 @@ (t/deftest path-data-transit-roundtrip (let [pdata (path/content sample-content) result1 (trans/encode-str pdata) - expected (str "[\"~#penpot/path-data\",\"~bAAEAAAAAAAAAAAAAAAAAAAAAAA" - "BD8AAARFHAAAACAAAAAAAAAAAAAAAAAAAAAAAAQ9uAAERIgAAAAwAA" - "Q7gAAEQ4QABDmwAARCpAAEOEAABEHoAAAAQAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAA==\"]") + expected (str "[\"~#penpot/path-data\",\"~bAQAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAPBDAMBRRAIAAAAAAAAAAAAAAAAAAA" + "AAAAAAAIDbQwCASEQDAAAAAAC4QwBAOEQAAJtDAEAqR" + "AAAhEMAgB5EBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAA==\"]") result2 (trans/decode-str result1)] (t/is (= expected result1)) (t/is (= pdata result2)))) @@ -352,7 +353,6 @@ (t/is (= result5 expect2)) (t/is (= result6 expect3)))) - (defn get-handlers "Retrieve a map where for every point will retrieve a list of the handlers that are associated with that point. @@ -375,7 +375,6 @@ (t/deftest content-to-handlers (let [content (path/content sample-content-large) - result1 (get-handlers content) + result1 (get-handlers sample-content-large) result2 (path.segment/get-handlers content)] - (t/is (= result1 result2)))) diff --git a/frontend/playwright/data/workspace/get-file-copy-paste-fragment.json b/frontend/playwright/data/workspace/get-file-copy-paste-fragment.json index e16eba344..2cb2ea90a 100644 --- a/frontend/playwright/data/workspace/get-file-copy-paste-fragment.json +++ b/frontend/playwright/data/workspace/get-file-copy-paste-fragment.json @@ -448,7 +448,7 @@ }, "~:rotation": 0, "~:grow-type": "~:fixed", - "~:content": ["~#penpot/path-data","~bAAEAAAAAAAAAAAAAAAAAAAAAAABEjCAARAqAAAACAAAAAAAAAAAAAAAAAAAAAAAARJmgAEPlAAAAAwAARJmgAEPlAABEpQAAQ/YAAESi4ABEAYAAAAMAAESgwABECAAARJ1AAEQPAABEmGAARBIAAAADAABEk4AARBUAAESMIABECoAARIwgAEQKgAA="], + "~:content": ["~#penpot/path-data","~bAQAAAAAAAAAAAAAAAAAAAAAAAAAAIIxEAIAKRAIAAAAAAAAAAAAAAAAAAAAAAAAAAKCZRAAA5UMDAAAAAKCZRAAA5UMAAKVEAAD2QwDgokQAgAFEAwAAAADAoEQAAAhEAECdRAAAD0QAYJhEAAASRAMAAAAAgJNEAAAVRAAgjEQAgApEACCMRACACkQ="], "~:name": "Path", "~:width": null, "~:type": "~:path", diff --git a/render-wasm/src/shapes/paths.rs b/render-wasm/src/shapes/paths.rs index a09ec3c54..6ad5e5075 100644 --- a/render-wasm/src/shapes/paths.rs +++ b/render-wasm/src/shapes/paths.rs @@ -14,26 +14,26 @@ pub struct RawPathData { impl RawPathData { fn command(&self) -> Result { - 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) } fn xy(&self) -> Result { - let x = f32::from_be_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 x = f32::from_le_bytes(self.data[20..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)) } fn c1(&self) -> Result { - let c1_x = f32::from_be_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_x = f32::from_le_bytes(self.data[4..8].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)) } fn c2(&self) -> Result { - let c2_x = f32::from_be_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_x = f32::from_le_bytes(self.data[12..16].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)) }