mirror of
https://github.com/penpot/penpot.git
synced 2026-09-10 22:19:19 +00:00
🔧 Improve image parsing performance
This commit is contained in:
parent
015bd9e453
commit
bf6cdf729d
@ -170,11 +170,10 @@
|
|||||||
[string]
|
[string]
|
||||||
(+ (count string) 1))
|
(+ (count string) 1))
|
||||||
|
|
||||||
|
|
||||||
(defn- fetch-image
|
(defn- fetch-image
|
||||||
[shape-id image-id]
|
[shape-id image-id]
|
||||||
(let [buffer-shape-id (uuid/get-u32 shape-id)
|
(let [url (cf/resolve-file-media {:id image-id})]
|
||||||
buffer-image-id (uuid/get-u32 image-id)
|
|
||||||
url (cf/resolve-file-media {:id image-id})]
|
|
||||||
{:key url
|
{:key url
|
||||||
:callback #(->> (http/send! {:method :get
|
:callback #(->> (http/send! {:method :get
|
||||||
:uri url
|
:uri url
|
||||||
@ -182,23 +181,32 @@
|
|||||||
(rx/map :body)
|
(rx/map :body)
|
||||||
(rx/mapcat wapi/read-file-as-array-buffer)
|
(rx/mapcat wapi/read-file-as-array-buffer)
|
||||||
(rx/map (fn [image]
|
(rx/map (fn [image]
|
||||||
;; FIXME use bigger heap ptr size if it
|
(let [size (.-byteLength image)
|
||||||
;; is possible (if image size modulo
|
padded-size (if (zero? (mod size 4)) size (+ size (- 4 (mod size 4))))
|
||||||
;; permits it)
|
total-bytes (+ 32 padded-size) ; UUID size + padded size
|
||||||
(let [size (.-byteLength image)
|
offset (mem/alloc->offset-32 total-bytes)
|
||||||
offset (mem/alloc size)
|
heap32 (mem/get-heap-u32)
|
||||||
heap (mem/get-heap-u8)
|
data (js/Uint8Array. image)
|
||||||
data (js/Uint8Array. image)]
|
padded (js/Uint8Array. padded-size)]
|
||||||
(.set heap data offset)
|
|
||||||
(h/call wasm/internal-module "_store_image"
|
;; 1. Set shape id
|
||||||
(aget buffer-shape-id 0)
|
(mem.h32/write-uuid offset heap32 shape-id)
|
||||||
(aget buffer-shape-id 1)
|
|
||||||
(aget buffer-shape-id 2)
|
;; 2. Set image id
|
||||||
(aget buffer-shape-id 3)
|
(mem.h32/write-uuid (+ offset 4) heap32 image-id)
|
||||||
(aget buffer-image-id 0)
|
|
||||||
(aget buffer-image-id 1)
|
;; 3. Adjust padding on image data
|
||||||
(aget buffer-image-id 2)
|
(.set padded data)
|
||||||
(aget buffer-image-id 3))
|
(when (< size padded-size)
|
||||||
|
(dotimes [i (- padded-size size)]
|
||||||
|
(aset padded (+ size i) 0)))
|
||||||
|
|
||||||
|
;; 4. Set image data
|
||||||
|
(let [u32view (js/Uint32Array. (.-buffer padded))
|
||||||
|
image-u32-offset (+ offset 8)]
|
||||||
|
(.set heap32 u32view image-u32-offset))
|
||||||
|
|
||||||
|
(h/call wasm/internal-module "_store_image")
|
||||||
true))))}))
|
true))))}))
|
||||||
|
|
||||||
(defn- get-fill-images
|
(defn- get-fill-images
|
||||||
|
|||||||
@ -300,34 +300,6 @@ pub extern "C" fn set_children() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn store_image(
|
|
||||||
a1: u32,
|
|
||||||
b1: u32,
|
|
||||||
c1: u32,
|
|
||||||
d1: u32,
|
|
||||||
a2: u32,
|
|
||||||
b2: u32,
|
|
||||||
c2: u32,
|
|
||||||
d2: u32,
|
|
||||||
) {
|
|
||||||
with_state_mut!(state, {
|
|
||||||
let image_id = uuid_from_u32_quartet(a2, b2, c2, d2);
|
|
||||||
let image_bytes = mem::bytes();
|
|
||||||
|
|
||||||
if let Err(msg) = state.render_state_mut().add_image(image_id, &image_bytes) {
|
|
||||||
eprintln!("{}", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
mem::free_bytes();
|
|
||||||
});
|
|
||||||
|
|
||||||
with_state_mut!(state, {
|
|
||||||
let shape_id = uuid_from_u32_quartet(a1, b1, c1, d1);
|
|
||||||
state.update_tile_for_shape(shape_id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn is_image_cached(a: u32, b: u32, c: u32, d: u32) -> bool {
|
pub extern "C" fn is_image_cached(a: u32, b: u32, c: u32, d: u32) -> bool {
|
||||||
with_state_mut!(state, {
|
with_state_mut!(state, {
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
|
use crate::mem;
|
||||||
|
use crate::mem::SerializableResult;
|
||||||
|
use crate::uuid::Uuid;
|
||||||
|
use crate::with_state_mut;
|
||||||
|
use crate::STATE;
|
||||||
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;
|
const FLAG_KEEP_ASPECT_RATIO: u8 = 1 << 0;
|
||||||
|
const IMAGE_IDS_SIZE: usize = 32;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -31,3 +37,50 @@ impl From<RawImageFillData> for ImageFill {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ShapeImageIds {
|
||||||
|
shape_id: Uuid,
|
||||||
|
image_id: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<[u8; IMAGE_IDS_SIZE]> for ShapeImageIds {
|
||||||
|
fn from(bytes: [u8; IMAGE_IDS_SIZE]) -> Self {
|
||||||
|
let shape_id = Uuid::from_bytes(bytes[0..16].try_into().unwrap());
|
||||||
|
let image_id = Uuid::from_bytes(bytes[16..32].try_into().unwrap());
|
||||||
|
ShapeImageIds { shape_id, image_id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Vec<u8>> for ShapeImageIds {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
||||||
|
let mut arr = [0u8; IMAGE_IDS_SIZE];
|
||||||
|
arr.copy_from_slice(&value);
|
||||||
|
Ok(ShapeImageIds::from(arr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn store_image() {
|
||||||
|
let bytes = mem::bytes();
|
||||||
|
let ids = ShapeImageIds::try_from(bytes[0..IMAGE_IDS_SIZE].to_vec()).unwrap();
|
||||||
|
let image_bytes = &bytes[IMAGE_IDS_SIZE..];
|
||||||
|
|
||||||
|
with_state_mut!(state, {
|
||||||
|
if let Err(msg) = state
|
||||||
|
.render_state_mut()
|
||||||
|
.add_image(ids.image_id, image_bytes)
|
||||||
|
{
|
||||||
|
eprintln!("{}", msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
with_state_mut!(state, {
|
||||||
|
state.update_tile_for_shape(ids.shape_id);
|
||||||
|
});
|
||||||
|
|
||||||
|
mem::free_bytes();
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user