Refactor Vector vello renderer for Gradient / Color

# Conflicts:
#	node-graph/libraries/rendering/src/renderer.rs
This commit is contained in:
YohYamasaki
2026-05-18 09:03:49 +09:00
parent e192269481
commit 25358d3832
+31 -14
View File
@@ -18,6 +18,7 @@ use core_types::{
use dyn_any::DynAny; use dyn_any::DynAny;
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use graphene_hash::CacheHashWrapper; use graphene_hash::CacheHashWrapper;
use graphic_types::graphic::fill_to_paint;
use graphic_types::raster_types::{BitmapMut, CPU, GPU, Image, Raster}; use graphic_types::raster_types::{BitmapMut, CPU, GPU, Image, Raster};
use graphic_types::vector_types::gradient::{GradientStops, GradientType}; use graphic_types::vector_types::gradient::{GradientStops, GradientType};
use graphic_types::vector_types::subpath::Subpath; use graphic_types::vector_types::subpath::Subpath;
@@ -1181,16 +1182,30 @@ impl Render for List<Vector> {
let use_layer = can_draw_aligned_stroke; let use_layer = can_draw_aligned_stroke;
let wants_stroke_below = stroke.as_ref().is_some_and(|s| s.paint_order == vector::style::PaintOrder::StrokeBelow); let wants_stroke_below = stroke.as_ref().is_some_and(|s| s.paint_order == vector::style::PaintOrder::StrokeBelow);
// Closures to avoid duplicated fill/stroke drawing logic // TODO: This conversion is only necessary during the transition period from Fill to Table<Graphic>
let do_fill_path = |scene: &mut Scene, path: &kurbo::BezPath, fill_rule: peniko::Fill| match element.style.fill() { let do_fill_path = |scene: &mut Scene, path: &kurbo::BezPath, fill_rule: peniko::Fill| {
Fill::Solid(color) => { let Some(paint_table) = fill_to_paint(element.style.fill()) else {
return;
};
for paint_idx in 0..paint_table.len() {
let Some(paint) = paint_table.element(paint_idx) else { continue };
match paint {
Graphic::Color(table) => {
let Some(color) = table.element(0) else { continue };
let fill = peniko::Brush::Solid(SRGBA8::from(*color).to_peniko_color()); let fill = peniko::Brush::Solid(SRGBA8::from(*color).to_peniko_color());
scene.fill(fill_rule, kurbo::Affine::new(element_transform.to_cols_array()), &fill, None, path); scene.fill(fill_rule, kurbo::Affine::new(element_transform.to_cols_array()), &fill, None, path);
} }
Fill::Gradient(gradient) => { Graphic::Gradient(stops_table) => {
let mut stops = peniko::ColorStops::new(); let Some(stops) = stops_table.element(0) else { continue };
for (position, color, _) in gradient.stops.interpolated_samples() { let gradient_type: GradientType = stops_table.attribute_cloned_or_default(ATTR_GRADIENT_TYPE, 0);
stops.push(peniko::ColorStop { let gradient_transform: DAffine2 = stops_table.attribute_cloned_or_default(ATTR_TRANSFORM, 0);
let spread_method: GradientSpreadMethod = stops_table.attribute_cloned_or_default(ATTR_SPREAD_METHOD, 0);
let mut peniko_stops = peniko::ColorStops::new();
for (position, color, _) in stops.interpolated_samples() {
peniko_stops.push(peniko::ColorStop {
offset: position as f32, offset: position as f32,
color: peniko::color::DynamicColor::from_alpha_color(SRGBA8::from(color).to_peniko_color()), color: peniko::color::DynamicColor::from_alpha_color(SRGBA8::from(color).to_peniko_color()),
}); });
@@ -1204,13 +1219,13 @@ impl Render for List<Vector> {
} else { } else {
Default::default() Default::default()
}; };
let mod_points = inverse_parent_transform * multiplied_transform * bound_transform; let mod_points = inverse_parent_transform * multiplied_transform * bound_transform * gradient_transform;
let start = mod_points.transform_point2(gradient.start); let start = mod_points.transform_point2(DVec2::ZERO);
let end = mod_points.transform_point2(gradient.end); let end = mod_points.transform_point2(DVec2::X);
let fill = peniko::Brush::Gradient(peniko::Gradient { let fill = peniko::Brush::Gradient(peniko::Gradient {
kind: match gradient.gradient_type { kind: match gradient_type {
GradientType::Linear => peniko::LinearGradientPosition { GradientType::Linear => peniko::LinearGradientPosition {
start: to_point(start), start: to_point(start),
end: to_point(end), end: to_point(end),
@@ -1227,12 +1242,12 @@ impl Render for List<Vector> {
.into() .into()
} }
}, },
extend: match gradient.spread_method { extend: match spread_method {
GradientSpreadMethod::Pad => peniko::Extend::Pad, GradientSpreadMethod::Pad => peniko::Extend::Pad,
GradientSpreadMethod::Reflect => peniko::Extend::Reflect, GradientSpreadMethod::Reflect => peniko::Extend::Reflect,
GradientSpreadMethod::Repeat => peniko::Extend::Repeat, GradientSpreadMethod::Repeat => peniko::Extend::Repeat,
}, },
stops, stops: peniko_stops,
interpolation_alpha_space: peniko::InterpolationAlphaSpace::Premultiplied, interpolation_alpha_space: peniko::InterpolationAlphaSpace::Premultiplied,
..Default::default() ..Default::default()
}); });
@@ -1244,7 +1259,9 @@ impl Render for List<Vector> {
let brush_transform = kurbo::Affine::new((inverse_element_transform * parent_transform).to_cols_array()); let brush_transform = kurbo::Affine::new((inverse_element_transform * parent_transform).to_cols_array());
scene.fill(fill_rule, kurbo::Affine::new(element_transform.to_cols_array()), &fill, Some(brush_transform), path); scene.fill(fill_rule, kurbo::Affine::new(element_transform.to_cols_array()), &fill, Some(brush_transform), path);
} }
Fill::None => {} _ => todo!(),
};
}
}; };
// Branching vectors without regions (e.g. mesh grids) need face-by-face fill rendering. // Branching vectors without regions (e.g. mesh grids) need face-by-face fill rendering.