mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-09 18:54:57 +00:00
Color Wheel: the remembered hue resets when the color settings change the color's display
The wheel kept the HSB picked last while the objects and the color were unchanged, even after a change of the working RGB space or the document's profile made the same color display differently. It now also stores the display sRGB of the color it picked, and shows the color's own HSB when that no longer matches.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
//! proxy and Shift steps the ring by 45°. A pick is display sRGB, converted into the working RGB
|
||||
//! space: an RGB, CMYK or Lab color keeps its model, and a Gray color or a tint of a global swatch
|
||||
//! becomes a process color in the document's color mode. The HSB picked last stays while the
|
||||
//! objects, the proxy and the color are unchanged, so a gray keeps its hue.
|
||||
//! objects, the proxy, the color and the color settings are unchanged, so a gray keeps its hue.
|
||||
|
||||
use egui::{Ui, UiBuilder};
|
||||
use vectorcraft_color::cms::{self, Cms};
|
||||
@@ -20,7 +20,7 @@ use crate::widgets::{self, FieldAxis, Live};
|
||||
pub const ID: &str = "colorWheel";
|
||||
/// The widest the wheel is drawn.
|
||||
const MAX_WHEEL: f32 = 200.0;
|
||||
/// Panel state: the HSB picked last and its [`Owner`].
|
||||
/// Panel state: the HSB picked last, its [`Owner`] and the display sRGB of the color it stored.
|
||||
const MEMORY: &str = "color-wheel-hsb";
|
||||
|
||||
/// What the HSB picked last belongs to: the document, the selected objects, the proxy, the
|
||||
@@ -59,6 +59,13 @@ pub(crate) fn display_hsb(cms: &Cms, c: &Color) -> [f32; 3] {
|
||||
rgb_to_hsb(cms.display_rgb(c))
|
||||
}
|
||||
|
||||
/// The HSB the wheel shows for `c` through `cms` when `hsb` was picked last and `c` then displayed
|
||||
/// as the sRGB `shown`: `hsb` while `c` still displays as `shown`, else `c`'s own display HSB (after
|
||||
/// a change of the color settings or the document's profile).
|
||||
pub(crate) fn remembered_hsb(cms: &Cms, c: &Color, shown: [f32; 3], hsb: [f32; 3]) -> [f32; 3] {
|
||||
if cms.display_rgb(c) == shown { hsb } else { display_hsb(cms, c) }
|
||||
}
|
||||
|
||||
/// The color a pick of display HSB `hsb` stores in place of `was`, through `cms`. The picked sRGB
|
||||
/// goes into the working RGB space. An RGB color stays RGB, and a CMYK or Lab color converts to its
|
||||
/// model with the color settings. Anything else (no color, a Gray color, a tint of a global swatch)
|
||||
@@ -104,8 +111,8 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
let cms = cms::active();
|
||||
// With None, a pattern or a "?" proxy the wheel shows the last solid color without markers,
|
||||
// and a click, an arrow key or a screen reader's action applies the picked color.
|
||||
let hsb = match (color, pstate::<Option<(Owner, [f32; 3])>>(ui.ctx(), MEMORY)) {
|
||||
(Some(c), Some((owner, hsb))) if owner == Owner::of(app, &tgt, c) => hsb,
|
||||
let hsb = match (color, pstate::<Option<(Owner, [f32; 3], [f32; 3])>>(ui.ctx(), MEMORY)) {
|
||||
(Some(c), Some((owner, shown, hsb))) if owner == Owner::of(app, &tgt, c) => remembered_hsb(&cms, &c, shown, hsb),
|
||||
(c, _) => display_hsb(&cms, &c.unwrap_or(app.session.last_solid)),
|
||||
};
|
||||
let marked = color.is_some();
|
||||
@@ -144,7 +151,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
let cmyk_doc = app.session.active().is_some_and(|d| d.doc.color_mode == ColorMode::Cmyk);
|
||||
let c = stored(&cms, hsb, replaced(app, &tgt, behind).as_ref(), cmyk_doc);
|
||||
if !behind {
|
||||
set_pstate(ui.ctx(), MEMORY, Some((Owner::of(app, &tgt, c), hsb)));
|
||||
set_pstate(ui.ctx(), MEMORY, Some((Owner::of(app, &tgt, c), cms.display_rgb(&c), hsb)));
|
||||
}
|
||||
apply(app, &tgt, c, phase, behind);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use vectorcraft_color::cms::{self, Cms, ColorSettings, delta_e2000};
|
||||
use vectorcraft_color::{Color, Paint};
|
||||
use vectorcraft_engine::Session;
|
||||
|
||||
use super::color_wheel::{ID, display_hsb, show, stored};
|
||||
use super::color_wheel::{ID, display_hsb, remembered_hsb, show, stored};
|
||||
use crate::VectorcraftApp;
|
||||
|
||||
/// An app with a selected rectangle filled with `fill`.
|
||||
@@ -308,6 +308,21 @@ fn the_remembered_hue_stays_with_its_object() {
|
||||
assert!(!(1.0..359.0).contains(&hue), "the white object's own hue is 0°, not 120°: {hue}");
|
||||
}
|
||||
|
||||
/// The remembered HSB holds only while the color displays as it did when picked: in another
|
||||
/// working RGB space the wheel shows the color's own HSB there.
|
||||
#[test]
|
||||
fn the_remembered_hsb_follows_a_change_of_working_space() {
|
||||
let srgb = Cms::default();
|
||||
let p3 = Cms::new(&ColorSettings { rgb: cms::DISPLAY_P3.into(), ..ColorSettings::default() }).unwrap();
|
||||
let c = Color::rgb(0.5, 0.3, 0.2);
|
||||
let picked = [25.0, 0.6, 0.5];
|
||||
let shown = srgb.display_rgb(&c);
|
||||
assert_eq!(remembered_hsb(&srgb, &c, shown, picked), picked);
|
||||
let own = display_hsb(&p3, &c);
|
||||
assert_ne!(own, picked);
|
||||
assert_eq!(remembered_hsb(&p3, &c, shown, picked), own);
|
||||
}
|
||||
|
||||
/// A CMYK fill stays CMYK and keeps its look (ΔE 2000 under 2) when its marker is clicked; the
|
||||
/// working profile separates the picked color again, so its inks can move.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user