diff --git a/common/src/app/common/buffer.cljc b/common/src/app/common/buffer.cljc index 74514a3951..69413db7db 100644 --- a/common/src/app/common/buffer.cljc +++ b/common/src/app/common/buffer.cljc @@ -21,6 +21,13 @@ (let [target (with-meta target {:tag 'java.nio.ByteBuffer})] `(long (.get ~target ~offset))))) +(defmacro read-unsigned-byte + [target offset] + (if (:ns &env) + `(.getUint8 ~target ~offset true) + (let [target (with-meta target {:tag 'java.nio.ByteBuffer})] + `(bit-and (long (.get ~target ~offset)) 0xff)))) + (defmacro read-bool [target offset] (if (:ns &env) diff --git a/common/src/app/common/types/fills/impl.cljc b/common/src/app/common/types/fills/impl.cljc index fb41340a45..73cdb2eec0 100644 --- a/common/src/app/common/types/fills/impl.cljc +++ b/common/src/app/common/types/fills/impl.cljc @@ -121,13 +121,16 @@ (let [image-id (get image :id) image-width (get image :width) image-height (get image :height) - keep-aspect-ratio (get image :keep-aspect-ratio false)] + opacity (mth/floor (* opacity 0xff)) + keep-aspect-ratio (if (get image :keep-aspect-ratio false) 0x01 0x00) + flags (bit-or keep-aspect-ratio 0x00)] (buf/write-byte buffer (+ offset 0) 0x03) (buf/write-uuid buffer (+ offset 4) image-id) - (buf/write-float buffer (+ offset 20) opacity) + (buf/write-byte buffer (+ offset 20) opacity) + (buf/write-byte buffer (+ offset 21) flags) + (buf/write-short buffer (+ offset 22) 0) ;; 2-byte padding (reserved for future use) (buf/write-int buffer (+ offset 24) image-width) (buf/write-int buffer (+ offset 28) image-height) - (buf/write-bool buffer (+ offset 32) keep-aspect-ratio) (+ offset FILL-BYTE-SIZE))) (defn- write-metadata @@ -202,10 +205,12 @@ :stops stops :type type}}) - 3 - (let [ratio (buf/read-bool dbuffer (+ doffset 32)) - id (buf/read-uuid dbuffer (+ doffset 4)) - alpha (buf/read-float dbuffer (+ doffset 20)) + 3 ;; image fill + (let [id (buf/read-uuid dbuffer (+ doffset 4)) + alpha (buf/read-unsigned-byte dbuffer (+ doffset 20)) + opacity (mth/precision (/ alpha 0xff) 2) + flags (buf/read-unsigned-byte dbuffer (+ doffset 21)) + ratio (boolean (bit-and flags 0x01)) width (buf/read-int dbuffer (+ doffset 24)) height (buf/read-int dbuffer (+ doffset 28)) mtype (buf/read-short mbuffer (+ moffset 2)) @@ -215,7 +220,7 @@ 0x03 "image/gif" 0x04 "image/webp" 0x05 "image/svg+xml")] - {:fill-opacity alpha + {:fill-opacity opacity :fill-image {:id id :width width :height height diff --git a/render-wasm/src/wasm/fills/image.rs b/render-wasm/src/wasm/fills/image.rs index 07ae137d37..ab059d3ecd 100644 --- a/render-wasm/src/wasm/fills/image.rs +++ b/render-wasm/src/wasm/fills/image.rs @@ -1,5 +1,7 @@ use crate::{shapes::ImageFill, utils::uuid_from_u32_quartet}; +const FLAG_KEEP_ASPECT_RATIO: u8 = 1 << 0; + #[derive(Debug, Clone, Copy, PartialEq)] #[repr(C)] #[repr(align(4))] @@ -8,23 +10,24 @@ pub struct RawImageFillData { b: u32, c: u32, d: u32, - opacity: f32, + opacity: u8, + flags: u8, + _padding: u16, // reserved for future use width: i32, height: i32, - keep_aspect_ratio: i32, } impl From for ImageFill { fn from(value: RawImageFillData) -> Self { let id = uuid_from_u32_quartet(value.a, value.b, value.c, value.d); - let opacity = (value.opacity * 255.).floor() as u8; + let keep_aspect_ratio = value.flags & FLAG_KEEP_ASPECT_RATIO != 0; Self::new( id, - opacity, + value.opacity, value.width, value.height, - value.keep_aspect_ratio != 0, + keep_aspect_ratio, ) } }