Rename the Graphic enum wrapper variants with a "List" suffix (#4434)

Only the list-holding variant takes the suffix here: the record model already carries the rank-0 leaves upstream adds in #4437.

Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
Keavon Chambers
2026-09-15 15:06:10 +02:00
committed by Dennis Kobert
parent a41b362fe2
commit f09eb73c08
14 changed files with 76 additions and 76 deletions

View File

@@ -12,7 +12,7 @@ use glam::DAffine2;
/// enclosing `List<Artboard>`, not as fields here. This keeps `Artboard` a pure type-system boundary
/// that prevents arbitrary `List<List<...<Graphic>>>` nesting.
#[derive(Clone, Debug, Default, CacheHash, PartialEq, DynAny)]
pub struct Artboard<'e>(List<Graphic<'e>>);
pub struct Artboard<'e>(pub List<Graphic<'e>>);
impl<'e> Artboard<'e> {
pub fn new(content: List<Graphic<'e>>) -> Self {

View File

@@ -14,14 +14,14 @@ pub fn map_groups_to_owned<'out>(graphic: &Graphic<'_>) -> Graphic<'out> {
match graphic {
Graphic::None => Graphic::None,
Graphic::Group(group) => Graphic::Group(group.copy_out()),
Graphic::Graphic(children) => {
Graphic::GraphicList(children) => {
let mut out = List::new();
for item in children.clone().into_iter() {
let (element, attributes) = item.into_parts();
out.push(Item::from_parts(map_groups_to_owned(&element), attributes));
}
map_attribute_groups_to_owned(&mut out);
Graphic::Graphic(out)
Graphic::GraphicList(out)
}
Graphic::Vector(vector) => Graphic::Vector(vector.clone()),
Graphic::RasterCPU(raster) => Graphic::RasterCPU(raster.clone()),
@@ -37,13 +37,13 @@ pub fn map_groups_to_owned<'out>(graphic: &Graphic<'_>) -> Graphic<'out> {
pub fn map_groups_to_resident<'a>(graphic: &Graphic<'a>, arena: &'a core_types::arena::Arena) -> Option<Graphic<'a>> {
match graphic {
Graphic::Group(group) => group.replay(arena).map(Graphic::Group),
Graphic::Graphic(children) => {
Graphic::GraphicList(children) => {
let mut children = children.clone();
for child in children.iter_element_values_mut() {
*child = map_groups_to_resident(child, arena)?;
}
map_attribute_groups_to_resident(&mut children, arena)?;
Some(Graphic::Graphic(children))
Some(Graphic::GraphicList(children))
}
other => Some(other.clone()),
}
@@ -82,14 +82,14 @@ pub fn map_groups_to_persistent<'p>(graphic: &Graphic<'_>, promotion: &core_type
match graphic {
Graphic::None => Some(Graphic::None),
Graphic::Group(group) => group.to_persistent(promotion).map(Graphic::Group),
Graphic::Graphic(children) => {
Graphic::GraphicList(children) => {
let mut out = List::new();
for item in children.clone().into_iter() {
let (element, attributes) = item.into_parts();
out.push(Item::from_parts(map_groups_to_persistent(&element, promotion)?, attributes));
}
map_attribute_groups_to_persistent(&mut out, promotion)?;
Some(Graphic::Graphic(out))
Some(Graphic::GraphicList(out))
}
Graphic::Vector(vector) => Some(Graphic::Vector(vector.clone())),
Graphic::RasterCPU(raster) => Some(Graphic::RasterCPU(raster.clone())),
@@ -216,7 +216,7 @@ fn graphic_retained_heap(graphic: &Graphic<'_>) -> usize {
Graphic::RasterCPU(raster) => raster.data.len() * size_of::<Color>(),
Graphic::Text(text) => text.len(),
Graphic::Gradient(gradient) => gradient.len() * size_of::<(f64, Color)>(),
Graphic::Graphic(children) => (0..children.len()).filter_map(|index| children.element(index)).map(graphic_retained_heap).sum(),
Graphic::GraphicList(children) => (0..children.len()).filter_map(|index| children.element(index)).map(graphic_retained_heap).sum(),
Graphic::None | Graphic::Group(_) | Graphic::RasterGPU(_) | Graphic::Color(_) => 0,
}
}
@@ -236,7 +236,7 @@ fn vector_retained_heap(vector: &Vector) -> usize {
fn graphic_contains_groups(graphic: &Graphic) -> bool {
match graphic {
Graphic::Group(_) => true,
Graphic::Graphic(children) => list_contains_groups(children),
Graphic::GraphicList(children) => list_contains_groups(children),
_ => false,
}
}

View File

@@ -49,14 +49,14 @@ pub fn map_groups_to_legacy<'out>(graphic: &Graphic<'_>) -> Graphic<'out> {
match graphic {
Graphic::None => Graphic::None,
Graphic::Group(group) => group_to_legacy_graphic(group),
Graphic::Graphic(children) => {
Graphic::GraphicList(children) => {
let mut out = List::new();
for item in children.clone().into_iter() {
let (element, attributes) = item.into_parts();
out.push(Item::from_parts(map_groups_to_legacy(&element), attributes));
}
map_paint_attrs_to_legacy(&mut out);
Graphic::Graphic(out)
Graphic::GraphicList(out)
}
Graphic::Vector(vector) => Graphic::Vector(vector.clone()),
Graphic::RasterCPU(raster) => Graphic::RasterCPU(raster.clone()),
@@ -81,10 +81,10 @@ pub fn group_to_legacy_graphic(group: &core_types::record::Group) -> Graphic<'st
.or_else(|| run_to_legacy_list::<Gradient>(item).map(|list| detable_items(list, Graphic::Gradient)))
.or_else(|| run_to_legacy_list::<String>(item).map(|list| detable_items(list, Graphic::Text)));
if let Some(typed) = typed {
return Graphic::Graphic(typed);
return Graphic::GraphicList(typed);
}
}
Graphic::Graphic(group_to_legacy_list(group))
Graphic::GraphicList(group_to_legacy_list(group))
}
/// The group as a legacy `List<Graphic>`: a `Graphic` run becomes the items,
@@ -122,7 +122,7 @@ mod run_tests {
// SAFETY: the erased native list serves only while `source` is live; the
// deep glue under test replaces its borrows at the copy-out seam.
let paint = unsafe { core_types::record::erase_static(native_group_paint(&inner_vector, &source)) };
let appearance = Appearance::new_single(Coverage::new_fill(), Graphic::Graphic(paint.clone()));
let appearance = Appearance::new_single(Coverage::new_fill(), Graphic::GraphicList(paint.clone()));
let vector = unit_square_at(DVec2::new(4., 4.));
let mut builder = RunBuilder::new(&source, element_write_hashed::<Vector>(), &[FieldWrite::of::<AppearanceMarker>(0)], 1).unwrap();
@@ -137,7 +137,7 @@ mod run_tests {
let served = legacy.attribute::<Appearance>(ATTR_APPEARANCE, 0).expect("the appearance rides the list");
let cell = served.paint_at(0).expect("the fill coverage keeps its paint");
let Graphic::Graphic(cell_rows) = cell else { panic!("the paint cell keeps the list form") };
let Graphic::GraphicList(cell_rows) = cell else { panic!("the paint cell keeps the list form") };
assert_eq!(cell_rows.element(0).unwrap(), &expected);
}

View File

@@ -50,7 +50,7 @@ impl<'e> Graphic<'e> {
match self {
// The legacy interior is owned outright, so its lanes map in place.
Graphic::Graphic(children) => {
Graphic::GraphicList(children) => {
for row in 0..children.len() {
let lane_transform: DAffine2 = children.attribute_cloned_or_default(ATTR_TRANSFORM, row);
let Some(child) = children.element_mut(row) else { continue };
@@ -217,7 +217,7 @@ mod tests {
let mut children = List::new();
children.push(Item::new_from_element(Graphic::Color(core_types::Color::WHITE)));
children.push(Item::new_from_element(Graphic::Vector(unit_square_at(DVec2::ZERO))));
let mut graphic = Graphic::Graphic(children);
let mut graphic = Graphic::GraphicList(children);
let mut mapped = 0;
graphic
@@ -228,7 +228,7 @@ mod tests {
.expect("no rebuild is needed");
assert_eq!(mapped, 1, "only the vector leaf is mapped");
let Graphic::Graphic(children) = &graphic else { panic!("the list form survives") };
let Graphic::GraphicList(children) = &graphic else { panic!("the list form survives") };
assert!(matches!(children.element(0), Some(Graphic::Color(_))), "the color leaf passes through untouched");
}
}

View File

@@ -38,7 +38,7 @@ pub enum Graphic<'e> {
/// The absence of graphical content, like CSS's `none` keyword: painting it produces nothing.
#[default]
None,
Graphic(List<Graphic<'e>>),
GraphicList(List<Graphic<'e>>),
Vector(Vector),
RasterCPU(Raster<CPU>),
RasterGPU(Raster<GPU>),
@@ -164,7 +164,7 @@ impl From<String> for Graphic<'_> {
/// Both group forms are excluded: a lone native `Group` still has interior structure to flatten.
pub fn is_lone_anonymous_leaf(content: &List<Graphic>) -> bool {
content.len() == 1
&& !matches!(content.element(0), Some(Graphic::Graphic(_)) | Some(Graphic::Group(_)))
&& !matches!(content.element(0), Some(Graphic::GraphicList(_)) | Some(Graphic::Group(_)))
&& content.attribute::<DAffine2>(ATTR_TRANSFORM, 0).is_none()
&& content.attribute::<f64>(ATTR_OPACITY, 0).is_none()
&& content.attribute::<f64>(ATTR_OPACITY_FILL, 0).is_none()
@@ -172,7 +172,7 @@ pub fn is_lone_anonymous_leaf(content: &List<Graphic>) -> bool {
}
/// Deeply flattens a `List<Graphic>`, collecting only elements matching a specific variant (extracted by `extract_variant`)
/// and discarding all other non-matching content. Recursion through `Graphic::Graphic` sub-`List`s composes transforms and opacity.
/// and discarding all other non-matching content. Recursion through `Graphic::GraphicList` sub-`List`s composes transforms and opacity.
fn flatten_graphic_list<T>(content: List<Graphic>, extract_variant: fn(Graphic) -> Option<List<T>>) -> List<T> {
// Its list is already the flat answer, so hand it back rather than rebuilding it item by item
if is_lone_anonymous_leaf(&content) {
@@ -200,7 +200,7 @@ fn flatten_graphic_list<T>(content: List<Graphic>, extract_variant: fn(Graphic)
match element {
// Compose the parent's transform/opacity/fill onto each child, but only for attributes the parent carries.
// A child lacking one is padded with the composition identity (`1.` for opacity/fill, identity for transform), so composing through it is a no-op.
Graphic::Graphic(mut sub_list) => {
Graphic::GraphicList(mut sub_list) => {
// A group's first child has no preceding sibling, so its clipping flag is inert until splicing
// hands it the group's own predecessor. Clear it (keeping the column) to stay clip-neutral.
if sub_list.attribute::<bool>(ATTR_CLIPPING_MASK, 0).is_some() {
@@ -379,14 +379,14 @@ impl From<DVec2> for Graphic<'_> {
impl<'e> Graphic<'e> {
pub fn as_graphic(&self) -> Option<&List<Graphic<'_>>> {
match self {
Graphic::Graphic(graphic) => Some(graphic),
Graphic::GraphicList(graphic) => Some(graphic),
_ => None,
}
}
pub fn as_graphic_mut(&mut self) -> Option<&mut List<Graphic<'e>>> {
match self {
Graphic::Graphic(graphic) => Some(graphic),
Graphic::GraphicList(graphic) => Some(graphic),
_ => None,
}
}
@@ -420,7 +420,7 @@ impl<'e> Graphic<'e> {
match self {
Graphic::None => true,
Graphic::Graphic(list) => all_clipped(list),
Graphic::GraphicList(list) => all_clipped(list),
Graphic::Group(group) => group_all_clipped(group),
_ => false,
}
@@ -436,7 +436,7 @@ impl<'e> Graphic<'e> {
pub fn is_opaque(&self) -> bool {
match self {
Graphic::None => false,
Graphic::Graphic(list) => !list.is_empty() && list.iter_element_values().all(Graphic::is_opaque),
Graphic::GraphicList(list) => !list.is_empty() && list.iter_element_values().all(Graphic::is_opaque),
// A bare leaf carries no paint attribute, which rides its lane, so
// nothing here claims opacity.
Graphic::Vector(_) => false,
@@ -450,7 +450,7 @@ impl<'e> Graphic<'e> {
pub fn is_fully_transparent(&self) -> bool {
match self {
Graphic::None => true,
Graphic::Graphic(list) => list.iter_element_values().all(Graphic::is_fully_transparent),
Graphic::GraphicList(list) => list.iter_element_values().all(Graphic::is_fully_transparent),
// A bare vector leaf carries no paint or stroke of its own, so it is invisible on its own
Graphic::Vector(_) => true,
Graphic::Color(color) => color.a() == 0.,
@@ -470,7 +470,7 @@ impl<'e> Graphic<'e> {
pub fn is_empty(&self) -> bool {
match self {
Graphic::None => true,
Graphic::Graphic(list) => list.is_empty(),
Graphic::GraphicList(list) => list.is_empty(),
Graphic::Group(group) => group_is_empty(group),
_ => false,
}
@@ -484,7 +484,7 @@ impl BoundingBox for Graphic<'_> {
Graphic::Vector(vector) => BoundingBox::bounding_box(vector, transform, include_stroke),
Graphic::RasterCPU(raster) => raster.bounding_box(transform, include_stroke),
Graphic::RasterGPU(raster) => raster.bounding_box(transform, include_stroke),
Graphic::Graphic(list) => list.bounding_box(transform, include_stroke),
Graphic::GraphicList(list) => list.bounding_box(transform, include_stroke),
Graphic::Color(color) => color.bounding_box(transform, include_stroke),
Graphic::Gradient(gradient) => gradient.bounding_box(transform, include_stroke),
Graphic::Text(text) => text.bounding_box(transform, include_stroke),
@@ -498,7 +498,7 @@ impl BoundingBox for Graphic<'_> {
Graphic::Vector(vector) => vector.thumbnail_bounding_box(transform, include_stroke),
Graphic::RasterCPU(raster) => raster.thumbnail_bounding_box(transform, include_stroke),
Graphic::RasterGPU(raster) => raster.thumbnail_bounding_box(transform, include_stroke),
Graphic::Graphic(graphic) => graphic.thumbnail_bounding_box(transform, include_stroke),
Graphic::GraphicList(graphic) => graphic.thumbnail_bounding_box(transform, include_stroke),
Graphic::Color(color) => color.thumbnail_bounding_box(transform, include_stroke),
Graphic::Gradient(gradient) => gradient.thumbnail_bounding_box(transform, include_stroke),
Graphic::Text(list) => list.thumbnail_bounding_box(transform, include_stroke),
@@ -527,7 +527,7 @@ impl RenderComplexity for Graphic<'_> {
fn render_complexity(&self) -> usize {
match self {
Self::None => 0,
Self::Graphic(list) => list.render_complexity(),
Self::GraphicList(list) => list.render_complexity(),
Self::Vector(list) => list.render_complexity(),
Self::RasterCPU(list) => list.render_complexity(),
Self::RasterGPU(list) => list.render_complexity(),
@@ -676,7 +676,7 @@ mod tests {
let flattened: List<Vector> = graphics.into_flattened_list();
assert_eq!(flattened.attribute_cloned_or_default::<f64>(ATTR_OPACITY, 0), 0.5);
let mut group = List::new_from_element(Graphic::Graphic(List::new_from_element(vector_graphic())));
let mut group = List::new_from_element(Graphic::GraphicList(List::new_from_element(vector_graphic())));
group.set_attribute(ATTR_OPACITY, 0, 0.5_f64);
let flattened: List<Vector> = group.into_flattened_list();
assert_eq!(flattened.attribute_cloned_or_default::<f64>(ATTR_OPACITY, 0), 0.5);
@@ -695,7 +695,7 @@ mod tests {
inner.push(Item::new_from_element(vector_graphic()));
inner.set_attribute(ATTR_APPEARANCE, 0, single(Color::BLACK));
let mut outer = List::new_from_element(Graphic::Graphic(inner));
let mut outer = List::new_from_element(Graphic::GraphicList(inner));
outer.set_attribute(ATTR_APPEARANCE, 0, single(Color::WHITE));
let flattened: List<Vector> = outer.into_flattened_list();

View File

@@ -90,7 +90,7 @@ impl<'a> PaintReach<'a> {
/// cell of any other form is treated as paint that draws nothing.
pub fn paint_cell_rows<'a>(cell: &'a Graphic<'static>) -> Option<&'a List<Graphic<'static>>> {
match cell {
Graphic::Graphic(list) => Some(list).filter(|list| is_paint_present(list)),
Graphic::GraphicList(list) => Some(list).filter(|list| is_paint_present(list)),
_ => None,
}
}
@@ -103,7 +103,7 @@ pub fn bake_paint_transforms(attributes: &mut ItemAttributeValues, transform: DA
*item_transform = transform * *item_transform;
}
for graphic in graphics.iter_element_values_mut() {
if let Graphic::Graphic(list) = graphic {
if let Graphic::GraphicList(list) = graphic {
bake_graphic_paint_transform(list, transform);
}
}
@@ -113,7 +113,7 @@ pub fn bake_paint_transforms(attributes: &mut ItemAttributeValues, transform: DA
&& let Some(cells) = appearance.0.iter_attribute_values_mut::<Graphic>(crate::markers::ATTR_PAINT)
{
for cell in cells {
if let Graphic::Graphic(list) = cell {
if let Graphic::GraphicList(list) = cell {
bake_graphic_paint_transform(list, transform);
}
}

View File

@@ -399,7 +399,7 @@ fn walk_vector_rows_impl<'a>(
appearance: reach.appearance,
top_lane: row_top,
}),
Graphic::Graphic(children) => walk_vector_rows_impl(
Graphic::GraphicList(children) => walk_vector_rows_impl(
GraphicLevel::Legacy(children),
scale.composed(&level, index),
level.try_attr::<EditorLayerPath>(index),
@@ -496,11 +496,11 @@ mod run_tests {
let deep = List::new_from_element(Graphic::Vector(unit_square_at(DVec2::new(3., 3.))));
let mut mixed = List::new();
mixed.push(Item::new_from_element(Graphic::Vector(unit_square_at(DVec2::ZERO))));
mixed.push(Item::new_from_element(Graphic::Graphic(deep)));
mixed.push(Item::new_from_element(Graphic::GraphicList(deep)));
let mut top = List::new();
top.push(Item::new_from_element(Graphic::Vector(unit_square_at(DVec2::new(9., 9.)))));
top.push(Item::new_from_element(Graphic::Graphic(mixed)));
top.push(Item::new_from_element(Graphic::GraphicList(mixed)));
let mut reported = Vec::new();
walk_vector_rows(GraphicLevel::Legacy(&top), &mut |row| {
@@ -537,8 +537,8 @@ mod run_tests {
nested.set_attribute(core_types::ATTR_TRANSFORM, 0, DAffine2::from_scale(DVec2::splat(2.)));
let mut top = List::new();
top.push(Item::new_from_element(Graphic::Graphic(painted)));
top.push(Item::new_from_element(Graphic::Graphic(nested)));
top.push(Item::new_from_element(Graphic::GraphicList(painted)));
top.push(Item::new_from_element(Graphic::GraphicList(nested)));
top.push(Item::new_from_element(Graphic::Group(core_types::record::Group { row: None, content: inner_item })));
top.push(Item::new_from_element(Graphic::Color(Color::BLACK)));
top.push(Item::new_from_element(Graphic::Vector(unit_square_at(DVec2::new(6., 0.)))));
@@ -621,7 +621,7 @@ mod run_tests {
inner.push(Item::new_from_element(Graphic::Vector(unit_square_at(DVec2::ONE))));
inner.set_attribute(ATTR_APPEARANCE, 0, single(Color::BLACK));
let mut top = List::new_from_element(Graphic::Graphic(inner));
let mut top = List::new_from_element(Graphic::GraphicList(inner));
top.set_attribute(ATTR_APPEARANCE, 0, single(Color::WHITE));
let walked = flatten_vector_rows(GraphicLevel::Legacy(&top));

View File

@@ -271,7 +271,7 @@ impl RenderExt for List<Graphic<'_>> {
format!(r##" {paint_attr}="url(#{gradient_id})""##)
}
Some(Graphic::None) => format!(r#" {paint_attr}="none""#),
Some(Graphic::Vector(_)) | Some(Graphic::RasterCPU(_)) | Some(Graphic::RasterGPU(_)) | Some(Graphic::Graphic(_)) | Some(Graphic::Text(_)) | Some(Graphic::Group(_)) => {
Some(Graphic::Vector(_)) | Some(Graphic::RasterCPU(_)) | Some(Graphic::RasterGPU(_)) | Some(Graphic::GraphicList(_)) | Some(Graphic::Text(_)) | Some(Graphic::Group(_)) => {
let bounds = if target == PaintTarget::Stroke {
// To prevent a wraparound artefact occurring when the tile boundary and the stroke region are perfectly aligned, the local coordinate is expanded slightly.
let inverse = |len: f64| if len > 0. { 1. / len } else { 0. };

View File

@@ -210,7 +210,7 @@ pub struct RenderContext {
/// The single black-fill appearance a mask clone paints with, at full alpha so the mask fully covers the interior.
fn black_fill_appearance() -> Appearance {
Appearance::new_single(Coverage::new_fill(), Graphic::Graphic(List::new_from_element(Graphic::Color(Color::BLACK))))
Appearance::new_single(Coverage::new_fill(), Graphic::GraphicList(List::new_from_element(Graphic::Color(Color::BLACK))))
}
/// The alpha multiplier a paint row's opacity attributes apply when it serves as a paint.
@@ -737,7 +737,7 @@ impl Render for Graphic<'_> {
fn render_svg(&self, render: &mut SvgRender, render_params: &RenderParams) {
match self {
Graphic::None => (),
Graphic::Graphic(list) => list.render_svg(render, render_params),
Graphic::GraphicList(list) => list.render_svg(render, render_params),
Graphic::Vector(vector) => render_vector_svg(&Single(vector), None, render, render_params),
Graphic::RasterCPU(raster) => render_raster_cpu_svg(&Single(raster), render, render_params),
Graphic::RasterGPU(_) => (),
@@ -751,7 +751,7 @@ impl Render for Graphic<'_> {
fn render_to_vello(&self, scene: &mut Scene, transform: DAffine2, context: &mut RenderContext, render_params: &RenderParams) {
match self {
Graphic::None => (),
Graphic::Graphic(list) => list.render_to_vello(scene, transform, context, render_params),
Graphic::GraphicList(list) => list.render_to_vello(scene, transform, context, render_params),
Graphic::Vector(vector) => render_vector_vello(&Single(vector), None, scene, transform, context, render_params),
Graphic::RasterCPU(raster) => render_raster_cpu_vello(&Single(raster), scene, transform, render_params),
Graphic::RasterGPU(raster) => render_raster_gpu_vello(&Single(raster), scene, transform, context, render_params),
@@ -777,7 +777,7 @@ impl Render for Graphic<'_> {
fn contains_artboard(&self) -> bool {
match self {
Graphic::None => false,
Graphic::Graphic(list) => list.contains_artboard(),
Graphic::GraphicList(list) => list.contains_artboard(),
_ => false,
}
}
@@ -785,7 +785,7 @@ impl Render for Graphic<'_> {
fn new_ids_from_hash(&mut self, reference: Option<NodeId>) {
match self {
Graphic::None => (),
Graphic::Graphic(list) => list.new_ids_from_hash(reference),
Graphic::GraphicList(list) => list.new_ids_from_hash(reference),
Graphic::Vector(vector) => vector.vector_new_ids_from_hash(reference.map(|id| id.0).unwrap_or_default()),
_ => (),
}
@@ -795,7 +795,7 @@ impl Render for Graphic<'_> {
fn render_element_svg<'a>(element: &'a Graphic, reach: PaintReach<'a>, render: &mut SvgRender, render_params: &RenderParams) {
match element {
Graphic::Vector(vector) => render_vector_svg(&Single(vector), reach.appearance, render, render_params),
Graphic::Graphic(inner) => render_graphic_svg_with(inner, reach, render, render_params),
Graphic::GraphicList(inner) => render_graphic_svg_with(inner, reach, render, render_params),
Graphic::Group(group) => render_group_svg(group, reach, render, render_params),
_ => element.render_svg(render, render_params),
}
@@ -804,7 +804,7 @@ fn render_element_svg<'a>(element: &'a Graphic, reach: PaintReach<'a>, render: &
fn render_element_vello<'a>(element: &'a Graphic, reach: PaintReach<'a>, scene: &mut Scene, transform: DAffine2, context: &mut RenderContext, render_params: &RenderParams) {
match element {
Graphic::Vector(vector) => render_vector_vello(&Single(vector), reach.appearance, scene, transform, context, render_params),
Graphic::Graphic(inner) => render_graphic_vello_with(inner, reach, scene, transform, context, render_params),
Graphic::GraphicList(inner) => render_graphic_vello_with(inner, reach, scene, transform, context, render_params),
Graphic::Group(group) => render_group_vello(group, reach, scene, transform, context, render_params),
_ => element.render_to_vello(scene, transform, context, render_params),
}
@@ -834,7 +834,7 @@ fn collect_element_metadata<'a>(
metadata.upstream_footprints.insert(element_id, footprint);
match element {
Graphic::Group(group) => collect_group_row_metadata(group, metadata, element_id),
Graphic::Graphic(_) => {}
Graphic::GraphicList(_) => {}
// A leaf's layer identity and transform ride its containing lane.
Graphic::Vector(_) => {
metadata.first_element_source_id.insert(element_id, lane_source);
@@ -848,7 +848,7 @@ fn collect_element_metadata<'a>(
match element {
Graphic::None => {}
Graphic::Graphic(list) => collect_graphic_metadata_with(list, reach, metadata, footprint, element_id),
Graphic::GraphicList(list) => collect_graphic_metadata_with(list, reach, metadata, footprint, element_id),
Graphic::Vector(vector) => collect_vector_metadata(&Single(vector), reach.appearance, metadata, footprint, element_id),
Graphic::RasterCPU(raster) => collect_raster_metadata(&Single(raster), metadata, footprint, element_id),
Graphic::RasterGPU(raster) => collect_raster_metadata(&Single(raster), metadata, footprint, element_id),
@@ -891,7 +891,7 @@ fn collect_group_row_metadata(group: &Group, metadata: &mut RenderMetadata, elem
fn add_element_upstream_click_targets<'a>(element: &'a Graphic, reach: PaintReach<'a>, click_targets: &mut Vec<ClickTarget>) {
match element {
Graphic::None => (),
Graphic::Graphic(list) => add_graphic_upstream_click_targets_with(list, reach, click_targets),
Graphic::GraphicList(list) => add_graphic_upstream_click_targets_with(list, reach, click_targets),
Graphic::Vector(vector) => add_vector_upstream_click_targets(&Single(vector), reach.appearance, click_targets),
Graphic::RasterCPU(_) | Graphic::RasterGPU(_) => add_raster_upstream_click_targets(click_targets),
Graphic::Color(_) => {}
@@ -904,7 +904,7 @@ fn add_element_upstream_click_targets<'a>(element: &'a Graphic, reach: PaintReac
fn add_element_upstream_outline_targets<'a>(element: &'a Graphic, reach: PaintReach<'a>, outlines: &mut Vec<ClickTarget>) {
match element {
Graphic::None => (),
Graphic::Graphic(list) => add_graphic_upstream_outline_targets_with(list, reach, outlines),
Graphic::GraphicList(list) => add_graphic_upstream_outline_targets_with(list, reach, outlines),
Graphic::Vector(vector) => add_vector_upstream_outline_targets(&Single(vector), reach.appearance, outlines),
Graphic::RasterCPU(_) | Graphic::RasterGPU(_) => add_raster_upstream_click_targets(outlines),
Graphic::Color(_) => {}
@@ -1856,7 +1856,7 @@ fn render_vector_item_vello<S: LaneSource<Element = Vector>>(
let brush_transform = kurbo::Affine::new((inverse_element_transform * gradient_to_device).to_cols_array());
scene.fill(fill_rule, kurbo::Affine::new(element_transform.to_cols_array()), &brush, Some(brush_transform), path);
}
Graphic::Vector(_) | Graphic::RasterCPU(_) | Graphic::RasterGPU(_) | Graphic::Graphic(_) | Graphic::Text(_) | Graphic::Group(_) => {
Graphic::Vector(_) | Graphic::RasterCPU(_) | Graphic::RasterGPU(_) | Graphic::GraphicList(_) | Graphic::Text(_) | Graphic::Group(_) => {
scene.push_clip_layer(fill_rule, kurbo::Affine::new(element_transform.to_cols_array()), path);
paint.render_to_vello(scene, multiplied_transform, context, render_params);
scene.pop_layer();
@@ -1941,7 +1941,7 @@ fn render_vector_item_vello<S: LaneSource<Element = Vector>>(
scene.stroke(&stroke, kurbo::Affine::new(element_transform.to_cols_array()), &brush, Some(brush_transform), &path);
}
Graphic::Vector(_) | Graphic::RasterCPU(_) | Graphic::RasterGPU(_) | Graphic::Graphic(_) | Graphic::Text(_) | Graphic::Group(_) => {
Graphic::Vector(_) | Graphic::RasterCPU(_) | Graphic::RasterGPU(_) | Graphic::GraphicList(_) | Graphic::Text(_) | Graphic::Group(_) => {
let stroked = peniko::kurbo::stroke(path.iter(), &stroke, &StrokeOpts::default(), 0.01);
scene.push_clip_layer(peniko::Fill::NonZero, kurbo::Affine::new(element_transform.to_cols_array()), &stroked);
@@ -3015,7 +3015,7 @@ pub fn graphic_list_bounding_box<'e, S: LaneSource<Element = Graphic<'e>>>(sourc
let Some(graphic) = source.element(index) else { continue };
let bounds = match graphic {
Graphic::Text(text) => text_list_bounding_box(&Single(text), item_transform),
Graphic::Graphic(sub_list) => graphic_list_bounding_box(sub_list, item_transform),
Graphic::GraphicList(sub_list) => graphic_list_bounding_box(sub_list, item_transform),
other => other.thumbnail_bounding_box(item_transform, true),
};
match bounds {
@@ -3462,7 +3462,7 @@ mod group_walk_tests {
/// The appearance the fill node stamps, so test content mirrors node output.
fn fill_appearance(paint: &List<Graphic<'static>>) -> Appearance {
Appearance::new_single(Coverage::new_fill(), Graphic::Graphic(paint.clone()))
Appearance::new_single(Coverage::new_fill(), Graphic::GraphicList(paint.clone()))
}
fn rendered_svg(render: impl FnOnce(&mut SvgRender)) -> (String, String) {
@@ -3506,7 +3506,7 @@ mod group_walk_tests {
let params = RenderParams::default();
let native = rendered_svg(|render| Graphic::Group(group.clone()).render_svg(render, &params));
let legacy = rendered_svg(|render| Graphic::Graphic(graphic_types::graphic::group_to_legacy_list(&group)).render_svg(render, &params));
let legacy = rendered_svg(|render| Graphic::GraphicList(graphic_types::graphic::group_to_legacy_list(&group)).render_svg(render, &params));
assert!(native.0.contains(r##"fill="#"##), "the lane's fill paint must reach the vector interior: {}", native.0);
assert_eq!(native, legacy);

View File

@@ -26,7 +26,7 @@ pub enum GradientForm {
/// attributes place each stop along the 0 to 1 range. Stops lacking the `position` attribute distribute evenly,
/// and stops lacking the `midpoint` attribute interpolate linearly (`0.5`).
#[derive(Default, Debug, Clone, PartialEq, graphene_hash::CacheHash, DynAny)]
pub struct Gradient(List<Color>);
pub struct Gradient(pub List<Color>);
/// A gradient's per-stop parallel arrays, generic over color format: `GradientStops<Color>` nests inside the
/// [`GradientRamp`] exchange struct, while `GradientStops<SRGBA8>` is the JS-boundary shape used by the color picker UI.

View File

@@ -43,7 +43,7 @@ pub(crate) fn group_locate<'e>(group: &core_types::record::Group<'e>, transform:
/// itself otherwise.
pub(crate) fn leaf_count(graphic: &Graphic, fully_flatten: bool, depth: usize) -> usize {
match graphic {
Graphic::Graphic(children) if fully_flatten || depth == 0 => (0..children.len())
Graphic::GraphicList(children) if fully_flatten || depth == 0 => (0..children.len())
.map(|index| children.element(index).map_or(0, |child| leaf_count(child, fully_flatten, depth + 1)))
.sum(),
Graphic::Group(group) if (fully_flatten || depth == 0) && group_expands(group) => group_leaf_count(group, fully_flatten, depth),
@@ -55,7 +55,7 @@ pub(crate) fn leaf_count(graphic: &Graphic, fully_flatten: bool, depth: usize) -
/// along its path composed onto `transform`.
pub(crate) fn locate<'e>(graphic: &Graphic<'e>, transform: DAffine2, fully_flatten: bool, depth: usize, remaining: &mut usize) -> Option<(Graphic<'e>, DAffine2)> {
match graphic {
Graphic::Graphic(children) if fully_flatten || depth == 0 => (0..children.len()).find_map(|index| {
Graphic::GraphicList(children) if fully_flatten || depth == 0 => (0..children.len()).find_map(|index| {
let child = children.element(index)?;
let child_transform: DAffine2 = children.attribute_cloned_or_default(ATTR_TRANSFORM, index);
locate(child, transform * child_transform, fully_flatten, depth + 1, remaining)
@@ -108,7 +108,7 @@ impl Inherited {
/// of other element types contribute nothing.
pub(crate) fn walk_typed_leaves<T: TryFromGraphic + dyn_any::StaticTypeSized>(graphic: &Graphic, inherited: Inherited, visit: &mut dyn FnMut(&T, Inherited) -> RowStep) -> RowStep {
match graphic {
Graphic::Graphic(children) => {
Graphic::GraphicList(children) => {
for index in 0..children.len() {
let Some(child) = children.element(index) else { continue };
if let RowStep::Stop = walk_typed_leaves(child, inherited.composed(children, index), visit) {
@@ -283,7 +283,7 @@ mod tests {
list.push(Item::new_from_element(child));
list.set_attribute(ATTR_TRANSFORM, index, transform);
}
Graphic::Graphic(list)
Graphic::GraphicList(list)
}
fn text_of<'a>(graphic: &'a Graphic<'_>) -> &'a str {
@@ -607,7 +607,7 @@ mod tests {
let GPoll::Final(record) = record::capture(&node, &ctx.promoted(&head, 2), &frames) else {
panic!("expected a final record");
};
let Graphic::Graphic(children) = record.element::<Graphic>() else {
let Graphic::GraphicList(children) = record.element::<Graphic>() else {
panic!("lane 2 keeps the subgroup element");
};
assert_eq!(children.len(), 1);
@@ -937,11 +937,11 @@ mod tests {
let ctx = ContextImpl::root(&scope);
let nested = {
let Graphic::Graphic(mut children) = group(vec![(Graphic::Color(Color::WHITE), translation(20.)), (text("x"), translation(300.))]) else {
let Graphic::GraphicList(mut children) = group(vec![(Graphic::Color(Color::WHITE), translation(20.)), (text("x"), translation(300.))]) else {
unreachable!("group builds a legacy graphic list");
};
children.set_attribute(core_types::ATTR_OPACITY, 0, 0.5);
Graphic::Graphic(children)
Graphic::GraphicList(children)
};
let rows = vec![(Graphic::Color(Color::BLACK), translation(1.)), (nested, translation(0.5)), (text("y"), translation(9.))];
let layout = graphic_layout();

View File

@@ -361,7 +361,7 @@ fn flatten_vector_run_into<'a>(out: &mut List<Vector>, level: GraphicLevel<'a>,
let composed = ancestors.through(&level, index);
match element {
Graphic::Vector(vector) => push_leaf_vector_row(out, level, index, vector, ancestors, reach),
Graphic::Graphic(children) => push_union(out, flatten_vector_run(GraphicLevel::Legacy(children), composed, reach)),
Graphic::GraphicList(children) => push_union(out, flatten_vector_run(GraphicLevel::Legacy(children), composed, reach)),
Graphic::Group(group) => flatten_group(out, group, composed, reach),
Graphic::Text(text) => {
let one = List::new_from_item(Item::from_parts(text.clone(), graphic_types::graphic::lane_attributes(level, index)));
@@ -491,7 +491,7 @@ mod tests {
/// The single-fill appearance a built row paints with.
fn fill_appearance(paint: List<Graphic<'static>>) -> Appearance {
use graphic_types::appearance::Coverage;
Appearance::new_single(Coverage::new_fill(), Graphic::Graphic(paint))
Appearance::new_single(Coverage::new_fill(), Graphic::GraphicList(paint))
}
#[test]

View File

@@ -127,7 +127,7 @@ fn assign_colors<'e>(
// The recolor lands on the appearance's coverage paints
let mut appearance = existing_appearance.unwrap_or_default();
let paint_cell = Graphic::Graphic(paint);
let paint_cell = Graphic::GraphicList(paint);
if fill && !appearance.set_paint_of(Cover::Fill, paint_cell.clone()) {
appearance.replace_or_insert(Coverage::new_fill(), paint_cell.clone(), CoverPlacement::Below);
}
@@ -239,7 +239,7 @@ fn assign_colors_graphic<'e>(
// The recolor lands on the row's appearance coverage paints
let mut appearance = rows.attribute_cloned_or_default::<Appearance>(graphic_types::ATTR_APPEARANCE, row);
let paint_cell = Graphic::Graphic(paint);
let paint_cell = Graphic::GraphicList(paint);
if fill && !appearance.set_paint_of(Cover::Fill, paint_cell.clone()) {
appearance.replace_or_insert(Coverage::new_fill(), paint_cell.clone(), CoverPlacement::Below);
}
@@ -304,7 +304,7 @@ fn park_appearance(arena: &core_types::arena::Arena, appearance: Appearance) ->
/// graphic cell, the input lane's own envelope dropped.
fn stamped_appearance(content_appearance: Option<&Appearance>, coverage: Coverage, paint: &List<Graphic<'static>>, placement: CoverPlacement) -> Appearance {
let mut appearance = content_appearance.cloned().unwrap_or_default();
appearance.replace_or_insert(coverage, Graphic::Graphic(paint.clone()), placement);
appearance.replace_or_insert(coverage, Graphic::GraphicList(paint.clone()), placement);
appearance
}
@@ -3082,7 +3082,7 @@ fn morph_core(flattened: List<Vector>, snapshot: List<Graphic<'static>>, progres
// The paint cell carries its graphic list as one wrapped cell, so the lerp works on the unwrapped rows.
let source_paint = source_index.and_then(|index| a.paint_at(index)).and_then(graphic_types::graphic::paint_cell_rows);
let target_paint = target_index.and_then(|index| b.paint_at(index)).and_then(graphic_types::graphic::paint_cell_rows);
let paint = lerp_graphic(source_paint, target_paint, time).map(Graphic::Graphic).unwrap_or_default();
let paint = lerp_graphic(source_paint, target_paint, time).map(Graphic::GraphicList).unwrap_or_default();
result.replace_or_insert(coverage, paint, CoverPlacement::Above);
}
@@ -4344,7 +4344,7 @@ mod test {
v
};
let fill_appearance = |color: Color| Appearance::new_single(Coverage::new_fill(), Graphic::Graphic(List::new_from_element(color).into_graphic_list()));
let fill_appearance = |color: Color| Appearance::new_single(Coverage::new_fill(), Graphic::GraphicList(List::new_from_element(color).into_graphic_list()));
let item_a = Item::new_from_element(rect())
.with_attribute(ATTR_TRANSFORM, DAffine2::IDENTITY)
.with_attribute(graphic_types::ATTR_APPEARANCE, fill_appearance(Color::RED));