mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Render artwork at correct resolution when using vello on wasm (#3416)
* Work on fixing rendering for wasm+vello * Render vello canvas in wasm at the correct resolution * Cleanup unused surface rendering code * Remove vector to raster conversion * Remove desktop changes * Revert window.rs changes * Don't round logical coordinates * Fix desktop compilation + don't round logical coordinates for svg rendering * Further cleanup * Compute logical size from acutal physical sizes
This commit is contained in:
@@ -5,7 +5,7 @@ use core_types::{Color, Context, Ctx, ExtractFootprint, OwnedContextImpl, WasmNo
|
||||
use graph_craft::document::value::RenderOutput;
|
||||
pub use graph_craft::document::value::RenderOutputType;
|
||||
pub use graph_craft::wasm_application_io::*;
|
||||
use graphene_application_io::{ApplicationIo, ExportFormat, ImageTexture, RenderConfig, SurfaceFrame};
|
||||
use graphene_application_io::{ApplicationIo, ExportFormat, ImageTexture, RenderConfig};
|
||||
use graphic_types::Artboard;
|
||||
use graphic_types::Graphic;
|
||||
use graphic_types::Vector;
|
||||
@@ -120,12 +120,7 @@ async fn create_context<'a: 'n>(
|
||||
}
|
||||
|
||||
#[node_macro::node(category(""))]
|
||||
async fn render<'a: 'n>(
|
||||
ctx: impl Ctx + ExtractFootprint + ExtractVarArgs,
|
||||
editor_api: &'a WasmEditorApi,
|
||||
data: RenderIntermediate,
|
||||
_surface_handle: impl Node<Context<'static>, Output = Option<wgpu_executor::WgpuSurface>>,
|
||||
) -> RenderOutput {
|
||||
async fn render<'a: 'n>(ctx: impl Ctx + ExtractFootprint + ExtractVarArgs, editor_api: &'a WasmEditorApi, data: RenderIntermediate) -> RenderOutput {
|
||||
let footprint = ctx.footprint();
|
||||
let render_params = ctx
|
||||
.vararg(0)
|
||||
@@ -136,6 +131,10 @@ async fn render<'a: 'n>(
|
||||
render_params.footprint = *footprint;
|
||||
let render_params = &render_params;
|
||||
|
||||
let scale = render_params.scale;
|
||||
let physical_resolution = render_params.footprint.resolution;
|
||||
let logical_resolution = render_params.footprint.resolution.as_dvec2() / scale;
|
||||
|
||||
let RenderIntermediate { ty, mut metadata, contains_artboard } = data;
|
||||
metadata.apply_transform(footprint.transform);
|
||||
|
||||
@@ -146,8 +145,8 @@ async fn render<'a: 'n>(
|
||||
rendering.leaf_tag("rect", |attributes| {
|
||||
attributes.push("x", "0");
|
||||
attributes.push("y", "0");
|
||||
attributes.push("width", footprint.resolution.x.to_string());
|
||||
attributes.push("height", footprint.resolution.y.to_string());
|
||||
attributes.push("width", logical_resolution.x.to_string());
|
||||
attributes.push("height", logical_resolution.y.to_string());
|
||||
let matrix = format_transform_matrix(footprint.transform.inverse());
|
||||
if !matrix.is_empty() {
|
||||
attributes.push("transform", matrix);
|
||||
@@ -159,7 +158,7 @@ async fn render<'a: 'n>(
|
||||
rendering.image_data = svg_data.1.clone();
|
||||
rendering.svg_defs = svg_data.2.clone();
|
||||
|
||||
rendering.wrap_with_transform(footprint.transform, Some(footprint.resolution.as_dvec2()));
|
||||
rendering.wrap_with_transform(footprint.transform, Some(logical_resolution));
|
||||
RenderOutputType::Svg {
|
||||
svg: rendering.svg.to_svg_string(),
|
||||
image_data: rendering.image_data,
|
||||
@@ -171,15 +170,6 @@ async fn render<'a: 'n>(
|
||||
};
|
||||
let (child, context) = Arc::as_ref(vello_data);
|
||||
|
||||
let surface_handle = if cfg!(all(feature = "vello", target_family = "wasm")) {
|
||||
_surface_handle.eval(None).await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// When rendering to a surface, we do not want to apply the scale
|
||||
let scale = if surface_handle.is_none() { render_params.scale } else { 1. };
|
||||
|
||||
let scale_transform = glam::DAffine2::from_scale(glam::DVec2::splat(scale));
|
||||
let footprint_transform = scale_transform * footprint.transform;
|
||||
let footprint_transform_vello = vello::kurbo::Affine::new(footprint_transform.to_cols_array());
|
||||
@@ -187,11 +177,9 @@ async fn render<'a: 'n>(
|
||||
let mut scene = vello::Scene::new();
|
||||
scene.append(child, Some(footprint_transform_vello));
|
||||
|
||||
let resolution = (footprint.resolution.as_dvec2() * scale).as_uvec2();
|
||||
|
||||
// We now replace all transforms which are supposed to be infinite with a transform which covers the entire viewport
|
||||
// See <https://xi.zulipchat.com/#narrow/channel/197075-vello/topic/Full.20screen.20color.2Fgradients/near/538435044> for more detail
|
||||
let scaled_infinite_transform = vello::kurbo::Affine::scale_non_uniform(resolution.x as f64, resolution.y as f64);
|
||||
let scaled_infinite_transform = vello::kurbo::Affine::scale_non_uniform(physical_resolution.x as f64, physical_resolution.y as f64);
|
||||
let encoding = scene.encoding_mut();
|
||||
for transform in encoding.transforms.iter_mut() {
|
||||
if transform.matrix[0] == f32::INFINITY {
|
||||
@@ -204,25 +192,12 @@ async fn render<'a: 'n>(
|
||||
background = Color::WHITE;
|
||||
}
|
||||
|
||||
if let Some(surface_handle) = surface_handle {
|
||||
exec.render_vello_scene(&scene, &surface_handle, resolution, context, background)
|
||||
.await
|
||||
.expect("Failed to render Vello scene");
|
||||
let texture = exec
|
||||
.render_vello_scene_to_texture(&scene, physical_resolution, context, background)
|
||||
.await
|
||||
.expect("Failed to render Vello scene");
|
||||
|
||||
let frame = SurfaceFrame {
|
||||
surface_id: surface_handle.window_id,
|
||||
// TODO: Find a cleaner way to get the unscaled resolution here.
|
||||
// This is done because the surface frame (canvas) is in logical pixels, not physical pixels.
|
||||
resolution,
|
||||
transform: glam::DAffine2::IDENTITY,
|
||||
};
|
||||
|
||||
RenderOutputType::CanvasFrame(frame)
|
||||
} else {
|
||||
let texture = exec.render_vello_scene_to_texture(&scene, resolution, context, background).await.expect("Failed to render Vello scene");
|
||||
|
||||
RenderOutputType::Texture(ImageTexture { texture })
|
||||
}
|
||||
RenderOutputType::Texture(ImageTexture { texture })
|
||||
}
|
||||
_ => unreachable!("Render node did not receive its requested data type"),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user