diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index f0e6d2ca21..8e033aa3d1 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -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)) + (let [size (.-byteLength image) + 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 diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 12ceffc180..06ad75eb3d 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -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, { diff --git a/render-wasm/src/wasm/fills/image.rs b/render-wasm/src/wasm/fills/image.rs index 15ab5e037f..b7075899ff 100644 --- a/render-wasm/src/wasm/fills/image.rs +++ b/render-wasm/src/wasm/fills/image.rs @@ -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 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> for ShapeImageIds { + type Error = &'static str; + + fn try_from(value: Vec) -> Result { + 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(); +}