mirror of
https://github.com/storytold/craft-libs.git
synced 2026-10-31 07:39:23 +00:00
separations: use US spelling
This commit is contained in:
1 parent
602c915272
commit
2c80b65e98
11 files changed
+66
-66
No files matched your search
@@ -138,7 +138,7 @@ fn knockout_groups_replace_what_their_elements_cover() {
|
||||
|
||||
// A stencil mask must not erase the red beside it. Where the stencil paints (every sample 0)
|
||||
// its blue is drawn; a stencil composites rather than knocking the red out, and its exact
|
||||
// colour also depends on its fill opacity (pdfcraft #2975), so only "blue was drawn here" is
|
||||
// color also depends on its fill opacity (pdfcraft #2975), so only "blue was drawn here" is
|
||||
// pinned.
|
||||
let stencil = render(ko, &format!("{red}0 0 1 rg q 150 0 0 120 100 50 cm /Msk Do Q"));
|
||||
check(&stencil, 50, 40, [255, 128, 128], "red beside a stencil");
|
||||
|
||||
+16
-16
@@ -86,12 +86,12 @@ fn inks(spots: &[&str]) -> Vec<Ink> {
|
||||
Ink::PROCESS.into_iter().chain(spots.iter().map(|s| spot(s))).collect()
|
||||
}
|
||||
|
||||
/// The process plates and Gold, overprint honoured.
|
||||
/// The process plates and Gold, overprint honored.
|
||||
fn separate(pdf: &[u8]) -> Plates {
|
||||
plates(pdf, &inks(&["Gold"]), true, None)
|
||||
}
|
||||
|
||||
/// A spot colour whose alternate is a yellowish CMYK.
|
||||
/// A spot color whose alternate is a yellowish CMYK.
|
||||
const GOLD: &str = "[/Separation /Gold /DeviceCMYK << /FunctionType 2 /Domain [0 1] /C0 [0 0 0 0] /C1 [0 0.3 1 0] /N 1 >>]";
|
||||
|
||||
fn gold_resource() -> String {
|
||||
@@ -109,15 +109,15 @@ fn device_cmyk_puts_each_component_on_its_own_plate() {
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
fn a_spot_colour_paints_its_own_plate_and_knocks_out_the_process_plates() {
|
||||
fn a_spot_color_paints_its_own_plate_and_knocks_out_the_process_plates() {
|
||||
let s = separate(&page_pdf("0 0 0 1 k 0 0 40 40 re f /CS0 cs 0.5 scn 10 10 20 20 re f", &gold_resource(), &[]));
|
||||
assert_eq!(s.at(20, 20), [0, 0, 0, 0, 50], "knocked out under the spot colour");
|
||||
assert_eq!(s.at(20, 20), [0, 0, 0, 0, 50], "knocked out under the spot color");
|
||||
assert_eq!(s.at(2, 2), [0, 0, 0, 100, 0]);
|
||||
}
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
fn overprinting_keeps_the_plates_a_colour_does_not_specify() {
|
||||
fn overprinting_keeps_the_plates_a_color_does_not_specify() {
|
||||
let resources = format!("{} /ExtGState << /GS1 << /op true >> >>", gold_resource());
|
||||
let pdf = page_pdf("0 0 0 1 k 0 0 40 40 re f /GS1 gs /CS0 cs 0.5 scn 10 10 20 20 re f", &resources, &[]);
|
||||
assert_eq!(separate(&pdf).at(20, 20), [0, 0, 0, 100, 50], "overprinted");
|
||||
@@ -147,7 +147,7 @@ fn nonzero_overprint_mode_leaves_zero_device_cmyk_components() {
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
fn gray_and_rgb_are_process_colour_and_never_take_the_nonzero_overprint_mode() {
|
||||
fn gray_and_rgb_are_process_color_and_never_take_the_nonzero_overprint_mode() {
|
||||
let process = inks(&[]);
|
||||
let gray = page_pdf("1 0 0 0 k 0 0 40 40 re f /M1 gs 0.25 g 10 10 20 20 re f", "/ExtGState << /M1 << /OP true /OPM 1 >> >>", &[]);
|
||||
assert_eq!(plates(&gray, &process, true, None).at(20, 20), [0, 0, 0, 75], "gray is black only, and knocks out cyan");
|
||||
@@ -172,7 +172,7 @@ fn the_all_colorant_paints_every_plate_and_none_paints_nothing() {
|
||||
let resources = format!("/ColorSpace << /CS0 {GOLD} /Reg [/Separation /All {gray}] /No [/Separation /None {gray}] >>");
|
||||
let content = "/CS0 cs 0.2 scn 0 0 40 40 re f /Reg cs 1 scn 0 0 20 40 re f /No cs 1 scn 20 0 20 40 re f";
|
||||
let s = separate(&page_pdf(content, &resources, &[]));
|
||||
assert_eq!(s.at(10, 20), [100, 100, 100, 100, 100], "registration colour");
|
||||
assert_eq!(s.at(10, 20), [100, 100, 100, 100, 100], "registration color");
|
||||
assert_eq!(s.at(30, 20), [0, 0, 0, 0, 20], "None leaves every plate as it is");
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ fn images_are_separated_sample_by_sample() {
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
fn a_spot_colour_image_overprints_like_any_paint() {
|
||||
fn a_spot_color_image_overprints_like_any_paint() {
|
||||
let image = stream(&format!("/Type /XObject /Subtype /Image /Width 1 /Height 1 /BitsPerComponent 8 /ColorSpace {GOLD}"), &[128]);
|
||||
let resources = "/XObject << /Im1 5 0 R >> /ExtGState << /GS1 << /op true >> >>";
|
||||
let pdf = |gs: &str| page_pdf(&format!("0 0 0 1 k 0 0 40 40 re f {gs} q 20 0 0 20 10 10 cm /Im1 Do Q"), resources, std::slice::from_ref(&image));
|
||||
@@ -204,7 +204,7 @@ fn a_spot_colour_image_overprints_like_any_paint() {
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
fn shadings_are_separated_through_their_colour_space() {
|
||||
fn shadings_are_separated_through_their_color_space() {
|
||||
let shading = format!(
|
||||
"<< /ShadingType 2 /ColorSpace {GOLD} /Coords [0 0 40 0] /Function << /FunctionType 2 /Domain [0 1] /C0 [0] /C1 [1] /N 1 >> /Extend [true true] >>"
|
||||
);
|
||||
@@ -216,16 +216,16 @@ fn shadings_are_separated_through_their_colour_space() {
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
fn an_uncoloured_pattern_paints_the_film_of_the_colour_it_is_used_with() {
|
||||
fn an_uncolored_pattern_paints_the_film_of_the_color_it_is_used_with() {
|
||||
let cell = stream("/PatternType 1 /PaintType 2 /TilingType 1 /BBox [0 0 10 10] /XStep 10 /YStep 10 /Resources << >>", b"0 0 10 10 re f");
|
||||
let resources = format!("/ColorSpace << /PCS [/Pattern {GOLD}] >> /Pattern << /P1 5 0 R >>");
|
||||
let s = separate(&page_pdf("0 0 0 1 k 0 0 40 40 re f /PCS cs 0.5 /P1 scn 0 0 40 40 re f", &resources, &[cell]));
|
||||
assert_eq!(s.at(20, 20), [0, 0, 0, 0, 50], "the pattern's spot colour, knocking out black");
|
||||
assert_eq!(s.at(20, 20), [0, 0, 0, 0, 50], "the pattern's spot color, knocking out black");
|
||||
}
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
fn soft_masks_keep_the_luminosity_of_their_own_colours() {
|
||||
fn soft_masks_keep_the_luminosity_of_their_own_colors() {
|
||||
// A mask drawn in blue lets about a tenth of the black through. Drawn as the black
|
||||
// plate's film, blue (no black ink) would read as white and let all of it through.
|
||||
let group = stream("/Type /XObject /Subtype /Form /BBox [0 0 40 40] /Group << /S /Transparency /CS /DeviceRGB >>", b"0 0 1 rg 0 0 40 40 re f");
|
||||
@@ -263,12 +263,12 @@ fn the_ink_sink_reports_spot_inks_of_patterns_and_images_but_not_of_soft_masks()
|
||||
let seen = seen.lock().unwrap();
|
||||
let names: Vec<&str> = seen.iter().map(|(ink, _)| ink.name()).collect();
|
||||
assert_eq!(names, ["Silver", "Gold"], "in the order first painted; a mask's ink doesn't print");
|
||||
assert_eq!(seen[0].1, [128, 128, 128], "Silver at 100% is its alternate colour");
|
||||
assert_eq!(seen[0].1, [128, 128, 128], "Silver at 100% is its alternate color");
|
||||
}
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
fn malformed_colour_spaces_and_overprint_parameters_draw_what_they_can() {
|
||||
fn malformed_color_spaces_and_overprint_parameters_draw_what_they_can() {
|
||||
let resources = "/ColorSpace << /A [/DeviceN [] /DeviceGray 0] /B [/Separation] /C [/Indexed /DeviceCMYK 300 <00>] >> /ExtGState << /G << /OP 7 /OPM /X /op (y) >> >>";
|
||||
let pdf = page_pdf("/G gs /A cs 1 scn 0 0 9 9 re f /B cs 1 scn /C cs 255 scn 0 0 40 40 re f", resources, &[]);
|
||||
plates(&pdf, &inks(&["Gold"]), true, None);
|
||||
@@ -343,7 +343,7 @@ fn device_gray_stays_on_the_black_plate_under_a_simulation() {
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
fn cie_and_icc_colours_convert_through_the_profile_relative_to_their_white() {
|
||||
fn cie_and_icc_colors_convert_through_the_profile_relative_to_their_white() {
|
||||
let resources =
|
||||
"/ColorSpace << /D50 [/Lab << /WhitePoint [0.9642 1 0.8249] >>] /D65 [/Lab << /WhitePoint [0.9505 1 1.089] >>] /Gray [/ICCBased 5 0 R] >>";
|
||||
let content = "/D50 cs 50 20 -10 scn 0 0 10 40 re f /D65 cs 100 0 0 scn 10 0 10 40 re f /Gray cs 0.5 scn 20 0 10 40 re f";
|
||||
@@ -426,7 +426,7 @@ impl CmykConversion for Fixed {
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
fn a_callers_cmyk_conversion_separates_process_colour() {
|
||||
fn a_callers_cmyk_conversion_separates_process_color() {
|
||||
let profile = synthetic_icc::cmyk_profile(PRESS, true);
|
||||
let xyz = Arc::default();
|
||||
let simulation = CmykSimulation::with_conversion(&profile, Fixed(Arc::clone(&xyz)));
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
/// Grid points per input of the BToA table: fine enough that colours a little off the neutral
|
||||
/// Grid points per input of the BToA table: fine enough that colors a little off the neutral
|
||||
/// axis interpolate between unclamped grid points.
|
||||
const BTOA_GRID: usize = 17;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ Print separations for the Craft apps:
|
||||
- `coverage`: ink coverage at a pixel and over a page, total area coverage (TAC) per pixel,
|
||||
and the pixels and regions over a TAC limit.
|
||||
- `composite`: an sRGB preview of chosen plates.
|
||||
- `cms`: process colour conversion into a CMYK printing condition through craft-cms.
|
||||
- `cms`: process color conversion into a CMYK printing condition through craft-cms.
|
||||
|
||||
## Plates from an exported PDF
|
||||
|
||||
@@ -44,9 +44,9 @@ Inks are found by a low-resolution pass that records each spot ink a paint uses,
|
||||
first painted. Spot inks used only inside soft masks are left out. Each spot gets a Lab
|
||||
alternate measured from its sRGB appearance at 100%, so out-of-sRGB spots are clipped.
|
||||
|
||||
### Process colour
|
||||
### Process color
|
||||
|
||||
RGB, CIE-based and ICCBased colours become CMYK through, in order:
|
||||
RGB, CIE-based and ICCBased colors become CMYK through, in order:
|
||||
|
||||
1. the CMYK profile of the page's or the document's output intent (a `GTS_PDFX` intent first),
|
||||
when craft-cms can convert into it;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
//! Process colour conversion for plate mode through craft-cms.
|
||||
//! Process color conversion for plate mode through craft-cms.
|
||||
|
||||
use std::sync::{Arc, OnceLock};
|
||||
|
||||
use craft_cms::{Builtin, ColorSpace, Intent, Profile, Transform, TransformOptions, builtin, cached, math};
|
||||
use craft_pdf::interpret::color::{CmykConversion, CmykSimulation};
|
||||
|
||||
/// Converts process colour into a CMYK printing condition with craft-cms: relative
|
||||
/// Converts process color into a CMYK printing condition with craft-cms: relative
|
||||
/// colorimetric, without black point compensation, as the plate renderer expects (see
|
||||
/// [`CmykConversion`]). CMYK shows as sRGB relative colorimetric with black point
|
||||
/// compensation. Transforms are built on first use and shared through craft-cms's cache.
|
||||
@@ -55,7 +55,7 @@ impl CmsConversion {
|
||||
}
|
||||
|
||||
/// A plate-mode printing condition converting through this, for the profile bytes `icc`
|
||||
/// this was made from. ICCBased CMYK colours embedding those same bytes separate as they
|
||||
/// this was made from. ICCBased CMYK colors embedding those same bytes separate as they
|
||||
/// are.
|
||||
pub fn simulation(self, icc: &[u8]) -> CmykSimulation {
|
||||
CmykSimulation::with_conversion(icc, self)
|
||||
@@ -131,7 +131,7 @@ impl CmykConversion for CmsConversion {
|
||||
}
|
||||
}
|
||||
|
||||
/// CIE L\*a\*b\* (D50) of an sRGB colour, relative colorimetric; `None` if craft-cms can't
|
||||
/// CIE L\*a\*b\* (D50) of an sRGB color, relative colorimetric; `None` if craft-cms can't
|
||||
/// convert.
|
||||
pub(crate) fn srgb8_to_lab(rgb: [u8; 3]) -> Option<[f32; 3]> {
|
||||
static T: OnceLock<Option<Arc<Transform>>> = OnceLock::new();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! The ink model: which inks a job prints with, and colours as tints of those inks.
|
||||
//! The ink model: which inks a job prints with, and colors as tints of those inks.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
@@ -21,7 +21,7 @@ impl Process {
|
||||
/// The four process inks, in plate order.
|
||||
pub const ALL: [Process; 4] = [Process::Cyan, Process::Magenta, Process::Yellow, Process::Black];
|
||||
|
||||
/// The colorant name a `Separation` or `DeviceN` colour space gives this ink.
|
||||
/// The colorant name a `Separation` or `DeviceN` color space gives this ink.
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
Self::Cyan => "Cyan",
|
||||
@@ -36,13 +36,13 @@ impl Process {
|
||||
Self::ALL.into_iter().find(|p| p.name() == name)
|
||||
}
|
||||
|
||||
/// The ink's position in a CMYK colour.
|
||||
/// The ink's position in a CMYK color.
|
||||
pub fn index(self) -> usize {
|
||||
self as usize
|
||||
}
|
||||
}
|
||||
|
||||
/// How a spot ink looks, for previews and for printing it as process colour.
|
||||
/// How a spot ink looks, for previews and for printing it as process color.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Alternate {
|
||||
/// CMYK components, `0.0..=1.0`.
|
||||
@@ -54,7 +54,7 @@ pub enum Alternate {
|
||||
/// A spot ink.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Spot {
|
||||
/// The colorant name, as a `Separation` colour space would name it, without PDF name
|
||||
/// The colorant name, as a `Separation` color space would name it, without PDF name
|
||||
/// escapes (see [`normalize_name`]).
|
||||
pub name: String,
|
||||
/// The ink at 100%.
|
||||
@@ -135,7 +135,7 @@ impl InkSet {
|
||||
|
||||
/// Adds `ink` and returns its id. An ink whose name is already in the set (compared after
|
||||
/// [`normalize_name`]) is not added again, and its existing id is returned; a spot named
|
||||
/// `Cyan` … `Black` is the process ink. A spot's name is stored normalised. `None` for the
|
||||
/// `Cyan` … `Black` is the process ink. A spot's name is stored normalized. `None` for the
|
||||
/// names `All` and `None`, which are not inks (§8.6.6.4), and when the set is full
|
||||
/// (65 536 inks).
|
||||
pub fn add(&mut self, ink: Ink) -> Option<InkId> {
|
||||
@@ -338,14 +338,14 @@ impl InkSet {
|
||||
}
|
||||
}
|
||||
|
||||
/// A colour as ink tints.
|
||||
/// A color as ink tints.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum InkColor {
|
||||
/// Tints `0.0..=1.0` of the listed inks; other inks are unspecified (they keep what is
|
||||
/// under the paint when it overprints, and are knocked out otherwise). One entry is a
|
||||
/// `Separation` colour, several a `DeviceN` one.
|
||||
/// `Separation` color, several a `DeviceN` one.
|
||||
Tints(Vec<(InkId, f32)>),
|
||||
/// The same tint on every plate: the registration colour (the `All` colorant).
|
||||
/// The same tint on every plate: the registration color (the `All` colorant).
|
||||
All(f32),
|
||||
/// No ink on any plate (the `None` colorant).
|
||||
None,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! that overprints without naming the ink leaves the film as it is (ISO 32000-2 §8.6.7).
|
||||
//! Clipping, anti-aliasing, soft masks, transparency groups and blending stay the renderer's
|
||||
//! own. `Separation` and `DeviceN` colorants paint their own plates, DeviceCMYK its four
|
||||
//! components, DeviceGray black only, and other process colour converts to CMYK through the
|
||||
//! components, DeviceGray black only, and other process color converts to CMYK through the
|
||||
//! printing condition (see [`Conversion`]).
|
||||
//!
|
||||
//! Ported from PdfCraft #2770 by Guillem Hermida (`crates/render/src/separations.rs` at
|
||||
@@ -50,7 +50,7 @@ const MAX_PROFILE_BYTES: usize = 16 << 20;
|
||||
/// The longest output condition kept, in characters.
|
||||
const MAX_CONDITION: usize = 160;
|
||||
|
||||
/// The printing condition process colour converts to when the page has no usable output
|
||||
/// The printing condition process color converts to when the page has no usable output
|
||||
/// intent.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub enum Fallback {
|
||||
@@ -59,7 +59,7 @@ pub enum Fallback {
|
||||
Fogra39,
|
||||
/// The caller's CMYK ICC profile.
|
||||
Profile(Arc<[u8]>),
|
||||
/// The ISO 32000-2 §10.4.2.4 device formulas, black generation and undercolour removal the
|
||||
/// The ISO 32000-2 §10.4.2.4 device formulas, black generation and undercolor removal the
|
||||
/// identity: neutral RGB goes to black alone, ICCBased CMYK separates as it is.
|
||||
DeviceFormulas,
|
||||
}
|
||||
@@ -67,7 +67,7 @@ pub enum Fallback {
|
||||
/// How [`plates`] separates.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Options {
|
||||
/// Honour `OP`, `op` and `OPM` as a separating device does. Without it every paint knocks
|
||||
/// Honor `OP`, `op` and `OPM` as a separating device does. Without it every paint knocks
|
||||
/// out what is under it.
|
||||
pub overprint: bool,
|
||||
/// The printing condition when the page has no output intent with a usable CMYK profile.
|
||||
@@ -80,7 +80,7 @@ impl Default for Options {
|
||||
}
|
||||
}
|
||||
|
||||
/// How process colour that isn't CMYK already became CMYK.
|
||||
/// How process color that isn't CMYK already became CMYK.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Conversion {
|
||||
/// Through the CMYK profile of the page's or document's output intent (ISO 32000-2
|
||||
@@ -179,7 +179,7 @@ pub fn plates(pdf: &[u8], page: usize, dpi: f32, opts: &Options) -> Result<Plate
|
||||
}
|
||||
let alternate = Alternate::Lab(srgb8_to_lab(swatch).unwrap_or([0.0; 3]));
|
||||
let spot = Ink::Spot(Spot { name: ink.name().to_string(), alternate, solidity: None });
|
||||
// A name that normalises to one already listed (`A#2341` and `AA`) has no plate of its
|
||||
// A name that normalizes to one already listed (`A#2341` and `AA`) has no plate of its
|
||||
// own.
|
||||
match inks.add(spot) {
|
||||
Some(id) if id.index() == separated.len() => separated.push(ink),
|
||||
@@ -207,7 +207,7 @@ fn render<'a>(
|
||||
settings: &InterpreterSettings,
|
||||
scale: f32,
|
||||
) -> Result<raster::Raster, Error> {
|
||||
// The plate's gray film must keep its tints: no colour replacement.
|
||||
// The plate's gray film must keep its tints: no color replacement.
|
||||
let options = raster::Options { scale: [scale, scale], background: [255; 4], color_replacement: None, ..Default::default() };
|
||||
Ok(raster::render(page, cache, settings, &options)?)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ fn stream(dict: &str, data: &[u8]) -> Vec<u8> {
|
||||
out
|
||||
}
|
||||
|
||||
/// A spot colour whose alternate is a yellowish CMYK.
|
||||
/// A spot color whose alternate is a yellowish CMYK.
|
||||
const GOLD: &str = "[/Separation /Gold /DeviceCMYK << /FunctionType 2 /Domain [0 1] /C0 [0 0 0 0] /C1 [0 0.3 1 0] /N 1 >>]";
|
||||
|
||||
/// Black over the page, Gold at 50% in the middle square, overprinting when `gs` sets `op`.
|
||||
@@ -101,7 +101,7 @@ fn near(got: [u8; 4], expected: [u8; 4]) -> bool {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn process_colour_converts_through_the_output_intent_else_the_fallback() {
|
||||
fn process_color_converts_through_the_output_intent_else_the_fallback() {
|
||||
let synthetic = builtin::COATED_CMYK_ICC;
|
||||
let intent = "/OutputIntents [<< /Type /OutputIntent /S /GTS_PDFX /OutputConditionIdentifier (Synthetic press) /DestOutputProfile 5 0 R >>]";
|
||||
let red = |catalog: &str| page_pdf("1 0 0 rg 0 0 40 40 re f", "", catalog, &[stream("/N 4", synthetic)]);
|
||||
@@ -145,7 +145,7 @@ fn spot_inks_past_the_cap_are_listed_not_separated_and_bad_input_is_refused() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lab_colours_convert_through_the_profile_and_lab_white_is_paper() {
|
||||
fn lab_colors_convert_through_the_profile_and_lab_white_is_paper() {
|
||||
let resources = "/ColorSpace << /D50 [/Lab << /WhitePoint [0.9642 1 0.8249] >>] /D65 [/Lab << /WhitePoint [0.9505 1 1.089] >>] >>";
|
||||
let pdf = page_pdf("/D50 cs 50 20 -10 scn 0 0 20 40 re f /D65 cs 100 0 0 scn 20 0 20 40 re f", resources, "", &[]);
|
||||
let p = plates(&pdf, 0, 72.0, &Options::default()).unwrap();
|
||||
|
||||
Vendored
+6
-6
@@ -13,7 +13,7 @@ re-sync brings these PdfCraft changes:
|
||||
|
||||
| PdfCraft PR | Crate | Change |
|
||||
|---|---|---|
|
||||
| #1691 | hayro-interpret | Patch 28: images with few possible pixel values convert each value once (spot-colour images) |
|
||||
| #1691 | hayro-interpret | Patch 28: images with few possible pixel values convert each value once (spot-color images) |
|
||||
| #1903, #3316 | hayro-syntax | CCITT images that declare `/Rows 0`, or fewer `/Rows` than `/Height`, decode to their height |
|
||||
| #1954 | hayro-syntax | ASCII85 decoding stops at the stream's decode limit (here the per-document limit) |
|
||||
| #1982 | hayro-syntax | `Page::base_dimensions` keeps a one-point floor after `/UserUnit` |
|
||||
@@ -26,19 +26,19 @@ re-sync brings these PdfCraft changes:
|
||||
| #2035 | hayro-syntax | Flate back-references are copied in runs |
|
||||
| #3356 | hayro | A tiling pattern drawn once shows its cell at full scale |
|
||||
| #3378 | hayro-syntax | Patch 20: spaces or tabs between `stream` and its line break are accepted |
|
||||
| #3363 | hayro-syntax | A JP2 image in a colour space the decoder refuses is drawn by its component count |
|
||||
| #3363 | hayro-syntax | A JP2 image in a color space the decoder refuses is drawn by its component count |
|
||||
| #3412 | hayro-interpret | Type 3 glyph bounding boxes are transformed to device space before shading bounds are intersected |
|
||||
|
||||
PdfCraft's vendored `vello_common` patch (clip-intersection performance) is not part of this
|
||||
reader snapshot.
|
||||
|
||||
Changes ported from PdfCraft pull requests that were open when they were ported, under the
|
||||
same MIT OR Apache-2.0 licence. Code comments keep the pull request's patch numbers, except
|
||||
same MIT OR Apache-2.0 license. Code comments keep the pull request's patch numbers, except
|
||||
where noted below.
|
||||
|
||||
| PdfCraft PR | Author | Source commit | Files | Change |
|
||||
|---|---|---|---|---|
|
||||
| [#2770](https://github.com/storytold/pdfcraft/pull/2770) | Guillem Hermida (guillehr2) | [6fcf2a4](https://github.com/guillehr2/pdfcraft/commit/6fcf2a4aca29e943e28cb69017ff8f87d00656c6) | hayro-interpret `color.rs`, `interpret/mod.rs`, `interpret/path.rs`, `interpret/state.rs`, `pattern.rs`, `shading.rs`, `soft_mask.rs`, `x_object.rs` | Patches 35 and 36, plate mode: `InterpreterSettings::plate` draws one ink's separation as a gray film (`color::Plate`, `ColorSpace::ink_use`/`ink_tint`); the graphics state reads `OP`, `op` and `OPM` and an overprinting paint that doesn't specify the plate's ink leaves the plate as it is (ISO 32000-2 §8.6.7); `InterpreterSettings::ink_sink` reports spot inks; `color::CmykSimulation` converts process colour to an output intent's CMYK. Only the vendored interpreter part is ported; PdfCraft's `separations.rs` and Output Preview UI are not |
|
||||
| [#2770](https://github.com/storytold/pdfcraft/pull/2770) | Guillem Hermida (guillehr2) | [6fcf2a4](https://github.com/guillehr2/pdfcraft/commit/6fcf2a4aca29e943e28cb69017ff8f87d00656c6) | hayro-interpret `color.rs`, `interpret/mod.rs`, `interpret/path.rs`, `interpret/state.rs`, `pattern.rs`, `shading.rs`, `soft_mask.rs`, `x_object.rs` | Patches 35 and 36, plate mode: `InterpreterSettings::plate` draws one ink's separation as a gray film (`color::Plate`, `ColorSpace::ink_use`/`ink_tint`); the graphics state reads `OP`, `op` and `OPM` and an overprinting paint that doesn't specify the plate's ink leaves the plate as it is (ISO 32000-2 §8.6.7); `InterpreterSettings::ink_sink` reports spot inks; `color::CmykSimulation` converts process color to an output intent's CMYK. Only the vendored interpreter part is ported; PdfCraft's `separations.rs` and Output Preview UI are not |
|
||||
| [#2974](https://github.com/storytold/pdfcraft/pull/2974) | mtlcl410 | [bae6981](https://github.com/mtlcl410/pdfcraft/commit/bae69819594a6385a027fec1f67e6b3c36c259b4) | hayro-interpret `device.rs`, `x_object.rs`; hayro `renderer.rs` | Knockout groups (`/K true`) knock out: while one is innermost, fills, strokes, glyph outlines and shadings are drawn with `Compose::Copy` (weighted by coverage); an unmasked image's rectangle (`Device::knockout_image`) and a nested group's shape (an erase pass between `Device::begin_knockout_erase` and `end_knockout_erase`) are cleared before their layer composites; a transparency group drawn in a knockout group always gets a layer of its own. Masked images and stencils composite as before |
|
||||
|
||||
Code comments label #2974's changes `Knockout patch (pdfcraft #2974)` instead of a number: the
|
||||
@@ -49,9 +49,9 @@ object where two objects overlap. The erase pass resolves the group's resources
|
||||
`Resources::from_scope`, as the group's own draw does in this tree.
|
||||
|
||||
The output-intent conversion of patch 36 goes through a `color::CmykConversion` trait, so
|
||||
that callers can convert with their own colour management. `CmykSimulation::new` keeps
|
||||
that callers can convert with their own color management. `CmykSimulation::new` keeps
|
||||
#2770's moxcms conversion as the default, and `CmykSimulation::with_conversion` takes a
|
||||
caller's. Lab and ICCBased colours reach the conversion as CIE XYZ relative to the D50 PCS
|
||||
caller's. Lab and ICCBased colors reach the conversion as CIE XYZ relative to the D50 PCS
|
||||
white (`color::PCS_WHITE`); the moxcms conversion takes them on through #2770's ProPhoto hub.
|
||||
`crates/pdf/tests/plates.rs` adapts #2770's plate tests to the raster path, with its
|
||||
synthetic ICC profiles in `crates/pdf/tests/support/synthetic_icc.rs`.
|
||||
|
||||
Vendored
+1
-1
@@ -182,7 +182,7 @@
|
||||
"path": "src/color.rs",
|
||||
"source_sha256": "799ce29bb5e59c8fc94db202873e48c2047dd35962e6f26efd215156c47158c1",
|
||||
"source_git_blob": "56bb04f24c04ba33ab6bf99c02a24735670959ad",
|
||||
"sha256": "ed70bdb9618cf4d65032e977efe60b4d36f868fa4040db1012bfaf9ab4f5fb6e"
|
||||
"sha256": "50a039fbf0d8122b31fe03c0a06e2d4bb2994f50fd04072f6637233bc2ff9eb6"
|
||||
},
|
||||
{
|
||||
"path": "src/context.rs",
|
||||
|
||||
Vendored
+15
-15
@@ -785,7 +785,7 @@ impl Lab {
|
||||
]
|
||||
}
|
||||
|
||||
/// PdfCraft patch (36): the colour `input` as XYZ relative to [`PCS_WHITE`], relative
|
||||
/// PdfCraft patch (36): the color `input` as XYZ relative to [`PCS_WHITE`], relative
|
||||
/// colorimetric: the space's white point becomes the PCS white (Bradford-adapted).
|
||||
fn to_pcs(&self, input: &[f32], manual_scale: bool) -> [f32; 3] {
|
||||
let xyz = self.xyz(self.components(input, manual_scale));
|
||||
@@ -1091,8 +1091,8 @@ impl ICCProfile {
|
||||
})))
|
||||
}
|
||||
|
||||
/// PdfCraft patch (36): `input` (whole colours of this profile's components) as XYZ
|
||||
/// relative to [`PCS_WHITE`], three values per colour in `xyz`, through the separation hub
|
||||
/// PdfCraft patch (36): `input` (whole colors of this profile's components) as XYZ
|
||||
/// relative to [`PCS_WHITE`], three values per color in `xyz`, through the separation hub
|
||||
/// (see [`Hub`]). L*a*b* components are scaled to the profile's encoding unless
|
||||
/// `manual_scale` says they already are (an Indexed palette's).
|
||||
fn to_pcs(&self, input: &[f32], manual_scale: bool, xyz: &mut [f32]) -> Option<()> {
|
||||
@@ -1125,9 +1125,9 @@ impl ICCProfile {
|
||||
};
|
||||
}
|
||||
transform.transform(encoded, xyz).ok()?;
|
||||
for colour in xyz.chunks_exact_mut(3) {
|
||||
let pcs = HUB.to_pcs(&[colour[0], colour[1], colour[2]]);
|
||||
colour.copy_from_slice(&pcs);
|
||||
for color in xyz.chunks_exact_mut(3) {
|
||||
let pcs = HUB.to_pcs(&[color[0], color[1], color[2]]);
|
||||
color.copy_from_slice(&pcs);
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
@@ -1456,15 +1456,15 @@ struct SimulationRepr {
|
||||
}
|
||||
|
||||
/// The conversion into a [`CmykSimulation`]'s CMYK, relative colorimetric. Each call converts
|
||||
/// whole colours, at most 256 of them; CMYK components are `0.0..=1.0`, four per colour. A
|
||||
/// method returns `None` when it can't convert, and the colour then separates by the device
|
||||
/// whole colors, at most 256 of them; CMYK components are `0.0..=1.0`, four per color. A
|
||||
/// method returns `None` when it can't convert, and the color then separates by the device
|
||||
/// formulas.
|
||||
pub trait CmykConversion: Send + Sync {
|
||||
/// sRGB colours, gamma-encoded, three components in `0.0..=1.0` per colour, to CMYK.
|
||||
/// sRGB colors, gamma-encoded, three components in `0.0..=1.0` per color, to CMYK.
|
||||
fn from_srgb(&self, rgb: &[f32], cmyk: &mut [f32]) -> Option<()>;
|
||||
|
||||
/// CIE XYZ colours relative to [`PCS_WHITE`] (the Y of white is 1), three components per
|
||||
/// colour, to CMYK. The source's white has already been adapted to the PCS white.
|
||||
/// CIE XYZ colors relative to [`PCS_WHITE`] (the Y of white is 1), three components per
|
||||
/// color, to CMYK. The source's white has already been adapted to the PCS white.
|
||||
fn from_pcs_xyz(&self, xyz: &[f32], cmyk: &mut [f32]) -> Option<()>;
|
||||
|
||||
/// CMYK bytes, four per pixel, to sRGB bytes, three per pixel, to show what the printing
|
||||
@@ -1487,7 +1487,7 @@ pub trait CmykConversion: Send + Sync {
|
||||
}
|
||||
|
||||
/// The D50 white of the ICC profile connection space (ICC.1 §7.2.16), the white that
|
||||
/// [`CmykConversion::from_pcs_xyz`] takes its colours relative to.
|
||||
/// [`CmykConversion::from_pcs_xyz`] takes its colors relative to.
|
||||
pub const PCS_WHITE: [f32; 3] = [0.9642, 1.0, 0.8249];
|
||||
|
||||
impl Debug for CmykSimulation {
|
||||
@@ -1530,7 +1530,7 @@ impl CmykSimulation {
|
||||
}
|
||||
|
||||
/// The printing condition of the CMYK ICC profile `profile`, converted to by `conversion`,
|
||||
/// which the caller made from that profile. ICCBased CMYK colours in `profile` itself stay
|
||||
/// which the caller made from that profile. ICCBased CMYK colors in `profile` itself stay
|
||||
/// as they are.
|
||||
pub fn with_conversion(profile: &[u8], conversion: impl CmykConversion + 'static) -> Self {
|
||||
Self(Arc::new(SimulationRepr {
|
||||
@@ -1569,7 +1569,7 @@ impl CmykSimulation {
|
||||
}
|
||||
}
|
||||
|
||||
/// PdfCraft patch (36): the conversion [`CmykSimulation::new`] makes with moxcms. XYZ colours
|
||||
/// PdfCraft patch (36): the conversion [`CmykSimulation::new`] makes with moxcms. XYZ colors
|
||||
/// pass through the separation hub (see [`Hub`]).
|
||||
struct MoxcmsConversion {
|
||||
description: Option<String>,
|
||||
@@ -1708,7 +1708,7 @@ fn transform_u8(
|
||||
|
||||
static SRGB: LazyLock<ColorProfile> = LazyLock::new(ColorProfile::new_srgb);
|
||||
|
||||
/// PdfCraft patch (36): the separation hub, the RGB that ICCBased colours leave their profile
|
||||
/// PdfCraft patch (36): the separation hub, the RGB that ICCBased colors leave their profile
|
||||
/// in, and that [`MoxcmsConversion`] takes PCS XYZ to its CMYK through: ROMM RGB (ProPhoto)
|
||||
/// primaries, D50 white, gamma 1.8. Its
|
||||
/// gamut holds practically every surface colour, so nothing printable clips on the way, and
|
||||
|
||||
Reference in new issue
Block a user