Skip to content

Commit 246818d

Browse files
committed
Refactor Vector SVG renderer for Gradient / Color
1 parent 7a02433 commit 246818d

1 file changed

Lines changed: 54 additions & 21 deletions

File tree

node-graph/libraries/rendering/src/render_ext.rs

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,57 @@
11
use crate::renderer::{RenderParams, format_transform_matrix};
2+
use core_types::table::Table;
23
use core_types::uuid::generate_uuid;
3-
use glam::DAffine2;
4-
use graphic_types::vector_types::gradient::{Gradient, GradientType};
4+
use core_types::{ATTR_GRADIENT_TYPE, ATTR_SPREAD_METHOD, ATTR_TRANSFORM, Color};
5+
use glam::{DAffine2, DVec2};
6+
use graphic_types::Graphic;
7+
use graphic_types::graphic::fill_to_paint;
8+
use graphic_types::vector_types::gradient::GradientType;
59
use graphic_types::vector_types::vector::style::{Fill, PaintOrder, PathStyle, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
610
use std::fmt::Write;
11+
use vector_types::GradientStops;
712
use vector_types::gradient::GradientSpreadMethod;
813

914
pub trait RenderExt {
1015
type Output;
1116
fn render(&self, svg_defs: &mut String, element_transform: DAffine2, stroke_transform: DAffine2, bounds: DAffine2, transformed_bounds: DAffine2, render_params: &RenderParams) -> Self::Output;
1217
}
1318

14-
impl RenderExt for Gradient {
19+
impl RenderExt for Table<Color> {
20+
type Output = String;
21+
22+
fn render(
23+
&self,
24+
_svg_defs: &mut String,
25+
_element_transform: DAffine2,
26+
_stroke_transform: DAffine2,
27+
_bounds: DAffine2,
28+
_transformed_bounds: DAffine2,
29+
_render_params: &RenderParams,
30+
) -> Self::Output {
31+
let Some(color) = self.element(0) else { return String::new() };
32+
33+
let mut result = format!(r##" fill="#{}""##, color.to_rgb_hex_srgb_from_gamma());
34+
if color.a() < 1. {
35+
let _ = write!(result, r#" fill-opacity="{}""#, (color.a() * 1000.).round() / 1000.);
36+
}
37+
38+
result
39+
}
40+
}
41+
42+
impl RenderExt for Table<GradientStops> {
1543
type Output = u64;
1644

1745
/// Adds the gradient def through mutating the first argument, returning the gradient ID.
1846
fn render(&self, svg_defs: &mut String, element_transform: DAffine2, stroke_transform: DAffine2, bounds: DAffine2, transformed_bounds: DAffine2, _render_params: &RenderParams) -> Self::Output {
1947
let mut stop = String::new();
20-
for (position, color, original_midpoint) in self.stops.interpolated_samples() {
48+
49+
let Some(stops) = self.element(0) else { return 0 };
50+
let gradient_type: GradientType = self.attribute_cloned_or_default(ATTR_GRADIENT_TYPE, 0);
51+
let gradient_transform: DAffine2 = self.attribute_cloned_or_default(ATTR_TRANSFORM, 0);
52+
let spread_method: GradientSpreadMethod = self.attribute_cloned_or_default(ATTR_SPREAD_METHOD, 0);
53+
54+
for (position, color, original_midpoint) in stops.interpolated_samples() {
2155
stop.push_str("<stop");
2256
if position != 0. {
2357
let _ = write!(stop, r#" offset="{}""#, (position * 1_000_000.).round() / 1_000_000.);
@@ -32,9 +66,9 @@ impl RenderExt for Gradient {
3266
stop.push_str(" />")
3367
}
3468

35-
let transform_points = element_transform * stroke_transform * bounds;
36-
let start = transform_points.transform_point2(self.start);
37-
let end = transform_points.transform_point2(self.end);
69+
let transform_points = element_transform * stroke_transform * bounds * gradient_transform;
70+
let start = transform_points.transform_point2(DVec2::ZERO);
71+
let end = transform_points.transform_point2(DVec2::X);
3872

3973
let gradient_transform = if transformed_bounds.matrix2.determinant() != 0. {
4074
transformed_bounds.inverse()
@@ -48,15 +82,15 @@ impl RenderExt for Gradient {
4882
format!(r#" gradientTransform="{gradient_transform}""#)
4983
};
5084

51-
let spread_method = if self.spread_method == GradientSpreadMethod::Pad {
85+
let spread_method = if spread_method == GradientSpreadMethod::Pad {
5286
String::new()
5387
} else {
54-
format!(r#" spreadMethod="{}""#, self.spread_method.svg_name())
88+
format!(r#" spreadMethod="{}""#, spread_method.svg_name())
5589
};
5690

5791
let gradient_id = generate_uuid();
5892

59-
match self.gradient_type {
93+
match gradient_type {
6094
GradientType::Linear => {
6195
let _ = write!(
6296
svg_defs,
@@ -83,19 +117,18 @@ impl RenderExt for Fill {
83117

84118
/// Renders the fill, adding necessary defs through mutating the first argument.
85119
fn render(&self, svg_defs: &mut String, element_transform: DAffine2, stroke_transform: DAffine2, bounds: DAffine2, transformed_bounds: DAffine2, render_params: &RenderParams) -> Self::Output {
86-
match self {
87-
Self::None => r#" fill="none""#.to_string(),
88-
Self::Solid(color) => {
89-
let mut result = format!(r##" fill="#{}""##, color.to_rgb_hex_srgb_from_gamma());
90-
if color.a() < 1. {
91-
let _ = write!(result, r#" fill-opacity="{}""#, (color.a() * 1000.).round() / 1000.);
92-
}
93-
result
94-
}
95-
Self::Gradient(gradient) => {
96-
let gradient_id = gradient.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params);
120+
let Some(paint_table) = fill_to_paint(self) else { return r#" fill="none""#.to_string() };
121+
let Some(paint) = paint_table.element(0) else { return String::new() };
122+
123+
match paint {
124+
Graphic::Color(color_table) => color_table.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params),
125+
Graphic::Gradient(stops_table) => {
126+
let gradient_id = stops_table.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params);
97127
format!(r##" fill="url('#{gradient_id}')""##)
98128
}
129+
_ => {
130+
todo!()
131+
}
99132
}
100133
}
101134
}

0 commit comments

Comments
 (0)