Add rank-0 Item leaf variants to the Graphic enum alongside its List variants (#4437)

* Add the rank-0 Item leaf variants to the Graphic enum, rendering leaves and list rows through shared per-row logic

* Traverse the rank-0 Graphic leaf variants in the vector node helpers and flattening

* Reach rank-0 vector graphics from the styling and gradient-fitting helpers

* Two code review fixes

* Fix comment
This commit is contained in:
Keavon Chambers
2026-08-16 02:24:15 -07:00
committed by GitHub
parent ba7cbd83bc
commit c507b35645
13 changed files with 2412 additions and 1665 deletions
@@ -571,13 +571,33 @@ impl TableItemLayout for BoxCorners {
}
}
impl TableItemLayout for graphene_std::core_types::none::None {
fn type_name() -> &'static str {
"None"
}
fn identifier(&self) -> String {
"None".to_string()
}
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
label("None")
}
}
impl TableItemLayout for Graphic {
fn type_name() -> &'static str {
"Graphic"
}
fn identifier(&self) -> String {
match self {
Self::None => "None".to_string(),
Self::None(item) => item.identifier(),
Self::Graphic(item) => item.identifier(),
Self::Vector(item) => item.identifier(),
Self::RasterCPU(item) => item.identifier(),
Self::RasterGPU(item) => item.identifier(),
Self::Color(item) => item.identifier(),
Self::Gradient(item) => item.identifier(),
Self::Text(item) => item.identifier(),
Self::NoneList(list) => list.identifier(),
Self::GraphicList(list) => list.identifier(),
Self::VectorList(list) => list.identifier(),
Self::RasterCPUList(list) => list.identifier(),
@@ -593,7 +613,15 @@ impl TableItemLayout for Graphic {
}
fn value_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
match self {
Self::None => label("None"),
Self::None(item) => item.layout_with_breadcrumb(data),
Self::Graphic(item) => item.layout_with_breadcrumb(data),
Self::Vector(item) => item.layout_with_breadcrumb(data),
Self::RasterCPU(item) => item.layout_with_breadcrumb(data),
Self::RasterGPU(item) => item.layout_with_breadcrumb(data),
Self::Color(item) => item.layout_with_breadcrumb(data),
Self::Gradient(item) => item.layout_with_breadcrumb(data),
Self::Text(item) => item.layout_with_breadcrumb(data),
Self::NoneList(list) => list.layout_with_breadcrumb(data),
Self::GraphicList(list) => list.layout_with_breadcrumb(data),
Self::VectorList(list) => list.layout_with_breadcrumb(data),
Self::RasterCPUList(list) => list.layout_with_breadcrumb(data),
@@ -2760,7 +2760,7 @@ impl DocumentMessageHandler {
// A visible stroke needs both renderable geometry (non-zero weight) and paint that draws something
let has_stroke = appearance.is_some_and(|appearance| {
appearance.first_coverage_of(Cover::Stroke).is_some_and(|coverage| coverage.stroke_params().has_renderable_stroke())
&& appearance.first_paint_of(Cover::Stroke).is_some_and(|paint| !paint.is_fully_transparent())
&& appearance.first_paint_of(Cover::Stroke).is_some_and(|paint| !paint.is_guaranteed_fully_transparent())
});
// No stroke means there's nothing to solidify. Fill-only layers are already in the desired form, so skip.
@@ -4326,7 +4326,7 @@ mod document_message_handler_tests {
let instrumented = editor.eval_graph().await.unwrap();
// The emptiness guards keep these assertions honest: a wrong `Output` type on `grab_all_input` yields no records at all, which would otherwise pass vacuously
// The emptiness guards keep these assertions honest: a wrong `Output` type on `grab_all_input` yields no records at all, which would otherwise pass without checking anything
let base_lengths: Vec<usize> = instrumented
.grab_all_input::<graphene_std::graphic::extend::BaseInput, graphene_std::list::List<graphene_std::Graphic>>(&editor.runtime)
.map(|base| base.len())
@@ -4341,7 +4341,7 @@ mod document_message_handler_tests {
let phantom_count = news
.iter()
.flat_map(|new| new.iter_element_values())
.filter(|graphic| matches!(graphic, graphene_std::Graphic::None))
.filter(|graphic| matches!(graphic, graphene_std::Graphic::None(_)))
.count();
assert_eq!(phantom_count, 0, "No stacked element should be a phantom None graphic");
}