mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 09:39:52 +00:00
Color management: Working CMYK proofs a tagged document through the working space
View > Proof Setup > Working CMYK simulates the working CMYK space of Color Settings in Proof Colors and Separations Preview, also in a document assigned another CMYK profile. The active context keeps the working context beside the assigned profiles, and the proof table cache key includes the working settings, so a change of the working CMYK space shows in the next proof.
This commit is contained in:
+21
-7
@@ -321,6 +321,9 @@ pub struct Cms {
|
||||
settings: ColorSettings,
|
||||
rgb: RgbSpace,
|
||||
cmyk: CmykSpace,
|
||||
/// The working settings, when a document's assigned profiles take the place of their spaces
|
||||
/// ([`use_document_profiles`]): a [`ProofTarget::WorkingCmyk`] proof simulates their CMYK space.
|
||||
working: Option<Arc<Cms>>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Cms {
|
||||
@@ -331,7 +334,7 @@ impl std::fmt::Debug for Cms {
|
||||
|
||||
impl Default for Cms {
|
||||
fn default() -> Self {
|
||||
Self { settings: ColorSettings::default(), rgb: RgbSpace::Srgb, cmyk: CmykSpace::Generic(generic()) }
|
||||
Self { settings: ColorSettings::default(), rgb: RgbSpace::Srgb, cmyk: CmykSpace::Generic(generic()), working: None }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +342,7 @@ impl Cms {
|
||||
/// Profiles named by a legacy name are stored under their current name.
|
||||
pub fn new(settings: &ColorSettings) -> Result<Self, CmsError> {
|
||||
let settings = ColorSettings { rgb: canonical_name(&settings.rgb).into(), cmyk: canonical_name(&settings.cmyk).into(), ..settings.clone() };
|
||||
Ok(Self { rgb: rgb_space(&settings.rgb)?, cmyk: cmyk_space(&settings.cmyk)?, settings })
|
||||
Ok(Self { rgb: rgb_space(&settings.rgb)?, cmyk: cmyk_space(&settings.cmyk)?, settings, working: None })
|
||||
}
|
||||
pub fn settings(&self) -> &ColorSettings {
|
||||
&self.settings
|
||||
@@ -543,8 +546,9 @@ impl Cms {
|
||||
ProofTarget::Deuteranopia => simulate_cvd(srgb, &DEUTERANOPIA),
|
||||
ProofTarget::Tritanopia => TRITANOPIA.simulate(srgb),
|
||||
ProofTarget::WorkingCmyk => {
|
||||
let cmyk = self.srgb_to_cmyk(srgb, proof.intent);
|
||||
self.cmyk_to_srgb(cmyk, proof.simulate_paper)
|
||||
let working = self.working_cms();
|
||||
let cmyk = working.srgb_to_cmyk(srgb, proof.intent);
|
||||
working.cmyk_to_srgb(cmyk, proof.simulate_paper)
|
||||
}
|
||||
ProofTarget::Cmyk(name) => match cmyk_space(name) {
|
||||
Ok(sp) => {
|
||||
@@ -556,20 +560,29 @@ impl Cms {
|
||||
}
|
||||
}
|
||||
|
||||
/// Display sRGB of CMYK inks in the proof's CMYK space (the working space for RGB targets).
|
||||
/// Display sRGB of CMYK inks in the proof's CMYK space (this context's CMYK space for RGB
|
||||
/// targets).
|
||||
pub fn proof_cmyk_to_srgb(&self, cmyk: [f32; 4], proof: &ProofSetup) -> [f32; 3] {
|
||||
match &proof.target {
|
||||
ProofTarget::Cmyk(name) => match cmyk_space(name) {
|
||||
Ok(sp) => Self::cmyk_to_srgb_in(&sp, cmyk, proof.simulate_paper, self.settings.bpc),
|
||||
Err(_) => self.cmyk_to_srgb(cmyk, proof.simulate_paper),
|
||||
},
|
||||
ProofTarget::WorkingCmyk => self.working_cms().cmyk_to_srgb(cmyk, proof.simulate_paper),
|
||||
_ => self.cmyk_to_srgb(cmyk, proof.simulate_paper),
|
||||
}
|
||||
}
|
||||
|
||||
/// The context of the working settings: the one [`use_document_profiles`] put a document's
|
||||
/// profiles in place of, else this one.
|
||||
fn working_cms(&self) -> &Cms {
|
||||
self.working.as_deref().unwrap_or(self)
|
||||
}
|
||||
|
||||
/// A cached 3-D lookup table implementing [`Cms::proof_srgb`] for 8-bit pixels.
|
||||
pub fn proof_lut(&self, proof: &ProofSetup) -> Arc<ProofLut> {
|
||||
let key = format!("{:?}|{:?}|{:?}|{}", self.settings, proof.target, proof.intent, proof.simulate_paper);
|
||||
let working = self.working.as_ref().map(|w| &w.settings);
|
||||
let key = format!("{:?}|{working:?}|{:?}|{:?}|{}", self.settings, proof.target, proof.intent, proof.simulate_paper);
|
||||
let mut cache = PROOF_CACHE.lock().unwrap_or_else(|e| e.into_inner());
|
||||
if let Some((_, l)) = cache.iter().find(|(k, _)| *k == key) {
|
||||
return l.clone();
|
||||
@@ -955,7 +968,8 @@ pub fn use_document_profiles(rgb: Option<&str>, cmyk: Option<&str>) -> bool {
|
||||
}
|
||||
// The working settings were checked when they were set; a working profile removed since then
|
||||
// leaves the active settings as they are.
|
||||
let Ok(cms) = Cms::new(&st) else { return false };
|
||||
let Ok(mut cms) = Cms::new(&st) else { return false };
|
||||
cms.working = Some(working);
|
||||
install(Arc::new(cms));
|
||||
true
|
||||
}
|
||||
|
||||
@@ -180,6 +180,35 @@ fn a_batch_converts_through_the_profile_it_assigns() {
|
||||
assert_eq!(converted, fill(&device, b));
|
||||
}
|
||||
|
||||
/// View › Proof Setup › Working CMYK simulates the working CMYK space of Color Settings in a
|
||||
/// document assigned another CMYK profile, in Proof Colors and in Separations Preview, and a change
|
||||
/// of the working CMYK space shows in the next proof while the document keeps its profile.
|
||||
#[test]
|
||||
fn working_cmyk_proofs_a_tagged_document_through_the_working_space() {
|
||||
const NAME: &str = "Tagged CMYK";
|
||||
let _g = settings();
|
||||
let _reset = ColorSettingsReset { profile: Some(NAME), paths: vec![] };
|
||||
cms::register_icc(&cms::icc_bytes(cms::GENERIC_CMYK).unwrap(), Some(NAME.into())).unwrap();
|
||||
let proof = cms::ProofSetup::default();
|
||||
assert_eq!(proof.target, cms::ProofTarget::WorkingCmyk);
|
||||
let (blue, inks) = ([0.2, 0.4, 0.8], [0.6, 0.3, 0.0, 0.1]);
|
||||
let mut s = session();
|
||||
exec(&mut s, "edit.assignProfile", json!({"cmyk": NAME}));
|
||||
let (active, working) = (cms::active(), cms::working());
|
||||
assert_eq!(active.settings().cmyk, NAME);
|
||||
assert_eq!(active.proof_srgb(blue, &proof), working.proof_srgb(blue, &proof), "Proof Colors");
|
||||
assert_eq!(active.proof_cmyk_to_srgb(inks, &proof), working.proof_cmyk_to_srgb(inks, &proof), "Separations Preview");
|
||||
let _ = active.proof_lut(&proof);
|
||||
exec(&mut s, "edit.colorSettings", json!({"cmyk": cms::DEVICE_CMYK}));
|
||||
let (active, working) = (cms::active(), cms::working());
|
||||
assert_eq!(active.settings().cmyk, NAME, "the document keeps its profile");
|
||||
let lut = active.proof_lut(&proof);
|
||||
let fresh = cms::ProofLut::build(|rgb| working.proof_srgb(rgb, &proof));
|
||||
for px in [[51, 102, 204], [230, 30, 30], [20, 160, 40], [128, 128, 128]] {
|
||||
assert_eq!(lut.apply8(px), fresh.apply8(px), "the proof of {px:?} through the new working CMYK space");
|
||||
}
|
||||
}
|
||||
|
||||
/// Separations Preview follows the Color Settings and the profiles loaded: a renderer draws a gray
|
||||
/// square on the Black plate through the new working CMYK profile, and the four process plates
|
||||
/// through a proof profile loaded again under the same name, as a new renderer draws them.
|
||||
|
||||
+2
-1
@@ -1406,7 +1406,8 @@ preferences (the folder the desktop app uses, so both see the same ones; `VECTOR
|
||||
start, after the profiles above are registered (#6335). Saved settings that name a profile that is no longer
|
||||
there, or a damaged file, leave the defaults (logged), and the next change writes over the file.
|
||||
`edit.assignProfile` tags the document only: colors show and convert through the profiles it assigns, and the
|
||||
working spaces and the file stay as they are.
|
||||
working spaces and the file stay as they are. The `workingCmyk` target of `view.proofSetup` simulates the working
|
||||
CMYK space in such a document too.
|
||||
|
||||
Not remembered: the document, anything else. Nothing is read or written when
|
||||
`VECTORCRAFT_NO_PREFS` is set, and a server confined with `--automation-read-root` or
|
||||
|
||||
@@ -693,7 +693,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
|
||||
- **Document Setup modal handoff:** Document Setup → Edit Artboards applies valid settings, closes the dialog and activates the Artboard tool. Pointer-click tests cover successful handoff, invalid settings, OK, Cancel and Undo in `dialogs/document_setup.rs`.
|
||||
- **Document Setup › Color:** a Color tab shows the document color mode (RGB Color or CMYK Color), a Convert to CMYK or Convert to RGB box for a mode change (cleared: the colors keep their numbers), and the RGB and CMYK profiles assigned to the document, with a working-space entry for none. OK runs `edit.assignProfile` and then `file.documentColorMode` with the dialog's other changes in one `command.batch`, and the document's changes are one undo step. An unchanged Color tab adds no color commands, and Cancel, or OK with nothing changed, records no undo step. A Color tab field with a value of the wrong kind is an error, and the dialog stays open. The tab is VectorCraft's own layout; File › Document Color Mode and Edit › Assign Profile… stay as they are. Tests in `dialogs/document_setup.rs`.
|
||||
- **Assign Profile and the working spaces:** Edit › Assign Profile… tags the document and leaves the working spaces of Edit › Color Settings… as they are, in Color Settings, the Separations panel and the settings saved for the next start. Colors show and convert through the profiles assigned; a change in Color Settings keeps the profiles the document in front is assigned in use, and removing an assigned profile in use puts the working space back in its place. Public reference: [Changing the color profile for a document and About color working spaces](https://help.adobe.com/archive/en_US/illustrator/cs3/illustrator_cs3_help.pdf#page=150). Tests in `engine/tests/color_settings.rs`.
|
||||
- **Assign Profile and the working spaces:** Edit › Assign Profile… tags the document and leaves the working spaces of Edit › Color Settings… as they are, in Color Settings, the Separations panel and the settings saved for the next start. Colors show and convert through the profiles assigned; a change in Color Settings keeps the profiles the document in front is assigned in use, and removing an assigned profile in use puts the working space back in its place. View › Proof Setup › Working CMYK simulates the working CMYK space of Color Settings in Proof Colors and Separations Preview, also in a document assigned another CMYK profile. Public references: [Changing the color profile for a document and About color working spaces](https://help.adobe.com/archive/en_US/illustrator/cs3/illustrator_cs3_help.pdf#page=150) and [Soft-proof presets](https://help.adobe.com/archive/en_US/illustrator/cs3/illustrator_cs3_help.pdf#page=134). Tests in `engine/tests/color_settings.rs`.
|
||||
- **New Document's More Settings and Save Preset:** More Settings opens a pop-up over New Document with only Number of Artboards, the artboard layout, Change to Right-to-Left Layout, Spacing and Columns; Done, Escape or a click outside closes it and keeps the values. Save Preset turns the top of Preset Details into a Save Document Preset heading with the preset's name, Cancel and Save, and hides the document's name, Close and Create until the preset is saved or canceled; nothing in that mode creates a document. Save Preset's default name is the first "Preset N" no saved preset has. VectorCraft's own layout. Harness tests in `dialogs/new_document.rs` cover both.
|
||||
- **Control bar with the Artboard tool:** while the Artboard tool is in use, the Control bar shows the active artboard's controls in place of the object controls: Preset, Portrait and Landscape, New Artboard, Delete Artboard, the Name field, Artboard Options, Rearrange All Artboards, the Transform link, Move and Scale Artwork with Artboard and, while the bar has room, the reference point with X and Y, and W and H with the Constrain Width and Height Proportions link. Each runs the command its Properties or Transform panel counterpart runs (`artboard.setProps`, `artboard.new`, `artboard.delete`, `tool.options {tool: "artboard"}`), and the reference point is the one the Transform panel uses. In an 800-point window the controls up to the Transform link fit, Move and Scale Artwork with Artboard show as their boxes alone with their names in tooltips, and the link opens the Transform panel with the artboard's position and size. Pointer and key tests in `panels/artboards.rs` cover the controls, W about the reference point, the orientation and the name. Public reference: [Using multiple artboards](https://web.archive.org/web/20210925094818/https://helpx.adobe.com/illustrator/using/using-multiple-artboards.html) (archived copy).
|
||||
- **Names of new and renamed artboards, brushes and patterns:** `artboard.new` and `artboard.setProps` trim the white space around the name they are given, as the Artboards panel's rename does, and a blank name gives the artboard its default name, Artboard N for the Nth artboard. `brush.new`, `brush.duplicate`, `brush.options`, `object.pattern.make`, `object.pattern.saveCopy` and `pattern.options` trim the name as the Brush Options dialog and the Pattern Options panel do, and compare the trimmed name with the names there are; a blank name gives the name each command gives when there is none, and Brush Options and Pattern Options keep the name. Tests in `tests/panelcmds.rs`, `tests/brushsym.rs` and `tests/pattern.rs` cover each command. Public references: [Using multiple artboards](https://web.archive.org/web/20210925094818/https://helpx.adobe.com/illustrator/using/using-multiple-artboards.html), [Brushes](https://web.archive.org/web/20251018101754/https://helpx.adobe.com/illustrator/using/brushes.html) and [Create and edit patterns](https://web.archive.org/web/20211031180358/https://helpx.adobe.com/illustrator/using/create-edit-patterns.html) (archived copies).
|
||||
|
||||
Reference in New Issue
Block a user