Display images in the SVG viewport renderer via canvases instead of base64 PNGs (#2903)

* add: move images as rendered canvases to node_graph_executor

* add: added the frontend message

* fix: bytemuck stuff

* fix: canvas element breaking

* fix: width issues

* fix: remove the old message

* npm: run lint-fix

* fix

* works finally

* fix transforms

* Fix self closing tag

* fix: reuse id

* fix: have it working with repeat instance

* cargo: fmt

* fix

* Avoid "canvas" prefix to IDs

* fix

* fix: vello issue from 6111440

* fix: gpu stuff

* fix: vello bbox

* Code review

---------

Co-authored-by: hypercube <0hypercube@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
mTvare
2025-07-25 05:44:38 +05:30
committed by GitHub
parent 45bd031a36
commit 72f1047a27
17 changed files with 280 additions and 117 deletions

View File

@@ -46,6 +46,7 @@ num_enum = { workspace = true }
usvg = { workspace = true }
once_cell = { workspace = true }
web-sys = { workspace = true }
bytemuck = { workspace = true }
# Required dependencies
spin = "0.9.8"

View File

@@ -8,6 +8,7 @@ use crate::messages::portfolio::document::utility_types::wires::{WirePath, WireP
use crate::messages::prelude::*;
use crate::messages::tool::utility_types::HintData;
use graph_craft::document::NodeId;
use graphene_std::raster::Image;
use graphene_std::raster::color::Color;
use graphene_std::text::Font;
@@ -179,6 +180,9 @@ pub enum FrontendMessage {
UpdateDocumentArtwork {
svg: String,
},
UpdateImageData {
image_data: Vec<(u64, Image<Color>)>,
},
UpdateDocumentBarLayout {
#[serde(rename = "layoutTarget")]
layout_target: LayoutTarget,

View File

@@ -213,7 +213,7 @@ impl NodeGraphExecutor {
fn export(&self, node_graph_output: TaggedValue, export_config: ExportConfig, responses: &mut VecDeque<Message>) -> Result<(), String> {
let TaggedValue::RenderOutput(RenderOutput {
data: graphene_std::wasm_application_io::RenderOutputType::Svg(svg),
data: graphene_std::wasm_application_io::RenderOutputType::Svg { svg, .. },
..
}) = node_graph_output
else {
@@ -350,15 +350,16 @@ impl NodeGraphExecutor {
match node_graph_output {
TaggedValue::RenderOutput(render_output) => {
match render_output.data {
graphene_std::wasm_application_io::RenderOutputType::Svg(svg) => {
graphene_std::wasm_application_io::RenderOutputType::Svg { svg, image_data } => {
// Send to frontend
responses.add(FrontendMessage::UpdateImageData { image_data });
responses.add(FrontendMessage::UpdateDocumentArtwork { svg });
}
graphene_std::wasm_application_io::RenderOutputType::CanvasFrame(frame) => {
let matrix = format_transform_matrix(frame.transform);
let transform = if matrix.is_empty() { String::new() } else { format!(" transform=\"{}\"", matrix) };
let transform = if matrix.is_empty() { String::new() } else { format!(" transform=\"{matrix}\"") };
let svg = format!(
r#"<svg><foreignObject width="{}" height="{}"{transform}><div data-canvas-placeholder="canvas{}"></div></foreignObject></svg>"#,
r#"<svg><foreignObject width="{}" height="{}"{transform}><div data-canvas-placeholder="{}"></div></foreignObject></svg>"#,
frame.resolution.x, frame.resolution.y, frame.surface_id.0
);
responses.add(FrontendMessage::UpdateDocumentArtwork { svg });