Rename spread method to gradient spread so it matches the other gradient attribute names (#4404)

* Rename spread method to gradient spread so it matches the other gradient attribute names

* Keep the legacy gradient struct's spread method field name matching its on-disk key
This commit is contained in:
Keavon Chambers
2026-08-04 05:15:21 -07:00
committed by Dennis Kobert
parent c2f27bf743
commit 51ab692df3
23 changed files with 237 additions and 232 deletions

View File

@@ -637,7 +637,8 @@ tagged_value! {
StrokeAlign(vector::style::StrokeAlign),
PaintOrder(vector::style::PaintOrder),
GradientType(vector::style::GradientType),
GradientSpreadMethod(vector::style::GradientSpreadMethod),
#[serde(alias = "GradientSpreadMethod")] // TODO: Eventually remove this document upgrade code
GradientSpread(vector::style::GradientSpread),
ReferencePoint(vector::ReferencePoint),
CentroidType(vector::misc::CentroidType),
BooleanOperation(vector::misc::BooleanOperation),
@@ -1112,7 +1113,7 @@ mod paint_default_parsing {
#[cfg(test)]
mod gradient_shape_migration {
use graphic_types::vector_types::GradientSpreadMethod;
use graphic_types::vector_types::GradientSpread;
use super::*;
@@ -1133,7 +1134,7 @@ mod gradient_shape_migration {
let mut gradient = Gradient::from(vec![Color::BLACK, Color::WHITE]);
gradient.set_positions(&[0.2, 0.9]);
let value = TaggedValue::GradientRamp(GradientRamp {
spread_method: GradientSpreadMethod::Reflect,
gradient_spread: GradientSpread::Reflect,
..GradientRamp::from(gradient)
});

View File

@@ -1161,7 +1161,7 @@ impl<T: CacheHash> CacheHash for List<T> {
self.element.cache_hash(state);
// Hash every attribute attribute (key + values) rather than just the well-known ones, so changes to user-defined keys
// (e.g., gradient_type, spread_method) invalidate downstream graph caches as expected
// (e.g., gradient_type, gradient_spread) invalidate downstream graph caches as expected
for (key, attribute) in &self.attributes.attributes {
std::hash::Hash::hash(key.as_str(), state);
attribute.cache_hash_dyn(state);

View File

@@ -36,7 +36,7 @@ pub mod migrations {
pub start: DVec2,
pub end: DVec2,
#[serde(default)]
pub spread_method: vector::style::GradientSpreadMethod,
pub spread_method: vector::style::GradientSpread,
#[serde(default)]
pub absolute: bool,
#[serde(default)]

View File

@@ -8,11 +8,11 @@ use core_types::uuid::generate_uuid;
use glam::{DAffine2, DVec2};
use graphic_types::Graphic;
use graphic_types::vector_types::gradient::GradientType;
use graphic_types::vector_types::markers::{GradientType as GradientTypeAttr, SpreadMethod};
use graphic_types::vector_types::markers::{GradientSpread as GradientSpreadAttr, GradientType as GradientTypeAttr};
use graphic_types::vector_types::vector::style::{PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
use std::fmt::Write;
use vector_types::Gradient;
use vector_types::gradient::GradientSpreadMethod;
use vector_types::gradient::GradientSpread;
#[derive(Copy, Clone, PartialEq)]
pub enum PaintTarget {
@@ -110,7 +110,7 @@ pub fn render_gradient_paint<S: core_types::lane::LaneSource<Element = Gradient>
let Some(stops) = source.element(0) else { return 0 };
let gradient_type: GradientType = source.attr::<GradientTypeAttr>(0);
let local_gradient_transform: DAffine2 = source.attr::<Transform>(0);
let spread_method: GradientSpreadMethod = source.attr::<SpreadMethod>(0);
let gradient_spread: GradientSpread = source.attr::<GradientSpreadAttr>(0);
for (position, color, original_midpoint) in stops.interpolated_samples() {
stop.push_str("<stop");
@@ -149,10 +149,10 @@ pub fn render_gradient_paint<S: core_types::lane::LaneSource<Element = Gradient>
format!(r#" gradientTransform="{gradient_transform}""#)
};
let spread_method = if spread_method == GradientSpreadMethod::Pad {
let gradient_spread = if gradient_spread == GradientSpread::Pad {
String::new()
} else {
format!(r#" spreadMethod="{}""#, spread_method.svg_name())
format!(r#" spreadMethod="{}""#, gradient_spread.svg_name())
};
let gradient_id = generate_uuid();
@@ -161,14 +161,14 @@ pub fn render_gradient_paint<S: core_types::lane::LaneSource<Element = Gradient>
GradientType::Linear => {
let _ = write!(
svg_defs,
r#"<linearGradient id="{}" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="1" y2="0"{spread_method}{gradient_transform}>{}</linearGradient>"#,
r#"<linearGradient id="{}" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="1" y2="0"{gradient_spread}{gradient_transform}>{}</linearGradient>"#,
gradient_id, stop
);
}
GradientType::Radial => {
let _ = write!(
svg_defs,
r#"<radialGradient id="{}" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1"{spread_method}{gradient_transform}>{}</radialGradient>"#,
r#"<radialGradient id="{}" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1"{gradient_spread}{gradient_transform}>{}</radialGradient>"#,
gradient_id, stop
);
}

View File

@@ -27,7 +27,7 @@ use graphic_types::graphic::{PaintColumns, PaintOverlay, PaintReach, has_paint,
use graphic_types::markers::{EditorMergedLayers, Fill, Stroke};
use graphic_types::raster_types::{BitmapMut, CPU, GPU, Image, Raster, Texture};
use graphic_types::vector_types::gradient::{Gradient, GradientType};
use graphic_types::vector_types::markers::{GradientType as GradientTypeAttr, SpreadMethod};
use graphic_types::vector_types::markers::{GradientSpread as GradientSpreadAttr, GradientType as GradientTypeAttr};
use graphic_types::vector_types::subpath::Subpath;
use graphic_types::vector_types::vector::click_target::{ClickTarget, FreePoint};
use graphic_types::vector_types::vector::style::{PaintOrder, RenderMode, StrokeAlign, StrokeCap, StrokeJoin};
@@ -44,7 +44,7 @@ use std::hash::Hash;
use std::ops::Deref;
use std::sync::{Arc, LazyLock};
use text_nodes::markers::{Font, TextAlign};
use vector_types::gradient::GradientSpreadMethod;
use vector_types::gradient::GradientSpread;
use vector_types::markers::EditorClickTarget;
use vello::*;
@@ -430,7 +430,7 @@ fn create_peniko_gradient_brush<S: LaneSource<Element = Gradient>>(gradient_list
let gradient_type: GradientType = gradient_list.attr::<GradientTypeAttr>(0);
let gradient_transform: DAffine2 = gradient_list.attr::<Transform>(0);
let spread_method: GradientSpreadMethod = gradient_list.attr::<SpreadMethod>(0);
let gradient_spread: GradientSpread = gradient_list.attr::<GradientSpreadAttr>(0);
let peniko_stops = peniko_color_stops(stops);
@@ -452,10 +452,10 @@ fn create_peniko_gradient_brush<S: LaneSource<Element = Gradient>>(gradient_list
}
.into(),
},
extend: match spread_method {
GradientSpreadMethod::Pad => peniko::Extend::Pad,
GradientSpreadMethod::Reflect => peniko::Extend::Reflect,
GradientSpreadMethod::Repeat => peniko::Extend::Repeat,
extend: match gradient_spread {
GradientSpread::Pad => peniko::Extend::Pad,
GradientSpread::Reflect => peniko::Extend::Reflect,
GradientSpread::Repeat => peniko::Extend::Repeat,
},
stops: peniko_stops,
interpolation_alpha_space: peniko::InterpolationAlphaSpace::Premultiplied,
@@ -2327,7 +2327,7 @@ fn render_gradient_svg<S: LaneSource<Element = Gradient>>(source: &S, render: &m
let blend_mode: BlendMode = source.attr::<BlendModeAttr>(index);
let opacity_attr: f64 = source.attr::<Opacity>(index);
let opacity_fill_attr: f64 = source.attr::<OpacityFill>(index);
let spread_method: GradientSpreadMethod = source.attr::<SpreadMethod>(index);
let gradient_spread: GradientSpread = source.attr::<GradientSpreadAttr>(index);
let gradient_type: GradientType = source.attr::<GradientTypeAttr>(index);
let tag = if thumbnail_rect.is_some() { "rect" } else { "polyline" };
render.leaf_tag(tag, |attributes| {
@@ -2366,10 +2366,10 @@ fn render_gradient_svg<S: LaneSource<Element = Gradient>>(source: &S, render: &m
};
let gradient_id = generate_uuid();
let spread_method_attribute = if spread_method == GradientSpreadMethod::Pad {
let spread_method_attribute = if gradient_spread == GradientSpread::Pad {
String::new()
} else {
format!(r#" spreadMethod="{}""#, spread_method.svg_name())
format!(r#" spreadMethod="{}""#, gradient_spread.svg_name())
};
// The unit gradient line is the +X unit vector in local space, before the item's transform is applied
@@ -2411,7 +2411,7 @@ fn render_gradient_vello<S: LaneSource<Element = Gradient>>(source: &S, scene: &
for index in 0..source.lane_count() {
let Some(gradient) = source.element(index) else { continue };
let spread_method: GradientSpreadMethod = source.attr::<SpreadMethod>(index);
let gradient_spread: GradientSpread = source.attr::<GradientSpreadAttr>(index);
let gradient_type: GradientType = source.attr::<GradientTypeAttr>(index);
let transform: DAffine2 = source.attr::<Transform>(index);
let blend_mode_attr: BlendMode = source.attr::<BlendModeAttr>(index);
@@ -2424,10 +2424,10 @@ fn render_gradient_vello<S: LaneSource<Element = Gradient>>(source: &S, scene: &
let stops = peniko_color_stops(gradient);
let extend = match spread_method {
GradientSpreadMethod::Pad => peniko::Extend::Pad,
GradientSpreadMethod::Reflect => peniko::Extend::Reflect,
GradientSpreadMethod::Repeat => peniko::Extend::Repeat,
let extend = match gradient_spread {
GradientSpread::Pad => peniko::Extend::Pad,
GradientSpread::Reflect => peniko::Extend::Reflect,
GradientSpread::Repeat => peniko::Extend::Repeat,
};
// The unit gradient line is the +X unit vector in local space, before the item's transform is applied.

View File

@@ -1,4 +1,4 @@
use crate::ATTR_SPREAD_METHOD;
use crate::markers::ATTR_GRADIENT_SPREAD;
use core_types::Color;
use core_types::color::SRGBA8;
use core_types::list::{ATTR_MIDPOINT, ATTR_POSITION, Item, List};
@@ -103,9 +103,9 @@ impl GradientStops<SRGBA8> {
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct GradientRamp<C = Color> {
pub stops: GradientStops<C>,
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "GradientSpreadMethod::is_default"))]
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "GradientSpread::is_default"))]
#[cfg_attr(feature = "wasm", tsify(optional))]
pub spread_method: GradientSpreadMethod,
pub gradient_spread: GradientSpread,
}
unsafe impl<C: dyn_any::StaticTypeSized> dyn_any::StaticType for GradientRamp<C> {
@@ -116,7 +116,7 @@ impl<C> From<GradientStops<C>> for GradientRamp<C> {
fn from(stops: GradientStops<C>) -> Self {
Self {
stops,
spread_method: Default::default(),
gradient_spread: Default::default(),
}
}
}
@@ -125,7 +125,7 @@ impl From<&Gradient> for GradientRamp {
fn from(gradient: &Gradient) -> Self {
Self {
stops: gradient.into(),
spread_method: Default::default(),
gradient_spread: Default::default(),
}
}
}
@@ -153,8 +153,8 @@ impl From<&GradientRamp> for Gradient {
impl From<GradientRamp> for Item<Gradient> {
fn from(ramp: GradientRamp) -> Self {
let mut item = Item::new_from_element(Gradient::from(ramp.stops));
if !ramp.spread_method.is_default() {
item.set_attribute(ATTR_SPREAD_METHOD, ramp.spread_method);
if !ramp.gradient_spread.is_default() {
item.set_attribute(ATTR_GRADIENT_SPREAD, ramp.gradient_spread);
}
item
}
@@ -164,7 +164,7 @@ impl From<&Item<Gradient>> for GradientRamp {
fn from(item: &Item<Gradient>) -> Self {
Self {
stops: item.element().into(),
spread_method: item.attribute_cloned_or_default(ATTR_SPREAD_METHOD),
gradient_spread: item.attribute_cloned_or_default(ATTR_GRADIENT_SPREAD),
}
}
}
@@ -190,7 +190,7 @@ impl From<&GradientRamp> for GradientRamp<SRGBA8> {
fn from(ramp: &GradientRamp) -> Self {
Self {
stops: ramp.into(),
spread_method: ramp.spread_method,
gradient_spread: ramp.gradient_spread,
}
}
}
@@ -199,7 +199,7 @@ impl From<&Gradient> for GradientRamp<SRGBA8> {
fn from(gradient: &Gradient) -> Self {
Self {
stops: gradient.into(),
spread_method: Default::default(),
gradient_spread: Default::default(),
}
}
}
@@ -207,7 +207,7 @@ impl From<&Gradient> for GradientRamp<SRGBA8> {
impl From<&GradientRamp<SRGBA8>> for GradientRamp {
fn from(ramp: &GradientRamp<SRGBA8>) -> Self {
Self {
spread_method: ramp.spread_method,
gradient_spread: ramp.gradient_spread,
..Self::from(&ramp.stops)
}
}
@@ -601,12 +601,12 @@ impl Gradient {
stops
}
/// Samples the gradient's color at `t`. Given a `t` outside the 0 to 1 range, the `spread_method` determines how the gradient extends.
pub fn evaluate(&self, t: f64, spread_method: GradientSpreadMethod) -> Color {
let t = match spread_method {
GradientSpreadMethod::Pad => t.clamp(0., 1.),
GradientSpreadMethod::Repeat => t.rem_euclid(1.),
GradientSpreadMethod::Reflect => {
/// Samples the gradient's color at `t`. Given a `t` outside the 0 to 1 range, the `gradient_spread` determines how the gradient extends.
pub fn evaluate(&self, t: f64, gradient_spread: GradientSpread) -> Color {
let t = match gradient_spread {
GradientSpread::Pad => t.clamp(0., 1.),
GradientSpread::Repeat => t.rem_euclid(1.),
GradientSpread::Reflect => {
let cycle = t.rem_euclid(2.);
if cycle > 1. { 2. - cycle } else { cycle }
}
@@ -785,7 +785,7 @@ impl Gradient {
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, Hash, graphene_hash::CacheHash, DynAny, node_macro::ChoiceType)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[widget(Radio)]
pub enum GradientSpreadMethod {
pub enum GradientSpread {
/// Extends the end colors outward.
#[default]
Pad,
@@ -796,12 +796,12 @@ pub enum GradientSpreadMethod {
// TODO: Add a "Clear" variant that returns transparent black outside the gradient's range
}
impl GradientSpreadMethod {
impl GradientSpread {
pub fn svg_name(&self) -> &'static str {
match self {
GradientSpreadMethod::Pad => "pad",
GradientSpreadMethod::Reflect => "reflect",
GradientSpreadMethod::Repeat => "repeat",
GradientSpread::Pad => "pad",
GradientSpread::Reflect => "reflect",
GradientSpread::Repeat => "repeat",
}
}
@@ -906,39 +906,39 @@ mod tests {
}
#[test]
fn spread_method_serializes_only_when_not_default() {
fn gradient_spread_serializes_only_when_not_default() {
let default_spread = GradientRamp::from(Gradient::from(vec![Color::BLACK, Color::WHITE]));
let json = serde_json::to_string(&default_spread).unwrap();
assert!(!json.contains("spread_method"), "the default Pad spread method must not serialize: {json}");
assert!(!json.contains("gradient_spread"), "the default Pad gradient spread must not serialize: {json}");
assert_eq!(serde_json::from_str::<GradientRamp>(&json).unwrap(), default_spread);
let repeating = GradientRamp {
spread_method: GradientSpreadMethod::Repeat,
gradient_spread: GradientSpread::Repeat,
..default_spread.clone()
};
let json = serde_json::to_string(&repeating).unwrap();
assert!(json.contains(r#""spread_method":"Repeat""#), "a non-default spread method must serialize: {json}");
assert!(json.contains(r#""gradient_spread":"Repeat""#), "a non-default gradient spread must serialize: {json}");
assert_eq!(serde_json::from_str::<GradientRamp>(&json).unwrap(), repeating);
}
#[test]
fn spread_method_round_trips_through_the_item_attribute() {
fn gradient_spread_round_trips_through_the_item_attribute() {
let ramp = GradientRamp {
spread_method: GradientSpreadMethod::Repeat,
gradient_spread: GradientSpread::Repeat,
..GradientRamp::from(Gradient::from(vec![Color::BLACK, Color::WHITE]))
};
let item = Item::<Gradient>::from(ramp.clone());
assert_eq!(
item.attribute_cloned_or_default::<GradientSpreadMethod>(ATTR_SPREAD_METHOD),
GradientSpreadMethod::Repeat,
"the runtime item should carry the spread method as its attribute"
item.attribute_cloned_or_default::<GradientSpread>(ATTR_GRADIENT_SPREAD),
GradientSpread::Repeat,
"the runtime item should carry the gradient spread as its attribute"
);
assert_eq!(GradientRamp::from(&item), ramp);
let padded = Item::<Gradient>::from(GradientRamp::from(Gradient::from(vec![Color::BLACK, Color::WHITE])));
assert!(
padded.attribute::<GradientSpreadMethod>(ATTR_SPREAD_METHOD).is_none(),
padded.attribute::<GradientSpread>(ATTR_GRADIENT_SPREAD).is_none(),
"the default Pad must stay absent rather than materialize"
);
}

View File

@@ -9,8 +9,8 @@ pub mod vector;
// Re-export commonly used types at the crate root
pub use core_types as gcore;
pub use gradient::{Gradient, GradientRamp, GradientSpreadMethod, GradientStop, GradientType};
pub use markers::{ATTR_EDITOR_CLICK_TARGET, ATTR_GRADIENT_TYPE, ATTR_SPREAD_METHOD};
pub use gradient::{Gradient, GradientRamp, GradientSpread, GradientStop, GradientType};
pub use markers::{ATTR_EDITOR_CLICK_TARGET, ATTR_GRADIENT_SPREAD, ATTR_GRADIENT_TYPE};
pub use math::{QuadExt, RectExt};
pub use subpath::Subpath;
pub use vector::Vector;

View File

@@ -5,7 +5,7 @@ use core_types::attribute::Attribute;
core_types::attribute! {
/// Gradient's spread behavior past its endpoints (`Pad`, `Reflect`, or `Repeat`).
pub SpreadMethod("spread_method"): crate::gradient::GradientSpreadMethod;
pub GradientSpread("gradient_spread"): crate::gradient::GradientSpread;
/// Gradient's shape (`Linear` or `Radial`).
pub GradientType("gradient_type"): crate::gradient::GradientType;
/// Optional `Vector` that overrides the item's own geometry for click-target generation.
@@ -18,11 +18,11 @@ core_types::attribute! {
// The value types a name-generic attribute can name here, so a compile-time
// named write or read reaches this crate's enums like any other plain value.
core_types::named_value! {
for crate::gradient::GradientSpreadMethod;
for crate::gradient::GradientSpread;
for crate::gradient::GradientType;
}
pub const ATTR_SPREAD_METHOD: &str = SpreadMethod::NAME;
pub const ATTR_GRADIENT_SPREAD: &str = GradientSpread::NAME;
pub const ATTR_GRADIENT_TYPE: &str = GradientType::NAME;
pub const ATTR_EDITOR_CLICK_TARGET: &str = EditorClickTarget::NAME;
@@ -35,7 +35,7 @@ mod tests {
#[test]
fn the_census_carries_this_crates_names() {
assert_eq!(info("gradient_type").unwrap().value_type, TypeId::of::<crate::gradient::GradientType>());
assert_eq!(info("spread_method").unwrap().value_type, TypeId::of::<crate::gradient::GradientSpreadMethod>());
assert_eq!(info("gradient_spread").unwrap().value_type, TypeId::of::<crate::gradient::GradientSpread>());
assert_eq!(info("editor:click_target").unwrap().value_type, TypeId::of::<Option<&'static crate::Vector>>());
}

View File

@@ -14,7 +14,7 @@ use rand::seq::SliceRandom;
use raster_types::{CPU, GPU, Raster};
use std::cmp::Ordering;
use vector_types::gradient::{GradientSpreadMethod, GradientType as GradientTypeValue};
use vector_types::gradient::{GradientSpread, GradientType as GradientTypeValue};
use vector_types::{Gradient, ReferencePoint};
/// Resolves a signed index over `total` lanes: negatives count from the end,
@@ -723,8 +723,8 @@ attribute_reads! {
read_blend_mode_attribute: core_types::blending::BlendMode => core_types::blending::BlendMode;
/// Reads a named gradient-shape attribute, such as `gradient_type`.
read_gradient_type_attribute: GradientTypeValue => GradientTypeValue;
/// Reads a named gradient-spread attribute, such as `spread_method`.
read_spread_method_attribute: GradientSpreadMethod => GradientSpreadMethod;
/// Reads a named gradient-spread attribute, such as `gradient_spread`.
read_gradient_spread_attribute: GradientSpread => GradientSpread;
}
/// Joins two levels of the same type, the base's lanes followed by the new's.

View File

@@ -12,7 +12,7 @@ use math_parser::value::{Number, Value};
use rand::{Rng, SeedableRng};
use std::ops::{Add, Mul, Rem, Sub};
use vector_types::Gradient;
use vector_types::markers::{GradientType as GradientTypeAttr, SpreadMethod as SpreadMethodAttr};
use vector_types::markers::{GradientSpread as GradientSpreadAttr, GradientType as GradientTypeAttr};
/// The struct that stores the context for the maths parser.
/// This is currently just limited to supplying `a` and `b` until we add better node graph support and UI for variadic inputs.
@@ -1211,8 +1211,8 @@ fn gradient_type(_: impl Ctx, gradient: Gradient, gradient_type: vector_types::G
/// Sets how each gradient in the input list extends past its endpoints: Pad, Reflect, or Repeat.
#[node_macro::node(category("Gradient"))]
fn spread_method(_: impl Ctx, gradient: Gradient, spread_method: vector_types::GradientSpreadMethod) -> (Gradient, Attr<SpreadMethodAttr>) {
(gradient, Attr(spread_method))
fn gradient_spread(_: impl Ctx, gradient: Gradient, gradient_spread: vector_types::GradientSpread) -> (Gradient, Attr<GradientSpreadAttr>) {
(gradient, Attr(gradient_spread))
}
/// Sets the position of each of a gradient's stops, a factor from 0 to 1 along the gradient.
@@ -1237,7 +1237,7 @@ fn gradient_midpoints(_: impl Ctx, mut gradient: Gradient, midpoints: List<f64>)
gradient
}
/// Evaluates the color at the specified position along the gradient, given a position from 0 (left) to 1 (right). Positions beyond that range follow the gradient's `spread_method` attribute: Pad (default), Reflect, or Repeat.
/// Evaluates the color at the specified position along the gradient, given a position from 0 (left) to 1 (right). Positions beyond that range follow the gradient's `gradient_spread` attribute: Pad (default), Reflect, or Repeat.
#[node_macro::node(category("Color"))]
fn sample_gradient(
ctx: impl Ctx + ExtractIndex + InjectIndex + Copy,
@@ -1250,7 +1250,7 @@ fn sample_gradient(
return Err(GraphError::past_end().into());
}
let spread_method = gradient.lane(0).attr::<SpreadMethodAttr>();
let spread_method = gradient.lane(0).attr::<GradientSpreadAttr>();
Ok(gradient.element_ref(0).evaluate(position, spread_method))
}

View File

@@ -7,11 +7,11 @@ use graphic_types::graphic::{GraphicLevel, PaintColumns, PaintReach, bake_paint_
use graphic_types::markers::{EditorMergedLayers, Fill, Stroke};
use graphic_types::raster_types::{CPU, GPU, Raster};
use graphic_types::vector_types::Gradient;
use graphic_types::vector_types::gradient::{GradientSpreadMethod, GradientType};
use graphic_types::vector_types::gradient::{GradientSpread, GradientType};
use graphic_types::vector_types::subpath::{ManipulatorGroup, Subpath};
use graphic_types::vector_types::vector::PointId;
use graphic_types::vector_types::vector::algorithms::merge_by_distance::MergeByDistanceExt;
use graphic_types::vector_types::{ATTR_GRADIENT_TYPE, ATTR_SPREAD_METHOD};
use graphic_types::vector_types::{ATTR_GRADIENT_SPREAD, ATTR_GRADIENT_TYPE};
use graphic_types::{ATTR_FILL, ATTR_STROKE, Graphic, IntoGraphicList, Vector};
use linesweeper::topology::Topology;
use linesweeper::{BinaryOp, FillRule, binary_op};
@@ -327,8 +327,8 @@ fn gradient_paint_row(stops: Gradient, mut attributes: core_types::list::ItemAtt
if let Some(gradient_type) = attributes.remove::<GradientType>(ATTR_GRADIENT_TYPE) {
gradient_paint.set_attribute(ATTR_GRADIENT_TYPE, 0, gradient_type);
}
if let Some(spread_method) = attributes.remove::<GradientSpreadMethod>(ATTR_SPREAD_METHOD) {
gradient_paint.set_attribute(ATTR_SPREAD_METHOD, 0, spread_method);
if let Some(spread_method) = attributes.remove::<GradientSpread>(ATTR_GRADIENT_SPREAD) {
gradient_paint.set_attribute(ATTR_GRADIENT_SPREAD, 0, spread_method);
}
attributes.insert(ATTR_FILL, Some(gradient_paint));

View File

@@ -23,13 +23,13 @@ fn gradient_map<T: Adjust<Color> + Clone + Send + Sync + core_types::CacheHash +
if gradient.is_empty() {
return image;
}
let spread_method = gradient.lane(0).attr::<vector_types::markers::SpreadMethod>();
let gradient_spread = gradient.lane(0).attr::<vector_types::markers::GradientSpread>();
let gradient = gradient.element_ref(0);
image.adjust(|color| {
let intensity = color.luminance_rec_709();
let intensity = if reverse { 1. - intensity } else { intensity };
gradient.evaluate(intensity as f64, spread_method)
gradient.evaluate(intensity as f64, gradient_spread)
});
image