Skip to content

Commit b216cbd

Browse files
committed
Add conversion from Fill to Table<Graphic>
1 parent 269a217 commit b216cbd

2 files changed

Lines changed: 50 additions & 1 deletion

File tree

node-graph/libraries/graphic-types/src/graphic.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ use core_types::ops::TableConvert;
55
use core_types::render_complexity::RenderComplexity;
66
use core_types::table::{Table, TableRow};
77
use core_types::uuid::NodeId;
8-
use core_types::{ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_TRANSFORM, Color};
8+
use core_types::{ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_GRADIENT_TYPE, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_SPREAD_METHOD, ATTR_TRANSFORM, Color};
99
use dyn_any::DynAny;
1010
use glam::DAffine2;
1111
use raster_types::{CPU, GPU, Raster};
1212
use vector_types::GradientStops;
1313
// use vector_types::Vector;
1414

1515
pub use vector_types::Vector;
16+
use vector_types::vector::style::Fill;
1617

1718
/// The possible forms of graphical content that can be rendered by the Render node into either an image or SVG syntax.
1819
#[derive(Clone, Debug, CacheHash, PartialEq, DynAny)]
@@ -193,6 +194,24 @@ fn flatten_graphic_table<T>(content: Table<Graphic>, extract_variant: fn(Graphic
193194
output
194195
}
195196

197+
/// Converts a `Fill` enum into the `Table<Graphic>` representation used as paint storage.
198+
/// TODO: Remove once all paint sources flow through `Table<Graphic>` directly without going through the `Fill` enum.
199+
pub fn fill_to_paint(fill: &Fill) -> Option<Table<Graphic>> {
200+
match fill {
201+
Fill::None => None,
202+
Fill::Solid(color) => Some(Table::new_from_element((*color).into())),
203+
Fill::Gradient(gradient) => {
204+
let gradient_row = TableRow::new_from_element(gradient.stops.clone())
205+
.with_attribute(ATTR_TRANSFORM, gradient.to_transform())
206+
.with_attribute(ATTR_GRADIENT_TYPE, gradient.gradient_type)
207+
.with_attribute(ATTR_SPREAD_METHOD, gradient.spread_method);
208+
let gradient_table = Table::new_from_row(gradient_row);
209+
210+
Some(Table::new_from_element(Graphic::Gradient(gradient_table)))
211+
}
212+
}
213+
}
214+
196215
/// Maps from a concrete element type to its corresponding `Graphic` enum variant,
197216
/// enabling type-directed casting of typed `Table`s from a `Graphic` value.
198217
pub trait TryFromGraphic: Clone + Sized {

node-graph/libraries/vector-types/src/gradient.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,12 @@ impl Gradient {
523523

524524
Some(index)
525525
}
526+
527+
/// Builds the affine that places the gradient endpoints at `start` and `end` when applied to canonical gradient space (0,0) -> (1,0)
528+
pub fn to_transform(&self) -> DAffine2 {
529+
let direction = self.end - self.start;
530+
DAffine2::from_cols(direction, direction.perp(), self.start)
531+
}
526532
}
527533

528534
// TODO: Eventually remove this migration document upgrade code
@@ -556,3 +562,27 @@ impl core_types::bounds::BoundingBox for GradientStops {
556562
core_types::bounds::RenderBoundingBox::Rectangle([start.min(end), start.max(end)])
557563
}
558564
}
565+
566+
#[cfg(test)]
567+
mod tests {
568+
use super::*;
569+
use glam::DVec2;
570+
571+
fn linear_gradient(start: DVec2, end: DVec2) -> Gradient {
572+
Gradient { start, end, ..Default::default() }
573+
}
574+
575+
#[test]
576+
fn to_transform_roundtrip() {
577+
let cases = [(DVec2::ZERO, DVec2::X), (DVec2::new(10., 20.), DVec2::new(50., 30.)), (DVec2::new(-5., -5.), DVec2::new(5., 3.))];
578+
579+
for (start, end) in cases {
580+
let transform = linear_gradient(start, end).to_transform();
581+
let recovered_start = transform.transform_point2(DVec2::ZERO);
582+
let recovered_end = transform.transform_point2(DVec2::X);
583+
584+
assert!((recovered_start - start).length() < 1e-10);
585+
assert!((recovered_end - end).length() < 1e-10);
586+
}
587+
}
588+
}

0 commit comments

Comments
 (0)