mirror of
https://github.com/penpot/penpot.git
synced 2025-12-11 22:14:05 +01:00
Merge pull request #7385 from penpot/elenatorro-improve-image-load-performance
🔧 Improve image parsing performance
This commit is contained in:
@@ -170,11 +170,10 @@
|
||||
[string]
|
||||
(+ (count string) 1))
|
||||
|
||||
|
||||
(defn- fetch-image
|
||||
[shape-id image-id]
|
||||
(let [buffer-shape-id (uuid/get-u32 shape-id)
|
||||
buffer-image-id (uuid/get-u32 image-id)
|
||||
url (cf/resolve-file-media {:id image-id})]
|
||||
(let [url (cf/resolve-file-media {:id image-id})]
|
||||
{:key url
|
||||
:callback #(->> (http/send! {:method :get
|
||||
:uri url
|
||||
@@ -182,23 +181,32 @@
|
||||
(rx/map :body)
|
||||
(rx/mapcat wapi/read-file-as-array-buffer)
|
||||
(rx/map (fn [image]
|
||||
;; FIXME use bigger heap ptr size if it
|
||||
;; is possible (if image size modulo
|
||||
;; permits it)
|
||||
(let [size (.-byteLength image)
|
||||
offset (mem/alloc size)
|
||||
heap (mem/get-heap-u8)
|
||||
data (js/Uint8Array. image)]
|
||||
(.set heap data offset)
|
||||
(h/call wasm/internal-module "_store_image"
|
||||
(aget buffer-shape-id 0)
|
||||
(aget buffer-shape-id 1)
|
||||
(aget buffer-shape-id 2)
|
||||
(aget buffer-shape-id 3)
|
||||
(aget buffer-image-id 0)
|
||||
(aget buffer-image-id 1)
|
||||
(aget buffer-image-id 2)
|
||||
(aget buffer-image-id 3))
|
||||
padded-size (if (zero? (mod size 4)) size (+ size (- 4 (mod size 4))))
|
||||
total-bytes (+ 32 padded-size) ; UUID size + padded size
|
||||
offset (mem/alloc->offset-32 total-bytes)
|
||||
heap32 (mem/get-heap-u32)
|
||||
data (js/Uint8Array. image)
|
||||
padded (js/Uint8Array. padded-size)]
|
||||
|
||||
;; 1. Set shape id
|
||||
(mem.h32/write-uuid offset heap32 shape-id)
|
||||
|
||||
;; 2. Set image id
|
||||
(mem.h32/write-uuid (+ offset 4) heap32 image-id)
|
||||
|
||||
;; 3. Adjust padding on image data
|
||||
(.set padded data)
|
||||
(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))))}))
|
||||
|
||||
(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]
|
||||
pub extern "C" fn is_image_cached(a: u32, b: u32, c: u32, d: u32) -> bool {
|
||||
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};
|
||||
|
||||
const FLAG_KEEP_ASPECT_RATIO: u8 = 1 << 0;
|
||||
const IMAGE_IDS_SIZE: usize = 32;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user