mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Remove the legacy Fill, Gradient, and PathStyle types now that paints live in attributes (#4297)
* Remove `Stroke.color` * Remove legacy Gradient struct usage * Fix gradient tool tests * Remove `Fill` enum * Fix direction of `gradient_orientation_rightward` * Remove `Gradient` struct * Remove `PathStyle` struct * Fix old `VectorData` migration * Refactor - Remove unnecessary wrapper functions - Use `as_ref` instead of `clone` for stroke if possible - Comment cleanup * Clean up stale style comments and bindings left by the paint attribute migration --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
@@ -13,7 +13,7 @@ use core_types::{
|
||||
};
|
||||
use glam::{DAffine2, DMat2, DVec2};
|
||||
use graphic_types::Vector;
|
||||
use graphic_types::graphic::{bake_paint_transforms, fill_graphic_list_at, has_paint_at, is_paint_present, set_paint_attribute, set_paint_attribute_at, stroke_graphic_list_at};
|
||||
use graphic_types::graphic::{bake_paint_transforms, graphic_list_at, has_paint_at, is_paint_present, set_paint_attribute_at};
|
||||
use graphic_types::raster_types::{CPU, GPU, Raster};
|
||||
use graphic_types::{Graphic, IntoGraphicList};
|
||||
use kurbo::simplify::{SimplifyOptions, simplify_bezpath};
|
||||
@@ -143,7 +143,7 @@ where
|
||||
if fill {
|
||||
set_paint_attribute_at(vector_list, index, ATTR_FILL, paint.clone());
|
||||
}
|
||||
if stroke && vector_list.element(index).and_then(|vector| vector.style.stroke()).is_some() {
|
||||
if stroke && vector_list.element(index).is_some_and(|vector| vector.stroke.is_some()) {
|
||||
set_paint_attribute_at(vector_list, index, ATTR_STROKE, paint.clone());
|
||||
}
|
||||
|
||||
@@ -328,8 +328,6 @@ where
|
||||
let dash_lengths = dash_lengths.into_vec().into_iter().map(|length| length.max(0.)).collect();
|
||||
|
||||
let stroke = Stroke {
|
||||
// TODO: Remove once the deprecated `Stroke.color` field is deleted in favor of the `ATTR_STROKE` attribute
|
||||
color: None,
|
||||
weight,
|
||||
dash_lengths,
|
||||
dash_offset,
|
||||
@@ -344,7 +342,7 @@ where
|
||||
content.for_each_vector_mut(|vector, transform| {
|
||||
let mut stroke = stroke.clone();
|
||||
stroke.transform *= transform;
|
||||
vector.style.set_stroke(stroke);
|
||||
vector.stroke = Some(stroke);
|
||||
});
|
||||
|
||||
let paint = paint.into_graphic_list();
|
||||
@@ -471,7 +469,7 @@ async fn round_corners(
|
||||
let edge_length_limit = edge_length_limit * 0.005;
|
||||
|
||||
let mut result = Vector {
|
||||
style: source.style.clone(),
|
||||
stroke: source.stroke.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -850,7 +848,7 @@ async fn box_warp(_: impl Ctx, content: List<Vector>, #[expose] rectangle: List<
|
||||
});
|
||||
}
|
||||
|
||||
result.style.set_stroke_transform(DAffine2::IDENTITY);
|
||||
result.set_stroke_transform(DAffine2::IDENTITY);
|
||||
|
||||
// Add this to the `List` and reset the transform since we've applied it directly to the points
|
||||
*row.element_mut() = result;
|
||||
@@ -1012,7 +1010,7 @@ async fn auto_tangents(
|
||||
let source = source.element(index).unwrap();
|
||||
|
||||
let mut result = Vector {
|
||||
style: source.style.clone(),
|
||||
stroke: source.stroke.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -1162,8 +1160,8 @@ async fn bounding_box(_: impl Ctx, content: List<Vector>) -> List<Vector> {
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
result.style = vector.style.clone();
|
||||
result.style.set_stroke_transform(DAffine2::IDENTITY);
|
||||
result.stroke = vector.stroke.clone();
|
||||
result.set_stroke_transform(DAffine2::IDENTITY);
|
||||
|
||||
*row.element_mut() = result;
|
||||
row
|
||||
@@ -1226,10 +1224,10 @@ async fn offset_path(_: impl Ctx, content: List<Vector>, distance: f64, join: St
|
||||
|
||||
let bezpaths = vector.stroke_bezpath_iter();
|
||||
let mut result = Vector {
|
||||
style: vector.style.clone(),
|
||||
stroke: vector.stroke.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
result.style.set_stroke_transform(DAffine2::IDENTITY);
|
||||
result.set_stroke_transform(DAffine2::IDENTITY);
|
||||
|
||||
// Perform operation on all subpaths in this shape.
|
||||
for mut bezpath in bezpaths {
|
||||
@@ -1266,10 +1264,8 @@ async fn solidify_stroke<T: IntoGraphicList>(_: impl Ctx, #[implementations(List
|
||||
let graphic_list = content.into_graphic_list();
|
||||
let flattened: List<Vector> = graphic_list.clone().into_flattened_list();
|
||||
|
||||
// A fill exists when the canonical attribute carries paint or, matching the renderer's fallback, when the legacy `style.fill` does
|
||||
let has_fills: Vec<bool> = (0..flattened.len())
|
||||
.map(|index| has_paint_at(&flattened, index, ATTR_FILL) || flattened.element(index).is_some_and(|vector| !vector.style.fill().is_none()))
|
||||
.collect();
|
||||
// A fill exists when the canonical attribute carries paint
|
||||
let has_fills: Vec<bool> = (0..flattened.len()).map(|index| has_paint_at(&flattened, index, ATTR_FILL)).collect();
|
||||
|
||||
let mut output: List<Vector> = flattened
|
||||
.into_iter()
|
||||
@@ -1277,7 +1273,7 @@ async fn solidify_stroke<T: IntoGraphicList>(_: impl Ctx, #[implementations(List
|
||||
.flat_map(|(row, has_fill)| {
|
||||
let (mut vector, attributes) = row.into_parts();
|
||||
|
||||
let stroke = vector.style.stroke().clone().unwrap_or_default();
|
||||
let stroke = vector.stroke.clone().unwrap_or_default();
|
||||
let bezpaths = vector.stroke_bezpath_iter();
|
||||
let mut solidified_stroke = Vector::default();
|
||||
|
||||
@@ -1326,7 +1322,7 @@ async fn solidify_stroke<T: IntoGraphicList>(_: impl Ctx, #[implementations(List
|
||||
|
||||
// If the original vector has a fill, preserve it as a separate item with the stroke cleared.
|
||||
let fill_row = has_fill.then(|| {
|
||||
vector.style.clear_stroke();
|
||||
vector.stroke = None;
|
||||
let mut fill_attributes = attributes.clone();
|
||||
// No stroke remains on the fill row
|
||||
fill_attributes.remove::<List<Graphic>>(ATTR_STROKE);
|
||||
@@ -1338,13 +1334,6 @@ async fn solidify_stroke<T: IntoGraphicList>(_: impl Ctx, #[implementations(List
|
||||
stroke_attributes.remove::<List<Graphic>>(ATTR_FILL);
|
||||
stroke_attributes.rename(ATTR_STROKE, ATTR_FILL);
|
||||
|
||||
// Fall back to the legacy stroke color when no canonical stroke paint attribute was carried over
|
||||
if !stroke_attributes.get::<List<Graphic>>(ATTR_FILL).is_some_and(is_paint_present)
|
||||
&& let Some(color) = stroke.color
|
||||
{
|
||||
set_paint_attribute(&mut stroke_attributes, ATTR_FILL, List::new_from_element(color));
|
||||
}
|
||||
|
||||
let stroke_row = Item::from_parts(solidified_stroke, stroke_attributes);
|
||||
|
||||
// Ordering based on the paint order. The first item in the `List` is rendered below the second.
|
||||
@@ -1389,7 +1378,7 @@ async fn separate_subpaths(_: impl Ctx, content: List<Vector>) -> List<Vector> {
|
||||
return vec![row];
|
||||
}
|
||||
|
||||
let style = row.element().style.clone();
|
||||
let stroke = row.element().stroke.clone();
|
||||
let (_, attributes) = row.into_parts();
|
||||
|
||||
bezpaths
|
||||
@@ -1397,7 +1386,7 @@ async fn separate_subpaths(_: impl Ctx, content: List<Vector>) -> List<Vector> {
|
||||
.map(|bezpath| {
|
||||
let mut vector = Vector::default();
|
||||
vector.append_bezpath(bezpath);
|
||||
vector.style = style.clone();
|
||||
vector.stroke = stroke.clone();
|
||||
|
||||
Item::from_parts(vector, attributes.clone())
|
||||
})
|
||||
@@ -1464,9 +1453,9 @@ pub async fn flatten_path<T: IntoGraphicList>(_: impl Ctx, #[implementations(Lis
|
||||
let source_transform = flattened.attribute_cloned_or_default(ATTR_TRANSFORM, index);
|
||||
output.concat(element, source_transform, collision_hash_seed);
|
||||
|
||||
// TODO: Make this instead use the first encountered style
|
||||
// Use the last encountered style as the output style
|
||||
output.style = element.style.clone();
|
||||
// TODO: Make this instead use the first encountered stroke
|
||||
// Use the last encountered stroke as the output stroke
|
||||
output.stroke = element.stroke.clone();
|
||||
|
||||
primary_source = Some((index, source_transform));
|
||||
}
|
||||
@@ -1532,10 +1521,10 @@ async fn sample_polyline(
|
||||
segment_domain: Default::default(),
|
||||
region_domain: Default::default(),
|
||||
colinear_manipulators: Default::default(),
|
||||
style: std::mem::take(&mut row.element_mut().style),
|
||||
stroke: std::mem::take(&mut row.element_mut().stroke),
|
||||
};
|
||||
// Transfer the stroke transform from the input vector content to the result.
|
||||
result.style.set_stroke_transform(row.attribute_cloned_or_default(ATTR_TRANSFORM));
|
||||
result.set_stroke_transform(row.attribute_cloned_or_default(ATTR_TRANSFORM));
|
||||
|
||||
for local_bezpath in row.element().stroke_bezpath_iter() {
|
||||
// Apply the transform to compute sample locations in world space (for correct distance-based spacing)
|
||||
@@ -1606,7 +1595,7 @@ async fn simplify(
|
||||
let inverse_transform = transform.inverse();
|
||||
|
||||
let mut result = Vector {
|
||||
style: std::mem::take(&mut row.element_mut().style),
|
||||
stroke: std::mem::take(&mut row.element_mut().stroke),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -1702,7 +1691,7 @@ async fn decimate(
|
||||
let inverse_transform = transform.inverse();
|
||||
|
||||
let mut result = Vector {
|
||||
style: std::mem::take(&mut row.element_mut().style),
|
||||
stroke: std::mem::take(&mut row.element_mut().stroke),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -1781,7 +1770,7 @@ async fn cut_path(
|
||||
|
||||
if let Some((row_index, bezpath)) = bezpaths.get(index).cloned() {
|
||||
let mut result_vector = Vector {
|
||||
style: content.element(row_index).unwrap().style.clone(),
|
||||
stroke: content.element(row_index).unwrap().stroke.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -1991,8 +1980,8 @@ async fn scatter_points(
|
||||
}
|
||||
|
||||
// Transfer the style from the input vector content to the result.
|
||||
result.style = row.element().style.clone();
|
||||
result.style.set_stroke_transform(DAffine2::IDENTITY);
|
||||
result.stroke = row.element().stroke.clone();
|
||||
result.set_stroke_transform(DAffine2::IDENTITY);
|
||||
|
||||
*row.element_mut() = result;
|
||||
row
|
||||
@@ -2632,8 +2621,7 @@ async fn morph<I: IntoGraphicList>(
|
||||
return List::new_from_item(Item::from_parts(endpoint_element.clone(), attributes));
|
||||
}
|
||||
|
||||
let mut vector = Vector::default();
|
||||
vector.style.stroke = match (source_element.style.stroke.as_ref(), target_element.style.stroke.as_ref()) {
|
||||
let stroke = match (source_element.stroke.as_ref(), target_element.stroke.as_ref()) {
|
||||
(Some(a), Some(b)) => Some(a.lerp(b, time)),
|
||||
(Some(a), None) => {
|
||||
if time < 0.5 {
|
||||
@@ -2651,15 +2639,16 @@ async fn morph<I: IntoGraphicList>(
|
||||
}
|
||||
(None, None) => None,
|
||||
};
|
||||
let mut vector = Vector { stroke, ..Default::default() };
|
||||
|
||||
let fill_paint = {
|
||||
let source = fill_graphic_list_at(&content, source_index);
|
||||
let target = fill_graphic_list_at(&content, target_index);
|
||||
let source = graphic_list_at(&content, source_index, ATTR_FILL);
|
||||
let target = graphic_list_at(&content, target_index, ATTR_FILL);
|
||||
lerp_graphic(source.as_deref(), target.as_deref(), time)
|
||||
};
|
||||
let stroke_paint = {
|
||||
let source = stroke_graphic_list_at(&content, source_index);
|
||||
let target = stroke_graphic_list_at(&content, target_index);
|
||||
let source = graphic_list_at(&content, source_index, ATTR_STROKE);
|
||||
let target = graphic_list_at(&content, target_index, ATTR_STROKE);
|
||||
lerp_graphic(source.as_deref(), target.as_deref(), time)
|
||||
};
|
||||
|
||||
@@ -3457,7 +3446,7 @@ mod test {
|
||||
|
||||
let morphed = super::morph(Footprint::default(), content, 0.5, false, InterpolationDistribution::default(), List::default()).await;
|
||||
|
||||
let fill = fill_graphic_list_at(&morphed, 0).expect("Morph should keep the fill paint at the midpoint");
|
||||
let fill = graphic_list_at(&morphed, 0, ATTR_FILL).expect("Morph should keep the fill paint at the midpoint");
|
||||
|
||||
// Interpolated color between red and blue should have >0 value on both R and B
|
||||
let Some(Graphic::Color(colors)) = fill.element(0) else {
|
||||
|
||||
Reference in New Issue
Block a user