Merge pull request #7053 from penpot/ladybenko-11678-compact-keep-ratio-flag

 Compact fill serialization (opacity + flags)
This commit is contained in:
Alejandro Alonso 2025-08-05 13:29:49 +02:00 committed by GitHub
commit 7efc297cd9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 45 additions and 27 deletions

View File

@ -21,6 +21,13 @@
(let [target (with-meta target {:tag 'java.nio.ByteBuffer})] (let [target (with-meta target {:tag 'java.nio.ByteBuffer})]
`(long (.get ~target ~offset))))) `(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 (defmacro read-bool
[target offset] [target offset]
(if (:ns &env) (if (:ns &env)

View File

@ -86,6 +86,7 @@
start-y (:start-y gradient) start-y (:start-y gradient)
end-x (:end-x gradient) end-x (:end-x gradient)
end-y (:end-y gradient) end-y (:end-y gradient)
alpha (mth/floor (* opacity 0xff))
width (:width gradient 0) width (:width gradient 0)
stops (into [] xf:take-stops (:stops gradient)) stops (into [] xf:take-stops (:stops gradient))
type (if (= (:type gradient) :linear) type (if (= (:type gradient) :linear)
@ -97,7 +98,7 @@
(buf/write-float buffer (+ offset 8) start-y) (buf/write-float buffer (+ offset 8) start-y)
(buf/write-float buffer (+ offset 12) end-x) (buf/write-float buffer (+ offset 12) end-x)
(buf/write-float buffer (+ offset 16) end-y) (buf/write-float buffer (+ offset 16) end-y)
(buf/write-float buffer (+ offset 20) opacity) (buf/write-byte buffer (+ offset 20) alpha)
(buf/write-float buffer (+ offset 24) width) (buf/write-float buffer (+ offset 24) width)
(buf/write-byte buffer (+ offset 28) (count stops)) (buf/write-byte buffer (+ offset 28) (count stops))
@ -121,13 +122,16 @@
(let [image-id (get image :id) (let [image-id (get image :id)
image-width (get image :width) image-width (get image :width)
image-height (get image :height) image-height (get image :height)
keep-aspect-ratio (get image :keep-aspect-ratio false)] alpha (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-byte buffer (+ offset 0) 0x03)
(buf/write-uuid buffer (+ offset 4) image-id) (buf/write-uuid buffer (+ offset 4) image-id)
(buf/write-float buffer (+ offset 20) opacity) (buf/write-byte buffer (+ offset 20) alpha)
(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 24) image-width)
(buf/write-int buffer (+ offset 28) image-height) (buf/write-int buffer (+ offset 28) image-height)
(buf/write-bool buffer (+ offset 32) keep-aspect-ratio)
(+ offset FILL-BYTE-SIZE))) (+ offset FILL-BYTE-SIZE)))
(defn- write-metadata (defn- write-metadata
@ -180,9 +184,10 @@
start-y (buf/read-float dbuffer (+ doffset 8)) start-y (buf/read-float dbuffer (+ doffset 8))
end-x (buf/read-float dbuffer (+ doffset 12)) end-x (buf/read-float dbuffer (+ doffset 12))
end-y (buf/read-float dbuffer (+ doffset 16)) end-y (buf/read-float dbuffer (+ doffset 16))
alpha (buf/read-float dbuffer (+ doffset 20)) alpha (buf/read-unsigned-byte dbuffer (+ doffset 20))
width (buf/read-float dbuffer (+ doffset 24)) width (buf/read-float dbuffer (+ doffset 24))
stops (buf/read-byte dbuffer (+ doffset 28)) stops (buf/read-byte dbuffer (+ doffset 28))
opacity (mth/precision (/ alpha 0xff) 2)
type (if (= type 1) type (if (= type 1)
:linear :linear
:radial) :radial)
@ -193,7 +198,7 @@
(conj result (read-stop dbuffer (+ doffset 32 (* GRADIENT-STOP-SIZE index))))) (conj result (read-stop dbuffer (+ doffset 32 (* GRADIENT-STOP-SIZE index)))))
result))] result))]
{:fill-opacity alpha {:fill-opacity opacity
:fill-color-gradient {:start-x start-x :fill-color-gradient {:start-x start-x
:start-y start-y :start-y start-y
:end-x end-x :end-x end-x
@ -202,20 +207,22 @@
:stops stops :stops stops
:type type}}) :type type}})
3 3 ;; image fill
(let [ratio (buf/read-bool dbuffer (+ doffset 32)) (let [id (buf/read-uuid dbuffer (+ doffset 4))
id (buf/read-uuid dbuffer (+ doffset 4)) alpha (buf/read-unsigned-byte dbuffer (+ doffset 20))
alpha (buf/read-float dbuffer (+ doffset 20)) opacity (mth/precision (/ alpha 0xff) 2)
width (buf/read-int dbuffer (+ doffset 24)) flags (buf/read-unsigned-byte dbuffer (+ doffset 21))
height (buf/read-int dbuffer (+ doffset 28)) ratio (boolean (bit-and flags 0x01))
mtype (buf/read-short mbuffer (+ moffset 2)) width (buf/read-int dbuffer (+ doffset 24))
mtype (case mtype height (buf/read-int dbuffer (+ doffset 28))
0x01 "image/jpeg" mtype (buf/read-short mbuffer (+ moffset 2))
0x02 "image/png" mtype (case mtype
0x03 "image/gif" 0x01 "image/jpeg"
0x04 "image/webp" 0x02 "image/png"
0x05 "image/svg+xml")] 0x03 "image/gif"
{:fill-opacity alpha 0x04 "image/webp"
0x05 "image/svg+xml")]
{:fill-opacity opacity
:fill-image {:id id :fill-image {:id id
:width width :width width
:height height :height height

View File

@ -10,7 +10,8 @@ pub struct RawGradientData {
start_y: f32, start_y: f32,
end_x: f32, end_x: f32,
end_y: f32, end_y: f32,
opacity: f32, opacity: u8,
// 24-bit padding here, reserved for future use
width: f32, width: f32,
stop_count: u8, stop_count: u8,
stops: [RawStopData; MAX_GRADIENT_STOPS], stops: [RawStopData; MAX_GRADIENT_STOPS],
@ -55,7 +56,7 @@ impl From<RawGradientData> for Gradient {
Gradient::new( Gradient::new(
raw_gradient.start(), raw_gradient.start(),
raw_gradient.end(), raw_gradient.end(),
(raw_gradient.opacity * 255.) as u8, raw_gradient.opacity,
raw_gradient.width, raw_gradient.width,
&stops, &stops,
) )

View File

@ -1,5 +1,7 @@
use crate::{shapes::ImageFill, utils::uuid_from_u32_quartet}; use crate::{shapes::ImageFill, utils::uuid_from_u32_quartet};
const FLAG_KEEP_ASPECT_RATIO: u8 = 1 << 0;
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)] #[repr(C)]
#[repr(align(4))] #[repr(align(4))]
@ -8,23 +10,24 @@ pub struct RawImageFillData {
b: u32, b: u32,
c: u32, c: u32,
d: u32, d: u32,
opacity: f32, opacity: u8,
flags: u8,
// 16-bit padding here, reserved for future use
width: i32, width: i32,
height: i32, height: i32,
keep_aspect_ratio: i32,
} }
impl From<RawImageFillData> for ImageFill { impl From<RawImageFillData> for ImageFill {
fn from(value: RawImageFillData) -> Self { fn from(value: RawImageFillData) -> Self {
let id = uuid_from_u32_quartet(value.a, value.b, value.c, value.d); 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( Self::new(
id, id,
opacity, value.opacity,
value.width, value.width,
value.height, value.height,
value.keep_aspect_ratio != 0, keep_aspect_ratio,
) )
} }
} }