mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-02 08:43:57 +00:00
pdf: CMYK blending without an output intent for plain print PDFs
print::cmyk_blending(profile) blends transparency in CMYK and writes no output intent or /Trapped, as a non-PDF/X print PDF does. print::settings builds on it and adds the GTS_PDFX output intent and /Trapped /False.
This commit is contained in:
1 parent
0fe6156614
commit
8fbfea8840
3 files changed
+50
-21
No files matched your search
@@ -122,10 +122,10 @@ serialization uses the same backend version as before extraction. It provides:
|
||||
|
||||
### Print color
|
||||
|
||||
`write::print::settings` returns `SerializeSettings` for CMYK print: DeviceCMYK color,
|
||||
transparency blending in CMYK (`GroupColorSpace::Cmyk`), the document's CMYK profile as a
|
||||
`GTS_PDFX` output intent and `/Trapped /False`. The profile is the document's working space;
|
||||
print export always carries it. craft-pdf takes the profile bytes and does not depend on
|
||||
`write::print::cmyk_blending(profile)` returns `SerializeSettings` for a plain CMYK print
|
||||
PDF: DeviceCMYK color and transparency blending in CMYK (`GroupColorSpace::Cmyk`), with no
|
||||
output intent. `write::print::settings` adds the document's CMYK profile as a `GTS_PDFX`
|
||||
output intent and `/Trapped /False`, for PDF/X. The profile is the document's working space. craft-pdf takes the profile bytes and does not depend on
|
||||
craft-cms. Its CC0 `builtin::COATED_FOGRA39_ICC` is the default working space, described by
|
||||
`PrintColor::fogra39`:
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
//! Serialization settings for CMYK print output.
|
||||
//!
|
||||
//! The document's CMYK profile, its working space, describes the printing condition: the
|
||||
//! settings write it as the `GTS_PDFX` output intent, and DeviceCMYK content and the CMYK
|
||||
//! blending groups are interpreted through it. This module takes the profile bytes and has no
|
||||
//! The document's CMYK profile, its working space, describes the printing condition.
|
||||
//! [`cmyk_blending`] blends transparency in CMYK and writes no output intent, like a plain
|
||||
//! print PDF; [`settings`] also writes the profile as the `GTS_PDFX` output intent, through
|
||||
//! which DeviceCMYK content and the CMYK blending groups are interpreted, as PDF/X needs. This module takes the profile bytes and has no
|
||||
//! color-management dependency; craft-cms's `builtin::COATED_FOGRA39_ICC` is a suitable
|
||||
//! default profile, described by [`PrintColor::fogra39`].
|
||||
//!
|
||||
@@ -42,28 +43,41 @@ impl<'a> PrintColor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Settings for CMYK print output: DeviceCMYK color, CMYK blending groups, the profile as
|
||||
/// the `GTS_PDFX` output intent (and as `cmyk_profile`) and `/Trapped /False`. Other fields
|
||||
/// keep their defaults; override them with struct update syntax.
|
||||
/// Settings for a CMYK print PDF without an output intent: DeviceCMYK color and CMYK
|
||||
/// blending groups, with `profile` as `cmyk_profile`. Other fields keep their defaults;
|
||||
/// override them with struct update syntax.
|
||||
///
|
||||
/// Fails with [`WriteError::InvalidProfile`] when `profile` is not a readable CMYK ICC
|
||||
/// profile.
|
||||
pub fn settings(color: PrintColor<'_>) -> Result<SerializeSettings, WriteError> {
|
||||
pub fn cmyk_blending(profile: &[u8]) -> Result<SerializeSettings, WriteError> {
|
||||
guard(|| {
|
||||
let profile = ICCProfile::<4>::new(color.profile).ok_or(WriteError::InvalidProfile)?;
|
||||
let profile = ICCProfile::<4>::new(profile).ok_or(WriteError::InvalidProfile)?;
|
||||
Ok(SerializeSettings {
|
||||
no_device_cs: false,
|
||||
cmyk_profile: Some(profile.clone()),
|
||||
cmyk_profile: Some(profile),
|
||||
group_color_space: GroupColorSpace::Cmyk,
|
||||
output_intent: Some(OutputIntent {
|
||||
profile,
|
||||
condition_identifier: color.condition_identifier.to_owned(),
|
||||
condition: color.condition.map(str::to_owned),
|
||||
registry_name: color.registry_name.map(str::to_owned),
|
||||
info: color.info.map(str::to_owned),
|
||||
}),
|
||||
trapped: Some(Trapped::False),
|
||||
..SerializeSettings::default()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// [`cmyk_blending`] plus the profile as the `GTS_PDFX` output intent and `/Trapped /False`,
|
||||
/// for PDF/X export.
|
||||
///
|
||||
/// Fails with [`WriteError::InvalidProfile`] when `profile` is not a readable CMYK ICC
|
||||
/// profile.
|
||||
pub fn settings(color: PrintColor<'_>) -> Result<SerializeSettings, WriteError> {
|
||||
let settings = cmyk_blending(color.profile)?;
|
||||
let profile = settings.cmyk_profile.clone().ok_or(WriteError::InvalidProfile)?;
|
||||
Ok(SerializeSettings {
|
||||
output_intent: Some(OutputIntent {
|
||||
profile,
|
||||
condition_identifier: color.condition_identifier.to_owned(),
|
||||
condition: color.condition.map(str::to_owned),
|
||||
registry_name: color.registry_name.map(str::to_owned),
|
||||
info: color.info.map(str::to_owned),
|
||||
}),
|
||||
trapped: Some(Trapped::False),
|
||||
..settings
|
||||
})
|
||||
}
|
||||
@@ -987,6 +987,21 @@ fn print_settings_blend_in_cmyk_and_name_the_profile_as_the_output_intent() {
|
||||
assert!(!text.contains("GTS_PDFXVersion"));
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
fn cmyk_blending_writes_no_output_intent_or_trapped() {
|
||||
let settings = print::cmyk_blending(FOGRA39).unwrap();
|
||||
assert_eq!(settings.group_color_space, GroupColorSpace::Cmyk);
|
||||
assert!(settings.output_intent.is_none() && settings.trapped.is_none());
|
||||
|
||||
let bytes = sample(settings.clone(), placed(&settings).as_deref()).unwrap();
|
||||
let cmyk_group = Some(Some("DeviceCMYK".to_owned()));
|
||||
assert_eq!(groups(&bytes).pages, vec![cmyk_group.clone(), None, cmyk_group]);
|
||||
assert!(output_intents(&bytes).is_empty());
|
||||
assert!(!String::from_utf8_lossy(&bytes).contains("Trapped"));
|
||||
assert!(matches!(print::cmyk_blending(b"not a profile"), Err(WriteError::InvalidProfile)));
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), test)]
|
||||
fn print_settings_reject_a_profile_that_is_not_cmyk() {
|
||||
|
||||
Reference in new issue
Block a user