Eyedropper: sample the colour as the canvas shows it; picker strings in every catalog

- `screen_post` holds what the canvas does to a render before showing it
  (Proof Colors, the composite ink-limit preview). The texture and the
  eyedropper's one-pixel sample both go through it, so with either view
  on, the eyedropper takes the colour on screen.
- The picker's OK uses the footer's padded "  OK  " key, which every
  catalog has (Chinese showed "OK").
- "RGB Color Space View", "Lab Color Space View", "Add CMYK Swatch" and
  "Added swatch" are in the ar, cs, it, ka, pl, pt-br, ru and uk
  catalogs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
moppeeerandClaude Opus 5.5 committed 2026-10-22 00:30:40 +02:00
1 parent 3430a88cbc
commit 22bb814c9d
10 files changed
+97 -5

No files matched your search

+12 -4
View File
@@ -660,7 +660,9 @@ pub fn color_at(app: &mut DesignApp, ctx: &egui::Context, pos: Pos2) -> Option<[
let ppp = ctx.pixels_per_point() as f64;
let view = Affine::scale(ppp) * Affine::scale(xf.zoom) * Affine::translate((-at.x, -at.y));
let opts = screen_options(app, &layout, app.ui.screen_mode != ScreenMode::Normal, ppp);
let img = app.canvas.patcher.render(&doc, &app.session.cache, &placed, 1, 1, view, &opts);
let mut img = app.canvas.patcher.render(&doc, &app.session.cache, &placed, 1, 1, view, &opts);
// The colour as the canvas shows it: proofed, or marked over the ink limit.
screen_post(app, &mut img);
let [r, g, b, a] = <[u8; 4]>::try_from(img.pixels.get(..4)?).ok()?;
// Premultiplied over the paper.
let paper = doc.resolve_color(designcraft_color::swatch::PAPER, 1.0).unwrap_or(designcraft_color::Color::WHITE).to_rgba8(1.0);
@@ -934,14 +936,20 @@ fn render_worker_spawn(ctx: &egui::Context) -> Option<crate::render_worker::Work
crate::render_worker::Worker::spawn(ctx.clone())
}
fn upload(app: &mut DesignApp, ctx: &egui::Context, mut img: designcraft_render::Rendered) {
/// What the canvas does to a render before showing it: Proof Colors, and the composite ink-limit
/// preview. The texture and the eyedropper's sample both go through it.
fn screen_post(app: &DesignApp, img: &mut designcraft_render::Rendered) {
if app.ui.proof_colors {
designcraft_render::proof_view(&mut img, &app.ui.proof_setup);
designcraft_render::proof_view(img, &app.ui.proof_setup);
}
// Plates render from source colours; the ink limit is estimated from the composite.
if app.ui.separation.is_none() && app.ui.ink_limit.is_some() {
designcraft_render::separation_view(&mut img, None, app.ui.ink_limit);
designcraft_render::separation_view(img, None, app.ui.ink_limit);
}
}
fn upload(app: &mut DesignApp, ctx: &egui::Context, mut img: designcraft_render::Rendered) {
screen_post(app, &mut img);
let ci = egui::ColorImage::from_rgba_premultiplied([img.width as usize, img.height as usize], &img.pixels);
let ci = crate::widgets::fit_texture(ci, ctx.input(|i| i.max_texture_side));
match &mut app.canvas.texture {
+53 -1
View File
@@ -6775,7 +6775,8 @@ fn color_picker(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, label));
resp.clicked()
};
if pill(ui, 0, &tr("OK"), true) || ui.input(|i| i.key_pressed(egui::Key::Enter)) {
// The footer's padded OK key, which every catalog has.
if pill(ui, 0, tr(" OK ").trim(), true) || ui.input(|i| i.key_pressed(egui::Key::Enter)) {
d.fields.insert("_close".into(), json!("ok"));
}
if pill(ui, 1, &tr("Cancel"), false) || ui.input(|i| i.key_pressed(egui::Key::Escape)) {
@@ -10033,6 +10034,57 @@ mod tests {
/// is on, the new colour over the old one, and the values in every space.
/// The course's chapter 23: the Color Picker's eyedropper, dragged from the picker onto the
/// page and let go there, takes the colour the page shows.
/// The eyedropper takes the colour the canvas shows: with Proof Colors the proofed colour, and
/// with the ink-limit preview the warning colour over the limit.
#[test]
fn the_eyedropper_samples_what_proof_colors_and_the_ink_limit_show() {
use egui_kittest::Harness;
let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
app.run("file.new", json!({})).unwrap();
app.run("swatch.create", json!({"name": "Vivid Green", "color": [0, 255, 0]})).unwrap();
let id = app.run("frame.create", json!({"rect": [36, 36, 560, 700], "content": "unassigned"})).unwrap()["id"].as_u64().unwrap();
app.run("object.fill", json!({"ids": [id], "swatch": "Vivid Green"})).unwrap();
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_ui_state(
|ui, app: &mut DesignApp| {
let ctx = ui.ctx().clone();
app.logic(&ctx);
app.ui(ui);
},
app,
);
h.run_steps(6);
let target = {
let app = h.state();
let doc = &app.session.doc().unwrap().doc;
let layout = designcraft_tools::CanvasLayout::new(doc, false);
let v = *app.view().unwrap();
crate::canvas::Xf::new(app.canvas_rect.unwrap(), &v).to_screen(layout.slots[0].xf * designcraft_geom::Point::new(300.0, 600.0))
};
let ctx = h.ctx.clone();
let sample = |h: &mut Harness<'_, DesignApp>| crate::canvas::color_at(h.state_mut(), &ctx, target).expect("on the page");
// What a view makes of the plain colour, as the canvas texture gets it.
let shown = |c: [u8; 3], view: &dyn Fn(&mut designcraft_render::Rendered)| {
let mut img = designcraft_render::Rendered { width: 1, height: 1, pixels: vec![c[0], c[1], c[2], 255] };
view(&mut img);
[img.pixels[0], img.pixels[1], img.pixels[2]]
};
let plain = sample(&mut h);
h.state_mut().ui.proof_colors = true;
let setup = h.state().ui.proof_setup.clone();
let proofed = sample(&mut h);
assert_eq!(proofed, shown(plain, &|img| designcraft_render::proof_view(img, &setup)));
assert_ne!(proofed, plain, "the proof changes this green");
// The composite ink-limit preview: a blue over a 100% limit shows (and samples) the warning.
h.state_mut().ui.proof_colors = false;
h.state_mut().run("object.fill", json!({"ids": [id], "swatch": "C=100 M=90 Y=10 K=0"})).unwrap();
h.run_steps(3);
let blue = sample(&mut h);
h.state_mut().ui.ink_limit = Some(1.0);
let limited = sample(&mut h);
assert_eq!(limited, shown(blue, &|img| designcraft_render::separation_view(img, None, Some(1.0))));
assert_eq!(limited, [230, 40, 40]);
}
#[test]
fn the_color_pickers_eyedropper_takes_a_colour_off_the_page() {
use egui_kittest::{Harness, kittest::Queryable};
+4
View File
@@ -30,6 +30,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[
("Cut", "قص"),
("Copy", "نسخ"),
("Paste", "لصق"),
("RGB Color Space View", "عرض فضاء ألوان RGB"),
("Lab Color Space View", "عرض فضاء ألوان Lab"),
("Add CMYK Swatch", "إضافة عينة لون CMYK"),
("Added swatch", "تمت إضافة عينة اللون"),
("Eyedropper: drag it onto the page", "القطارة: اسحبها إلى الصفحة"),
("Paste Vector Art", "لصق رسم متجه"),
("Baseline Options", "خيارات خط الأساس"),
+4
View File
@@ -31,6 +31,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[
("Cut", "Vyjmout"),
("Copy", "Kopírovat"),
("Paste", "Vložit"),
("RGB Color Space View", "Zobrazení barevného prostoru RGB"),
("Lab Color Space View", "Zobrazení barevného prostoru Lab"),
("Add CMYK Swatch", "Přidat vzorek CMYK"),
("Added swatch", "Vzorek přidán"),
("Eyedropper: drag it onto the page", "Kapátko: přetáhněte ho na stránku"),
("Reverse Path", "Obrátit cestu"),
("Set Anchor", "Nastavit kotvu"),
+4
View File
@@ -28,6 +28,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[
("Cut", "Taglia"),
("Copy", "Copia"),
("Paste", "Incolla"),
("RGB Color Space View", "Vista spazio colore RGB"),
("Lab Color Space View", "Vista spazio colore Lab"),
("Add CMYK Swatch", "Aggiungi campione CMYK"),
("Added swatch", "Campione aggiunto"),
("Eyedropper: drag it onto the page", "Contagocce: trascinalo sulla pagina"),
("Paste Vector Art", "Incolla grafica vettoriale"),
("Baseline Options", "Opzioni linea di base"),
+4
View File
@@ -31,6 +31,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[
("Cut", "ამოჭრა"),
("Copy", "კოპირება"),
("Paste", "ჩასმა"),
("RGB Color Space View", "RGB ფერთა სივრცის ხედი"),
("Lab Color Space View", "Lab ფერთა სივრცის ხედი"),
("Add CMYK Swatch", "CMYK ფერის ნიმუშის დამატება"),
("Added swatch", "ფერის ნიმუში დამატებულია"),
("Eyedropper: drag it onto the page", "პიპეტი: გადაიტანეთ გვერდზე"),
("Inches Decimal", "ინჩები (ათობითი)"),
("Back", "უკან"),
+4
View File
@@ -29,6 +29,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[
("Cut", "Wytnij"),
("Copy", "Kopiuj"),
("Paste", "Wklej"),
("RGB Color Space View", "Widok przestrzeni barw RGB"),
("Lab Color Space View", "Widok przestrzeni barw Lab"),
("Add CMYK Swatch", "Dodaj próbkę CMYK"),
("Added swatch", "Dodano próbkę"),
("Eyedropper: drag it onto the page", "Kroplomierz: przeciągnij go na stronę"),
("Clear", "Wyczyść"),
("Duplicate", "Powiel"),
+4
View File
@@ -31,6 +31,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[
("Cut", "Recortar"),
("Copy", "Copiar"),
("Paste", "Colar"),
("RGB Color Space View", "Exibição do espaço de cores RGB"),
("Lab Color Space View", "Exibição do espaço de cores Lab"),
("Add CMYK Swatch", "Adicionar amostra CMYK"),
("Added swatch", "Amostra adicionada"),
("Eyedropper: drag it onto the page", "Conta-gotas: arraste-o para a página"),
("Paste Vector Art", "Colar arte vetorial"),
("Baseline Options", "Opções de linha de base"),
+4
View File
@@ -33,6 +33,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[
("Cut", "Вырезать"),
("Copy", "Копировать"),
("Paste", "Вставить"),
("RGB Color Space View", "Просмотр цветового пространства RGB"),
("Lab Color Space View", "Просмотр цветового пространства Lab"),
("Add CMYK Swatch", "Добавить образец CMYK"),
("Added swatch", "Образец добавлен"),
("Eyedropper: drag it onto the page", "Пипетка: перетащите её на страницу"),
("Clear", "Очистить"),
("Duplicate", "Дублировать"),
+4
View File
@@ -29,6 +29,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[
("Cut", "Вирізати"),
("Copy", "Копіювати"),
("Paste", "Вставити"),
("RGB Color Space View", "Перегляд колірного простору RGB"),
("Lab Color Space View", "Перегляд колірного простору Lab"),
("Add CMYK Swatch", "Додати зразок CMYK"),
("Added swatch", "Зразок додано"),
("Eyedropper: drag it onto the page", "Піпетка: перетягніть її на сторінку"),
("Paste Vector Art", "Вставити векторну графіку"),
("Baseline Options", "Параметри базової лінії"),