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:
YohYamasaki
2026-07-05 08:08:06 +02:00
committed by GitHub
parent 9f9899cfd0
commit 6a54dcb5da
28 changed files with 887 additions and 1334 deletions

View File

@@ -13,7 +13,7 @@ pub use dyn_any::StaticType;
pub use glam::{DAffine2, DVec2, IVec2, UVec2};
use graphene_application_io::resource::ResourceHash;
use graphic_types::raster_types::{CPU, Image, Raster};
use graphic_types::vector_types::vector::style::{Fill, Gradient, GradientStops};
use graphic_types::vector_types::vector::style::GradientStops;
use graphic_types::vector_types::vector::{self, ReferencePoint};
use graphic_types::{Artboard, Graphic, Vector};
use rendering::RenderMetadata;
@@ -65,7 +65,7 @@ macro_rules! tagged_value {
#[serde(alias = "ColorTable", alias = "OptionalColor", alias = "ColorNotInTable")]
Color(Option<Color>),
/// Stored compactly as a `GradientStops`, materializes as a single-row `List<GradientStops>` at runtime via `to_dynany`/`to_any`. Aliases recover legacy on-disk shapes.
/// (Old documents that stored a full `Gradient` struct under this same `"Gradient"` tag are routed to `FillGradient` by `deserialize_tagged_value_with_legacy_migration`.)
/// (Old documents that stored a full `Gradient` struct under this same `"Gradient"` tag are routed to `LegacyGradient` by `deserialize_tagged_value_with_legacy_migration`.)
#[serde(deserialize_with = "graphic_types::vector_types::gradient::migrate_to_gradient_stops")] // TODO: Eventually remove this migration document upgrade code
#[serde(alias = "GradientTable", alias = "GradientPositions", alias = "GradientStops")]
Gradient(GradientStops),
@@ -403,7 +403,8 @@ tagged_value! {
#[serde(alias = "Affine2")]
DAffine2(DAffine2),
OptionalDAffine2(Option<DAffine2>),
FillGradient(Gradient),
#[serde(alias = "FillGradient")]
LegacyGradient(graphic_types::migrations::legacy::Gradient),
Font(Font),
Footprint(Footprint),
VectorModification(Box<VectorModification>),
@@ -412,7 +413,8 @@ tagged_value! {
// ==========
// ENUM TYPES
// ==========
Fill(vector::style::Fill),
#[serde(alias = "Fill")]
LegacyFill(graphic_types::migrations::legacy::Fill),
BlendMode(core_types::blending::BlendMode),
LuminanceCalculation(raster_nodes::adjustments::LuminanceCalculation),
QRCodeErrorCorrectionLevel(vector_nodes::generator_nodes::QRCodeErrorCorrectionLevel),
@@ -587,7 +589,6 @@ impl TaggedValue {
// The Fill and Stroke nodes' paint connectors default to `List<Graphic>`, their first registered implementation row
() if ty == TypeId::of::<List<Graphic>>() => to_color(string).map(|color| TaggedValue::Color(Some(color)))?,
() if ty == TypeId::of::<List<GradientStops>>() => to_gradient(string).map(TaggedValue::Gradient)?,
() if ty == TypeId::of::<Fill>() => to_color(string).map(|color| TaggedValue::Fill(Fill::solid(color)))?,
() if ty == TypeId::of::<ReferencePoint>() => to_reference_point(string).map(TaggedValue::ReferencePoint)?,
_ => return None,
};
@@ -655,11 +656,11 @@ pub fn deserialize_tagged_value_with_legacy_migration<'de, D: serde::Deserialize
}
return Ok(MemoHash::new(TaggedValue::TypeDefault(descriptor!(List<Vector>))));
}
// The `Gradient` tag was reused: it used to carry a full `Gradient` struct (now `FillGradient`), and now carries an `Option<GradientStops>`.
// The `Gradient` tag was reused: it used to carry a full `Gradient` struct (now `LegacyGradient`), and now carries an `Option<GradientStops>`.
// Disambiguate by payload shape: a Gradient struct has `start`/`end` keys; a `GradientStops` has none of those (it has `position`/`midpoint`/`color`).
"Gradient" if content.as_object().is_some_and(|c| c.contains_key("start") && c.contains_key("end")) => {
let gradient: Gradient = serde_json::from_value(content.clone()).map_err(serde::de::Error::custom)?;
return Ok(MemoHash::new(TaggedValue::FillGradient(gradient)));
let gradient: graphic_types::migrations::legacy::Gradient = serde_json::from_value(content.clone()).map_err(serde::de::Error::custom)?;
return Ok(MemoHash::new(TaggedValue::LegacyGradient(gradient)));
}
_ => {}
}