Deprecate all usages of the Color struct representing gamma space values, fixing round-trip precision bugs (#4149)

* Deprecate all usages of the Color struct representing gamma space values, fixing round-trip precision bugs

* Code review fixes
This commit is contained in:
Keavon Chambers
2026-05-14 22:48:33 -07:00
committed by GitHub
parent 456a7c868d
commit a56746c6bf
67 changed files with 1210 additions and 941 deletions
@@ -1,7 +1,8 @@
use crate::messages::input_mapper::utility_types::input_keyboard::KeysGroup;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*;
use graphene_std::vector::style::FillChoice;
use graphene_std::color::SRGBA8;
use graphene_std::vector::style::FillChoiceUI;
use serde_json::Value;
use std::collections::HashMap;
@@ -179,11 +180,11 @@ impl LayoutMessageHandler {
let callback_message = match action {
WidgetValueAction::Commit => (color_button.on_commit.callback)(&()),
WidgetValueAction::Update => {
let Ok(fill_choice) = serde_json::from_value::<FillChoice>(value) else {
warn!("ColorInput update was not able to be parsed as FillChoice: {color_button:?}");
let Ok(fill_choice_ui) = serde_json::from_value::<FillChoiceUI>(value) else {
warn!("ColorInput update was not able to be parsed as FillChoiceUI: {color_button:?}");
return;
};
color_button.value = fill_choice;
color_button.value = fill_choice_ui;
(color_button.on_update.callback)(color_button)
}
};
@@ -496,25 +497,14 @@ fn populate_computed_display_fields(layout: &mut Layout) {
}
Widget::SpectrumInput(spectrum_input) => {
spectrum_input.track_css = spectrum_input.track.to_css_linear_gradient();
spectrum_input.track_start_css = spectrum_input
.track
.color
.first()
.map(|color| format!("#{}", color.to_rgba_hex_srgb_from_gamma()))
.unwrap_or_else(|| "black".to_string());
spectrum_input.track_end_css = spectrum_input
.track
.color
.last()
.map(|color| format!("#{}", color.to_rgba_hex_srgb_from_gamma()))
.unwrap_or_else(|| "black".to_string());
spectrum_input.track_start_css = spectrum_input.track.color.first().map(|color| color.to_css_hex()).unwrap_or_else(|| "black".to_string());
spectrum_input.track_end_css = spectrum_input.track.color.last().map(|color| color.to_css_hex()).unwrap_or_else(|| "black".to_string());
}
Widget::ColorComparisonInput(comparison) => {
use graphene_std::Color;
let contrasting = |color: Option<Color>| format!("#{}", color.map_or(Color::BLACK, |color| color.contrasting_text_color_from_gamma()).to_rgba_hex_srgb_from_gamma());
comparison.new_color_css = comparison.new_color.map(|color| format!("#{}", color.to_rgba_hex_srgb_from_gamma())).unwrap_or_default();
let contrasting = |color: Option<SRGBA8>| color.map_or(SRGBA8::BLACK, |color| color.contrasting_text_color()).to_css_hex();
comparison.new_color_css = comparison.new_color.map(|color| color.to_css_hex()).unwrap_or_default();
comparison.new_color_contrasting = contrasting(comparison.new_color);
comparison.old_color_css = comparison.old_color.map(|color| format!("#{}", color.to_rgba_hex_srgb_from_gamma())).unwrap_or_default();
comparison.old_color_css = comparison.old_color.map(|color| color.to_css_hex()).unwrap_or_default();
comparison.old_color_contrasting = contrasting(comparison.old_color);
}
_ => {}
@@ -22,7 +22,7 @@ impl core::fmt::Display for WidgetId {
macro_rules! define_layout_target {
($($(#[$attr:meta])* $variant:ident),* $(,)?) => {
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
#[cfg_attr(feature = "wasm", derive(tsify::Tsify), tsify(from_wasm_abi))]
#[derive(PartialEq, Clone, Debug, Hash, Eq, Copy, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum LayoutTarget {
@@ -4,7 +4,7 @@ use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType;
use crate::messages::tool::tool_messages::tool_prelude::WidgetCallback;
use derivative::*;
use graphene_std::vector::style::FillChoice;
use graphene_std::vector::style::FillChoiceUI;
use graphite_proc_macros::WidgetBuilder;
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
@@ -187,11 +187,10 @@ pub struct ImageButton {
#[derivative(Debug, PartialEq, Default)]
pub struct ColorInput {
// Content
/// WARNING: The colors are gamma, not linear!
#[widget_builder(constructor)]
pub value: FillChoice,
pub value: FillChoiceUI,
/// CSS `linear-gradient(...)` (or solid-color stand-in) for the swatch's `background-image`. Auto-populated from `value` at layout-send time.
/// `None` when `value` is `FillChoice::None`, in which case the frontend uses its "none" fallback styling.
/// `None` when `value` is `FillChoiceUI::None`, in which case the frontend uses its "none" fallback styling.
#[serde(rename = "chosenGradient")]
#[widget_builder(skip)]
pub chosen_gradient: Option<String>,
@@ -4,8 +4,9 @@ use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::node_graph::document_node_definitions::DefinitionIdentifier;
use derivative::*;
use graphene_std::Color;
use graphene_std::color::SRGBA8;
use graphene_std::transform::ReferencePoint;
use graphene_std::vector::style::{FillChoice, GradientStops};
use graphene_std::vector::style::{FillChoiceUI, GradientStopsUI};
use graphite_proc_macros::WidgetBuilder;
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
@@ -349,9 +350,9 @@ pub struct RadioEntryData {
pub struct WorkingColorsInput {
// Content
#[widget_builder(constructor)]
pub primary: Color,
pub primary: SRGBA8,
#[widget_builder(constructor)]
pub secondary: Color,
pub secondary: SRGBA8,
}
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
@@ -484,10 +485,10 @@ pub struct ColorComparisonInput {
// Content
#[widget_builder(constructor)]
#[serde(rename = "newColor")]
pub new_color: Option<Color>,
pub new_color: Option<SRGBA8>,
#[widget_builder(constructor)]
#[serde(rename = "oldColor")]
pub old_color: Option<Color>,
pub old_color: Option<SRGBA8>,
#[serde(rename = "isNone")]
pub is_none: bool,
#[serde(rename = "oldIsNone")]
@@ -544,7 +545,7 @@ pub struct ColorPresetsInput {
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum ColorPresetsInputUpdate {
Preset(FillChoice),
Preset(FillChoiceUI),
EyedropperColorCode(String),
}
@@ -555,7 +556,7 @@ pub struct SpectrumInput {
// Content
/// The colored gradient drawn behind the markers (display-only, caller-owned).
#[widget_builder(constructor)]
pub track: GradientStops,
pub track: GradientStopsUI,
/// CSS `linear-gradient(...)` string for the track strip's `background-image`. Auto-populated from `track` at layout-send time.
#[serde(rename = "trackCSS")]
#[widget_builder(skip)]
@@ -607,14 +608,14 @@ pub struct SpectrumMarker {
position: f64,
/// Position (0..1) of the midpoint between this marker and the next, used only if `show_midpoints` is true. The last marker's value is ignored.
midpoint: f64,
/// CSS color string for the marker handle's fill. Set via `SpectrumMarker::new` from a [`Color`] (gamma space).
/// CSS color string for the marker handle's fill. Set via `SpectrumMarker::new` from a linear [`Color`].
#[serde(rename = "handleColorCSS")]
handle_color_css: String,
}
impl SpectrumMarker {
pub fn new(position: f64, midpoint: f64, handle_color: Color) -> Self {
let handle_color_css = format!("#{}", handle_color.to_rgba_hex_srgb_from_gamma());
let handle_color_css = SRGBA8::from(handle_color).to_css_hex();
Self { position, midpoint, handle_color_css }
}
}