Add conversion from Fill to Table<Graphic>

This commit is contained in:
YohYamasaki
2026-05-06 17:19:57 +09:00
parent 21d2994059
commit e192269481
2 changed files with 50 additions and 1 deletions

View File

@@ -4,7 +4,7 @@ use core_types::list::List;
use core_types::ops::ListConvert;
use core_types::render_complexity::RenderComplexity;
use core_types::uuid::NodeId;
use core_types::{ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_TRANSFORM, Color};
use core_types::{ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_GRADIENT_TYPE, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_SPREAD_METHOD, ATTR_TRANSFORM, Color};
use dyn_any::DynAny;
use glam::DAffine2;
use raster_types::{CPU, GPU, Raster};
@@ -12,6 +12,7 @@ use vector_types::GradientStops;
// use vector_types::Vector;
pub use vector_types::Vector;
use vector_types::vector::style::Fill;
/// The possible forms of graphical content that can be rendered by the Render node into either an image or SVG syntax.
#[derive(Clone, Debug, CacheHash, PartialEq, DynAny)]
@@ -169,6 +170,24 @@ fn flatten_graphic_list<T>(content: List<Graphic>, extract_variant: fn(Graphic)
output
}
/// Converts a `Fill` enum into the `Table<Graphic>` representation used as paint storage.
/// TODO: Remove once all paint sources flow through `Table<Graphic>` directly without going through the `Fill` enum.
pub fn fill_to_paint(fill: &Fill) -> Option<Table<Graphic>> {
match fill {
Fill::None => None,
Fill::Solid(color) => Some(Table::new_from_element((*color).into())),
Fill::Gradient(gradient) => {
let gradient_row = TableRow::new_from_element(gradient.stops.clone())
.with_attribute(ATTR_TRANSFORM, gradient.to_transform())
.with_attribute(ATTR_GRADIENT_TYPE, gradient.gradient_type)
.with_attribute(ATTR_SPREAD_METHOD, gradient.spread_method);
let gradient_table = Table::new_from_row(gradient_row);
Some(Table::new_from_element(Graphic::Gradient(gradient_table)))
}
}
}
/// Maps from a concrete element type to its corresponding `Graphic` enum variant,
/// enabling type-directed casting of typed `List`s from a `Graphic` value.
pub trait TryFromGraphic: Clone + Sized {

View File

@@ -587,6 +587,12 @@ impl Gradient {
Some(index)
}
/// Builds the affine that places the gradient endpoints at `start` and `end` when applied to canonical gradient space (0,0) -> (1,0)
pub fn to_transform(&self) -> DAffine2 {
let direction = self.end - self.start;
DAffine2::from_cols(direction, direction.perp(), self.start)
}
}
// TODO: Eventually remove this migration document upgrade code
@@ -625,3 +631,27 @@ impl core_types::bounds::BoundingBox for GradientStops {
core_types::bounds::RenderBoundingBox::Rectangle([start.min(end), start.max(end)])
}
}
#[cfg(test)]
mod tests {
use super::*;
use glam::DVec2;
fn linear_gradient(start: DVec2, end: DVec2) -> Gradient {
Gradient { start, end, ..Default::default() }
}
#[test]
fn to_transform_roundtrip() {
let cases = [(DVec2::ZERO, DVec2::X), (DVec2::new(10., 20.), DVec2::new(50., 30.)), (DVec2::new(-5., -5.), DVec2::new(5., 3.))];
for (start, end) in cases {
let transform = linear_gradient(start, end).to_transform();
let recovered_start = transform.transform_point2(DVec2::ZERO);
let recovered_end = transform.transform_point2(DVec2::X);
assert!((recovered_start - start).length() < 1e-10);
assert!((recovered_end - end).length() < 1e-10);
}
}
}