mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
New node: 'Gradient to Colors' for unwrapping a gradient ramp into its colors (#4425)
* New node: 'Gradient to Colors' for unwrapping a gradient ramp into its colors * Update 'Gradient Midpoints' wording
This commit is contained in:
@@ -1057,12 +1057,18 @@ pub async fn flatten_gradient<T: IntoGraphicList>(_: impl Ctx, #[implementations
|
|||||||
content.into_flattened_list()
|
content.into_flattened_list()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a gradient from a `Color[]`, where the colors are evenly distributed as gradient stops across the range from 0 to 1.
|
/// Constructs a gradient from a `Color[]`, where each color becomes a gradient stop. A `position` attribute on the colors places their stops along the ramp and a `midpoint` attribute skews each transition, while colors carrying neither are distributed evenly across the 0 to 1 range.
|
||||||
#[node_macro::node(category("Gradient"), name("Colors to Gradient"))]
|
#[node_macro::node(category("Gradient"), name("Colors to Gradient"))]
|
||||||
fn colors_to_gradient<T: IntoGraphicList>(_: impl Ctx, #[implementations(List<Graphic>, List<Color>)] colors: T) -> Item<Gradient> {
|
fn colors_to_gradient<T: IntoGraphicList>(_: impl Ctx, #[implementations(List<Graphic>, List<Color>)] colors: T) -> Item<Gradient> {
|
||||||
Item::new_from_element(Gradient::from(colors.into_flattened_list::<Color>()))
|
Item::new_from_element(Gradient::from(colors.into_flattened_list::<Color>()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unwraps a gradient into a `Color[]` of its stops, keeping any `position` and `midpoint` attributes that place them along the ramp. Attributes belonging to the gradient as a whole (like spread and interpolation), rather than its individual color stops, are not preserved.
|
||||||
|
#[node_macro::node(category("Gradient"), name("Gradient to Colors"))]
|
||||||
|
fn gradient_to_colors(_: impl Ctx, gradient: Item<Gradient>) -> List<Color> {
|
||||||
|
gradient.into_element().into_color_list()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -1186,4 +1192,30 @@ mod test {
|
|||||||
let portion = list_slice((), list_of([1., 2., 3., 4., 5.]), Item::new_from_element(3.), Item::new_from_element(3.));
|
let portion = list_slice((), list_of([1., 2., 3., 4., 5.]), Item::new_from_element(3.), Item::new_from_element(3.));
|
||||||
assert!(elements(&portion).is_empty());
|
assert!(elements(&portion).is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gradient_to_colors_round_trips_the_stops_with_their_placement() {
|
||||||
|
let mut gradient = Gradient::from(vec![Color::RED, Color::GREEN, Color::BLUE]);
|
||||||
|
gradient.set_positions(&[0., 0.25, 1.]);
|
||||||
|
gradient.set_midpoints(&[0.3, 0.5, 0.5]);
|
||||||
|
|
||||||
|
let colors = gradient_to_colors((), Item::new_from_element(gradient.clone()));
|
||||||
|
assert_eq!(elements(&colors), [Color::RED, Color::GREEN, Color::BLUE], "every stop should come out as its color");
|
||||||
|
|
||||||
|
let restored = colors_to_gradient((), colors);
|
||||||
|
assert_eq!(
|
||||||
|
restored.element(),
|
||||||
|
&gradient,
|
||||||
|
"wrapping the stops back up should restore the uneven placement rather than redistributing them"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gradient_to_colors_leaves_an_untouched_ramp_without_placement_attributes() {
|
||||||
|
let gradient = Gradient::from(vec![Color::RED, Color::GREEN, Color::BLUE]);
|
||||||
|
assert!(!gradient.has_position_attribute(), "even spacing is stored as the attribute's absence");
|
||||||
|
|
||||||
|
let restored = colors_to_gradient((), gradient_to_colors((), Item::new_from_element(gradient.clone())));
|
||||||
|
assert_eq!(restored.element(), &gradient, "a default ramp should round trip without gaining attributes it never had");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1436,9 +1436,9 @@ fn gradient_positions(_: impl Ctx, gradient: Item<Gradient>, positions: List<f64
|
|||||||
gradient
|
gradient
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the interpolation midpoint for each interval between gradient stops, a factor from 0 to 1 where the 0.5 default means linear interpolation and another value skews the transition speed toward one stop or the other.
|
/// Skews how rapidly the color flows across each interval between color stops, bunching up the transition toward one end instead of progressing uniformly. Each value places the halfway color within its corresponding interval, measured as a fraction of the distance (0 to 1) between the adjacent stops. A 0.5 midpoint keeps a uniform transition rate through the interval.
|
||||||
///
|
///
|
||||||
/// The final stop's midpoint controls the wrap back around to the first stop when the gradient is cyclic, and is otherwise ignored.
|
/// Non-cyclic gradients have no interval following the last stop, meaning the midpoint is ignored in that position.
|
||||||
///
|
///
|
||||||
/// A list shorter than the stop count repeats its last value, a longer list is truncated, and an empty list sets each midpoint to its default of 0.5.
|
/// A list shorter than the stop count repeats its last value, a longer list is truncated, and an empty list sets each midpoint to its default of 0.5.
|
||||||
#[node_macro::node(category("Gradient"))]
|
#[node_macro::node(category("Gradient"))]
|
||||||
|
|||||||
Reference in New Issue
Block a user