Skip to content

Commit 796d3a6

Browse files
committed
fix
1 parent 2c7f427 commit 796d3a6

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

frontend/wasm/src/editor_api.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@ use editor::messages::prelude::*;
1717
use editor::messages::tool::tool_messages::tool_prelude::WidgetId;
1818
use graph_craft::document::NodeId;
1919
use graphene_std::raster::color::Color;
20+
use graphene_std::raster::{Image, TransformImage};
21+
use js_sys::{Object, Reflect};
2022
use serde::Serialize;
2123
use serde_wasm_bindgen::{self, from_value};
2224
use std::cell::RefCell;
2325
use std::sync::atomic::Ordering;
2426
use std::time::Duration;
27+
use wasm_bindgen::JsCast;
2528
use wasm_bindgen::prelude::*;
29+
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, ImageData, window};
2630

2731
/// Set the random seed used by the editor by calling this from JS upon initialization.
2832
/// This is necessary because WASM doesn't have a random number generator.
@@ -37,6 +41,73 @@ pub fn wasm_memory() -> JsValue {
3741
wasm_bindgen::memory()
3842
}
3943

44+
fn render_image_data_to_canvases(image_data: &[(u64, Image<Color>, TransformImage)]) {
45+
let window = match window() {
46+
Some(window) => window,
47+
None => {
48+
error!("Cannot render canvas: window object not found");
49+
return;
50+
}
51+
};
52+
let document = window.document().expect("window should have a document");
53+
let window_obj = Object::from(window);
54+
let image_canvases_key = JsValue::from_str("imageCanvases");
55+
56+
let canvases_obj = match Reflect::get(&window_obj, &image_canvases_key) {
57+
Ok(obj) if !obj.is_undefined() && !obj.is_null() => obj,
58+
_ => {
59+
let new_obj = Object::new();
60+
if Reflect::set(&window_obj, &image_canvases_key, &new_obj).is_err() {
61+
error!("Failed to create and set imageCanvases object on window");
62+
return;
63+
}
64+
new_obj.into()
65+
}
66+
};
67+
let canvases_obj = Object::from(canvases_obj);
68+
69+
for (placeholder_id, image, _) in image_data.iter() {
70+
if image.width == 0 || image.height == 0 {
71+
continue;
72+
}
73+
74+
let canvas: HtmlCanvasElement = document
75+
.create_element("canvas")
76+
.expect("Failed to create canvas element")
77+
.dyn_into::<HtmlCanvasElement>()
78+
.expect("Failed to cast element to HtmlCanvasElement");
79+
80+
canvas.set_width(1);
81+
canvas.set_height(1);
82+
let context: CanvasRenderingContext2d = canvas
83+
.get_context("2d")
84+
.expect("Failed to get 2d context")
85+
.expect("2d context was not found")
86+
.dyn_into::<CanvasRenderingContext2d>()
87+
.expect("Failed to cast context to CanvasRenderingContext2d");
88+
let u8_data: Vec<u8> = image.data.iter().flat_map(|color| color.to_rgba8_srgb()).collect();
89+
let clamped_u8_data = wasm_bindgen::Clamped(&u8_data[..]);
90+
match ImageData::new_with_u8_clamped_array_and_sh(clamped_u8_data, image.width, image.height) {
91+
Ok(image_data_obj) => {
92+
if context.put_image_data(&image_data_obj, 0.0, 0.0).is_err() {
93+
error!("Failed to put image data on canvas for id: {}", placeholder_id);
94+
}
95+
}
96+
Err(e) => {
97+
error!("Failed to create ImageData for id: {}: {:?}", placeholder_id, e);
98+
}
99+
}
100+
101+
let canvas_name = format!("canvas{}", placeholder_id);
102+
let js_key = JsValue::from_str(&canvas_name);
103+
let js_value = JsValue::from(canvas);
104+
105+
if Reflect::set(&canvases_obj, &js_key, &js_value).is_err() {
106+
error!("Failed to set canvas '{}' on imageCanvases object", canvas_name);
107+
}
108+
}
109+
}
110+
40111
// ============================================================================
41112

42113
/// This struct is, via wasm-bindgen, used by JS to interact with the editor backend. It does this by calling functions, which are `impl`ed
@@ -88,6 +159,11 @@ impl EditorHandle {
88159

89160
// Sends a FrontendMessage to JavaScript
90161
fn send_frontend_message_to_js(&self, mut message: FrontendMessage) {
162+
if let FrontendMessage::UpdateImageData { ref image_data } = message {
163+
render_image_data_to_canvases(image_data.as_slice());
164+
return;
165+
}
166+
91167
if let FrontendMessage::UpdateDocumentLayerStructure { data_buffer } = message {
92168
message = FrontendMessage::UpdateDocumentLayerStructureJs { data_buffer: data_buffer.into() };
93169
}

0 commit comments

Comments
 (0)