Instance tables refactor part 6: unwrap VectorData and ImageFrame from single-row to multi-row tables (#2684)

* Start refactoring the boolean operations code

* Switch to iterators in the boolean operations code

* Make boolean operations work on rows of a table, not Vecs of single-row tables

* Remove more .transform()

* Simplify brush code

* Attempt to remove .transform() by using Instance<Image<Color>> in brush code, but a regression is introduced

* Improve blend_image_closure

* Simplify

* Remove leading underscore from type arguments

* Remove .transform() from ImageFrameTable<P> and fix Mask node behavior on stencils not fully overlapping its target image

* Remove more .one_instance_ref()

* Fully remove .one_instance_ref() and improve the 'Combine Channels' node robustness

* Fully remove .once_instance_mut()

* Fix tests

* Remove .one_empty_image()

* Make Instances<T>::default() return an empty table for images, but still not yet vector

---------

Co-authored-by: hypercube <0hypercube@gmail.com>
This commit is contained in:
Keavon Chambers 2025-06-04 20:40:15 -07:00 committed by GitHub
parent 76ecdc8f1b
commit cb4289169d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 882 additions and 811 deletions

View file

@ -12,8 +12,6 @@ use graphene_core::raster::image::{Image, ImageFrameTable};
use graphene_core::renderer::RenderMetadata;
use graphene_core::renderer::{GraphicElementRendered, RenderParams, RenderSvgSegmentList, SvgRender, format_transform_matrix};
use graphene_core::transform::Footprint;
#[cfg(target_arch = "wasm32")]
use graphene_core::transform::TransformMut;
use graphene_core::vector::VectorDataTable;
use graphene_core::{Color, Context, Ctx, ExtractFootprint, GraphicGroupTable, OwnedContextImpl, WasmNotSend};
@ -44,7 +42,7 @@ async fn create_surface<'a: 'n>(_: impl Ctx, editor: &'a WasmEditorApi) -> Arc<W
// image: ImageFrameTable<graphene_core::raster::SRGBA8>,
// surface_handle: Arc<WasmSurfaceHandle>,
// ) -> graphene_core::application_io::SurfaceHandleFrame<HtmlCanvasElement> {
// let image = image.one_instance_ref().instance;
// let image = image.instance_ref_iter().next().unwrap().instance;
// let image_data = image.image.data;
// let array: Clamped<&[u8]> = Clamped(bytemuck::cast_slice(image_data.as_slice()));
// if image.image.width > 0 && image.image.height > 0 {
@ -80,7 +78,7 @@ async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")]
#[node_macro::node(category("Network"))]
fn decode_image(_: impl Ctx, data: Arc<[u8]>) -> ImageFrameTable<Color> {
let Some(image) = image::load_from_memory(data.as_ref()).ok() else {
return ImageFrameTable::one_empty_image();
return ImageFrameTable::default();
};
let image = image.to_rgba32f();
let image = Image {
@ -177,6 +175,8 @@ async fn rasterize<T: WasmNotSend + 'n>(
where
Instances<T>: GraphicElementRendered,
{
use graphene_core::instances::Instance;
if footprint.transform.matrix2.determinant() == 0. {
log::trace!("Invalid footprint received for rasterization");
return ImageFrameTable::empty();
@ -218,8 +218,12 @@ where
let rasterized = context.get_image_data(0., 0., resolution.x as f64, resolution.y as f64).unwrap();
let mut result = ImageFrameTable::new(Image::from_image_data(&rasterized.data().0, resolution.x as u32, resolution.y as u32));
*result.transform_mut() = footprint.transform;
let mut result = ImageFrameTable::empty();
result.push(Instance {
instance: Image::from_image_data(&rasterized.data().0, resolution.x as u32, resolution.y as u32),
transform: footprint.transform,
..Default::default()
});
result
}