Skip to content

Commit 7a02433

Browse files
committed
Refactor Vector vello renderer for Gradient / Color
1 parent b216cbd commit 7a02433

1 file changed

Lines changed: 76 additions & 59 deletions

File tree

node-graph/libraries/rendering/src/renderer.rs

Lines changed: 76 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use core_types::{
1717
use dyn_any::DynAny;
1818
use glam::{DAffine2, DVec2};
1919
use graphene_hash::CacheHashWrapper;
20+
use graphic_types::graphic::fill_to_paint;
2021
use graphic_types::raster_types::{BitmapMut, CPU, GPU, Image, Raster};
2122
use graphic_types::vector_types::gradient::{GradientStops, GradientType};
2223
use graphic_types::vector_types::subpath::Subpath;
@@ -1186,70 +1187,86 @@ impl Render for Table<Vector> {
11861187
let use_layer = can_draw_aligned_stroke;
11871188
let wants_stroke_below = stroke.as_ref().is_some_and(|s| s.paint_order == vector::style::PaintOrder::StrokeBelow);
11881189

1189-
// Closures to avoid duplicated fill/stroke drawing logic
1190-
let do_fill_path = |scene: &mut Scene, path: &kurbo::BezPath, fill_rule: peniko::Fill| match element.style.fill() {
1191-
Fill::Solid(color) => {
1192-
let fill = peniko::Brush::Solid(peniko::Color::new([color.r(), color.g(), color.b(), color.a()]));
1193-
scene.fill(fill_rule, kurbo::Affine::new(element_transform.to_cols_array()), &fill, None, path);
1194-
}
1195-
Fill::Gradient(gradient) => {
1196-
let mut stops = peniko::ColorStops::new();
1197-
for (position, color, _) in gradient.stops.interpolated_samples() {
1198-
stops.push(peniko::ColorStop {
1199-
offset: position as f32,
1200-
color: peniko::color::DynamicColor::from_alpha_color(peniko::Color::new([color.r(), color.g(), color.b(), color.a()])),
1201-
});
1202-
}
1203-
1204-
let bounds = element.nonzero_bounding_box();
1205-
let bound_transform = DAffine2::from_scale_angle_translation(bounds[1] - bounds[0], 0., bounds[0]);
1206-
1207-
let inverse_parent_transform = if parent_transform.matrix2.determinant() != 0. {
1208-
parent_transform.inverse()
1209-
} else {
1210-
Default::default()
1211-
};
1212-
let mod_points = inverse_parent_transform * multiplied_transform * bound_transform;
1190+
// TODO: This conversion is only necessary during the transition period from Fill to Table<Graphic>
1191+
let do_fill_path = |scene: &mut Scene, path: &kurbo::BezPath, fill_rule: peniko::Fill| {
1192+
let Some(paint_table) = fill_to_paint(element.style.fill()) else {
1193+
return;
1194+
};
12131195

1214-
let start = mod_points.transform_point2(gradient.start);
1215-
let end = mod_points.transform_point2(gradient.end);
1196+
for paint_idx in 0..paint_table.len() {
1197+
let Some(paint) = paint_table.element(paint_idx) else { continue };
1198+
match paint {
1199+
Graphic::Color(table) => {
1200+
let Some(color) = table.element(0) else { continue };
12161201

1217-
let fill = peniko::Brush::Gradient(peniko::Gradient {
1218-
kind: match gradient.gradient_type {
1219-
GradientType::Linear => peniko::LinearGradientPosition {
1220-
start: to_point(start),
1221-
end: to_point(end),
1222-
}
1223-
.into(),
1224-
GradientType::Radial => {
1225-
let radius = start.distance(end);
1226-
peniko::RadialGradientPosition {
1227-
start_center: to_point(start),
1228-
start_radius: 0.,
1229-
end_center: to_point(start),
1230-
end_radius: radius as f32,
1231-
}
1232-
.into()
1202+
let fill = peniko::Brush::Solid(peniko::Color::new([color.r(), color.g(), color.b(), color.a()]));
1203+
scene.fill(fill_rule, kurbo::Affine::new(element_transform.to_cols_array()), &fill, None, path);
1204+
}
1205+
Graphic::Gradient(stops_table) => {
1206+
let Some(stops) = stops_table.element(0) else { continue };
1207+
let gradient_type: GradientType = stops_table.attribute_cloned_or_default(ATTR_GRADIENT_TYPE, 0);
1208+
let gradient_transform: DAffine2 = stops_table.attribute_cloned_or_default(ATTR_TRANSFORM, 0);
1209+
let spread_method: GradientSpreadMethod = stops_table.attribute_cloned_or_default(ATTR_SPREAD_METHOD, 0);
1210+
1211+
let mut peniko_stops = peniko::ColorStops::new();
1212+
for (position, color, _) in stops.interpolated_samples() {
1213+
peniko_stops.push(peniko::ColorStop {
1214+
offset: position as f32,
1215+
color: peniko::color::DynamicColor::from_alpha_color(peniko::Color::new([color.r(), color.g(), color.b(), color.a()])),
1216+
});
12331217
}
1234-
},
1235-
extend: match gradient.spread_method {
1236-
GradientSpreadMethod::Pad => peniko::Extend::Pad,
1237-
GradientSpreadMethod::Reflect => peniko::Extend::Reflect,
1238-
GradientSpreadMethod::Repeat => peniko::Extend::Repeat,
1239-
},
1240-
stops,
1241-
interpolation_alpha_space: peniko::InterpolationAlphaSpace::Premultiplied,
1242-
..Default::default()
1243-
});
1244-
let inverse_element_transform = if element_transform.matrix2.determinant() != 0. {
1245-
element_transform.inverse()
1246-
} else {
1247-
Default::default()
1218+
1219+
let bounds = element.nonzero_bounding_box();
1220+
let bound_transform = DAffine2::from_scale_angle_translation(bounds[1] - bounds[0], 0., bounds[0]);
1221+
1222+
let inverse_parent_transform = if parent_transform.matrix2.determinant() != 0. {
1223+
parent_transform.inverse()
1224+
} else {
1225+
Default::default()
1226+
};
1227+
let mod_points = inverse_parent_transform * multiplied_transform * bound_transform * gradient_transform;
1228+
1229+
let start = mod_points.transform_point2(DVec2::ZERO);
1230+
let end = mod_points.transform_point2(DVec2::X);
1231+
1232+
let fill = peniko::Brush::Gradient(peniko::Gradient {
1233+
kind: match gradient_type {
1234+
GradientType::Linear => peniko::LinearGradientPosition {
1235+
start: to_point(start),
1236+
end: to_point(end),
1237+
}
1238+
.into(),
1239+
GradientType::Radial => {
1240+
let radius = start.distance(end);
1241+
peniko::RadialGradientPosition {
1242+
start_center: to_point(start),
1243+
start_radius: 0.,
1244+
end_center: to_point(start),
1245+
end_radius: radius as f32,
1246+
}
1247+
.into()
1248+
}
1249+
},
1250+
extend: match spread_method {
1251+
GradientSpreadMethod::Pad => peniko::Extend::Pad,
1252+
GradientSpreadMethod::Reflect => peniko::Extend::Reflect,
1253+
GradientSpreadMethod::Repeat => peniko::Extend::Repeat,
1254+
},
1255+
stops: peniko_stops,
1256+
interpolation_alpha_space: peniko::InterpolationAlphaSpace::Premultiplied,
1257+
..Default::default()
1258+
});
1259+
let inverse_element_transform = if element_transform.matrix2.determinant() != 0. {
1260+
element_transform.inverse()
1261+
} else {
1262+
Default::default()
1263+
};
1264+
let brush_transform = kurbo::Affine::new((inverse_element_transform * parent_transform).to_cols_array());
1265+
scene.fill(fill_rule, kurbo::Affine::new(element_transform.to_cols_array()), &fill, Some(brush_transform), path);
1266+
}
1267+
_ => todo!(),
12481268
};
1249-
let brush_transform = kurbo::Affine::new((inverse_element_transform * parent_transform).to_cols_array());
1250-
scene.fill(fill_rule, kurbo::Affine::new(element_transform.to_cols_array()), &fill, Some(brush_transform), path);
12511269
}
1252-
Fill::None => {}
12531270
};
12541271

12551272
// Branching vectors without regions (e.g. mesh grids) need face-by-face fill rendering.

0 commit comments

Comments
 (0)