mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Add a gradient interpolation space attribute with sRGB Gamma (existing) and sRGB Linear (new) (#4412)
* Build dropdown menu entries from choice type metadata * Add a gradient interpolation color space attribute, blending stops in linear light by default * Add a Space interpolation dropdown to the color picker popover * Stamp legacy gradient ramps with their implicit gamma interpolation during deserialization * Resolve color-interpolation from SVG style blocks and fix cascade order among repeated declarations
This commit is contained in:
@@ -555,6 +555,7 @@ tagged_value! {
|
||||
GradientForm(vector::style::GradientForm),
|
||||
#[serde(alias = "GradientSpreadMethod")] // TODO: Eventually remove this document upgrade code
|
||||
GradientSpread(vector::style::GradientSpread),
|
||||
GradientInterpolation(vector::style::GradientInterpolation),
|
||||
ReferencePoint(vector::ReferencePoint),
|
||||
CentroidType(vector::misc::CentroidType),
|
||||
BooleanOperation(vector::misc::BooleanOperation),
|
||||
@@ -805,11 +806,15 @@ pub fn deserialize_tagged_value_with_legacy_migration<'de, D: serde::Deserialize
|
||||
.and_then(|c| c.get("element").or_else(|| c.get("instance")).or_else(|| c.get("instances")))
|
||||
.and_then(|element| element.as_array());
|
||||
|
||||
// An empty legacy table wrapper carries no gradient, degrading to the default rather than failing the document load
|
||||
// An empty legacy table wrapper carries no gradient, degrading to the default (in the era's gamma) rather than failing the document load
|
||||
if let Some(array) = table_element
|
||||
&& array.is_empty()
|
||||
{
|
||||
return Ok(MemoHash::new(TaggedValue::GradientRamp(GradientRamp::default())));
|
||||
let ramp = GradientRamp {
|
||||
gradient_interpolation: vector::style::GradientInterpolation::SrgbGamma,
|
||||
..Default::default()
|
||||
};
|
||||
return Ok(MemoHash::new(TaggedValue::GradientRamp(ramp)));
|
||||
}
|
||||
|
||||
let payload = table_element.and_then(|array| array.first()).unwrap_or(content);
|
||||
@@ -1023,7 +1028,7 @@ mod paint_default_parsing {
|
||||
|
||||
#[cfg(test)]
|
||||
mod gradient_shape_migration {
|
||||
use graphic_types::vector_types::GradientSpread;
|
||||
use graphic_types::vector_types::{GradientInterpolation, GradientSpread};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -1050,9 +1055,29 @@ mod gradient_shape_migration {
|
||||
|
||||
let json = serde_json::to_value(&value).unwrap();
|
||||
assert!(json.get("GradientRamp").and_then(|payload| payload.get("stops")).is_some(), "the payload should nest its stops: {json}");
|
||||
assert_eq!(
|
||||
json.get("GradientRamp").and_then(|payload| payload.get("gradient_interpolation")),
|
||||
Some(&serde_json::json!("SrgbLinear")),
|
||||
"the interpolation should serialize even at its default, marking the ramp as post-legacy: {json}"
|
||||
);
|
||||
assert_eq!(load(json), value);
|
||||
}
|
||||
|
||||
// TODO: Eventually remove this document upgrade code
|
||||
#[test]
|
||||
fn ramp_without_interpolation_field_reads_as_legacy_gamma() {
|
||||
let json = serde_json::json!({ "GradientRamp": { "stops": { "color": [white(), white()] } } });
|
||||
let TaggedValue::GradientRamp(ramp) = load(json) else {
|
||||
panic!("the ramp payload should become a gradient ramp value")
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
ramp.gradient_interpolation,
|
||||
GradientInterpolation::SrgbGamma,
|
||||
"a ramp saved before the field existed should read as gamma"
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Eventually remove this document upgrade code
|
||||
#[test]
|
||||
fn legacy_flat_stops_parse_faithfully() {
|
||||
@@ -1060,6 +1085,7 @@ mod gradient_shape_migration {
|
||||
let TaggedValue::GradientRamp(ramp) = load(json) else {
|
||||
panic!("the flat stops should become a gradient ramp value")
|
||||
};
|
||||
assert_eq!(ramp.gradient_interpolation, GradientInterpolation::SrgbGamma, "the pre-ramp flat form should carry the era's gamma");
|
||||
|
||||
let gradient = Gradient::from(ramp);
|
||||
assert_eq!(gradient.positions(), vec![0., 0.25]);
|
||||
@@ -1073,6 +1099,7 @@ mod gradient_shape_migration {
|
||||
let TaggedValue::GradientRamp(ramp) = load(json) else {
|
||||
panic!("the tuple stops should become a gradient ramp value")
|
||||
};
|
||||
assert_eq!(ramp.gradient_interpolation, GradientInterpolation::SrgbGamma, "the pre-ramp tuple form should carry the era's gamma");
|
||||
|
||||
let gradient = Gradient::from(ramp);
|
||||
assert_eq!(gradient.positions(), vec![0., 1.]);
|
||||
@@ -1083,7 +1110,11 @@ mod gradient_shape_migration {
|
||||
#[test]
|
||||
fn empty_legacy_gradient_table_degrades_to_the_default() {
|
||||
let json = serde_json::json!({ "GradientTable": { "element": [] } });
|
||||
assert_eq!(load(json), TaggedValue::GradientRamp(GradientRamp::default()));
|
||||
let expected = GradientRamp {
|
||||
gradient_interpolation: GradientInterpolation::SrgbGamma,
|
||||
..Default::default()
|
||||
};
|
||||
assert_eq!(load(json), TaggedValue::GradientRamp(expected));
|
||||
}
|
||||
|
||||
// TODO: Eventually remove this document upgrade code
|
||||
|
||||
Reference in New Issue
Block a user