blitz-pdf 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +266 -12
- package/THIRD_PARTY_NOTICES.md +4 -2
- package/dist/browser.d.ts +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/document-options.d.ts +36 -0
- package/dist/document-options.d.ts.map +1 -0
- package/dist/document-options.js +236 -0
- package/dist/document-options.js.map +1 -0
- package/dist/node.d.ts +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/options.d.ts +35 -1
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +21 -14
- package/dist/options.js.map +1 -1
- package/dist/types.d.ts +71 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/validation.d.ts +2 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +7 -0
- package/dist/validation.js.map +1 -0
- package/examples/zugferd.mjs +41 -0
- package/licenses/RUST_DEPENDENCIES.txt +27 -0
- package/package.json +3 -2
- package/src/browser.ts +1 -1
- package/src/document-options.ts +218 -0
- package/src/node.ts +1 -1
- package/src/options.ts +18 -13
- package/src/types.ts +76 -1
- package/src/validation.ts +6 -0
- package/vendor/README.md +27 -2
- package/vendor/krilla/.cargo-ok +1 -0
- package/vendor/krilla/.cargo_vcs_info.json +6 -0
- package/vendor/krilla/Cargo.lock +1357 -0
- package/vendor/krilla/Cargo.toml +165 -0
- package/vendor/krilla/LICENSE_APACHE +202 -0
- package/vendor/krilla/LICENSE_MIT +21 -0
- package/vendor/krilla/README.md +156 -0
- package/vendor/krilla/examples/basic.rs +117 -0
- package/vendor/krilla/examples/empty_document.rs +25 -0
- package/vendor/krilla/examples/parley.rs +174 -0
- package/vendor/krilla/examples/simple_text.rs +118 -0
- package/vendor/krilla/examples/stream_builder.rs +93 -0
- package/vendor/krilla/icc/LICENSE +116 -0
- package/vendor/krilla/icc/README.md +1 -0
- package/vendor/krilla/icc/sGrey-v2-magic.icc +0 -0
- package/vendor/krilla/icc/sGrey-v4.icc +0 -0
- package/vendor/krilla/icc/sRGB-v2-magic.icc +0 -0
- package/vendor/krilla/icc/sRGB-v4.icc +0 -0
- package/vendor/krilla/src/chunk_container.rs +503 -0
- package/vendor/krilla/src/configure/PDF_A1.md +227 -0
- package/vendor/krilla/src/configure/PDF_A2.md +269 -0
- package/vendor/krilla/src/configure/PDF_A3.md +31 -0
- package/vendor/krilla/src/configure/PDF_A4.md +211 -0
- package/vendor/krilla/src/configure/PDF_UA1.md +202 -0
- package/vendor/krilla/src/configure/README.md +23 -0
- package/vendor/krilla/src/configure/mod.rs +197 -0
- package/vendor/krilla/src/configure/validate.rs +1244 -0
- package/vendor/krilla/src/configure/version.rs +134 -0
- package/vendor/krilla/src/content.rs +1352 -0
- package/vendor/krilla/src/data.rs +49 -0
- package/vendor/krilla/src/document.rs +156 -0
- package/vendor/krilla/src/error.rs +170 -0
- package/vendor/krilla/src/geom.rs +341 -0
- package/vendor/krilla/src/graphics/blend.rs +46 -0
- package/vendor/krilla/src/graphics/color.rs +552 -0
- package/vendor/krilla/src/graphics/graphic.rs +30 -0
- package/vendor/krilla/src/graphics/graphics_state.rs +251 -0
- package/vendor/krilla/src/graphics/icc.rs +218 -0
- package/vendor/krilla/src/graphics/image.rs +835 -0
- package/vendor/krilla/src/graphics/mask.rs +128 -0
- package/vendor/krilla/src/graphics/mod.rs +14 -0
- package/vendor/krilla/src/graphics/paint.rs +434 -0
- package/vendor/krilla/src/graphics/separation.rs +86 -0
- package/vendor/krilla/src/graphics/shading_function.rs +865 -0
- package/vendor/krilla/src/graphics/shading_pattern.rs +60 -0
- package/vendor/krilla/src/graphics/tiling_pattern.rs +119 -0
- package/vendor/krilla/src/graphics/xobject.rs +150 -0
- package/vendor/krilla/src/interactive/action.rs +68 -0
- package/vendor/krilla/src/interactive/annotation.rs +283 -0
- package/vendor/krilla/src/interactive/destination.rs +289 -0
- package/vendor/krilla/src/interactive/mod.rs +3 -0
- package/vendor/krilla/src/interchange/embed.rs +240 -0
- package/vendor/krilla/src/interchange/metadata.rs +564 -0
- package/vendor/krilla/src/interchange/mod.rs +4 -0
- package/vendor/krilla/src/interchange/outline.rs +263 -0
- package/vendor/krilla/src/interchange/tagging/fmt.rs +733 -0
- package/vendor/krilla/src/interchange/tagging/generate.toml +474 -0
- package/vendor/krilla/src/interchange/tagging/generated.rs +4754 -0
- package/vendor/krilla/src/interchange/tagging/mod.rs +1324 -0
- package/vendor/krilla/src/interchange/tagging/tag.rs +686 -0
- package/vendor/krilla/src/lib.rs +179 -0
- package/vendor/krilla/src/num.rs +26 -0
- package/vendor/krilla/src/page.rs +612 -0
- package/vendor/krilla/src/pdf.rs +313 -0
- package/vendor/krilla/src/resource.rs +436 -0
- package/vendor/krilla/src/serialize.rs +1101 -0
- package/vendor/krilla/src/stream.rs +368 -0
- package/vendor/krilla/src/surface.rs +664 -0
- package/vendor/krilla/src/text/cid.rs +488 -0
- package/vendor/krilla/src/text/font.rs +351 -0
- package/vendor/krilla/src/text/glyph/bitmap.rs +81 -0
- package/vendor/krilla/src/text/glyph/colr.rs +581 -0
- package/vendor/krilla/src/text/glyph/mod.rs +205 -0
- package/vendor/krilla/src/text/glyph/outline.rs +72 -0
- package/vendor/krilla/src/text/glyph/svg.rs +34 -0
- package/vendor/krilla/src/text/group.rs +463 -0
- package/vendor/krilla/src/text/mod.rs +232 -0
- package/vendor/krilla/src/text/shape.rs +102 -0
- package/vendor/krilla/src/text/type3.rs +514 -0
- package/vendor/krilla/src/util.rs +286 -0
- package/vendor/stylo/properties/longhands.toml +0 -1
- package/vendor/stylo/stylesheets/rule_parser.rs +1 -1
- package/wasm/blitz_pdf.js +10 -5
- package/wasm/blitz_pdf_bg.wasm +0 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
use std::hash::Hash;
|
|
2
|
+
use std::sync::Arc;
|
|
3
|
+
|
|
4
|
+
use pdf_writer::types::BlendMode;
|
|
5
|
+
use pdf_writer::{Finish, Name, Ref};
|
|
6
|
+
|
|
7
|
+
use crate::chunk_container::ChunkContainer;
|
|
8
|
+
use crate::configure::ValidationError;
|
|
9
|
+
use crate::geom::{Rect, Transform};
|
|
10
|
+
use crate::graphics::mask::Mask;
|
|
11
|
+
use crate::num::NormalizedF32;
|
|
12
|
+
use crate::resource;
|
|
13
|
+
use crate::resource::Resourceable;
|
|
14
|
+
use crate::serialize::{Cacheable, SerializeContext};
|
|
15
|
+
|
|
16
|
+
/// The inner representation of an external graphics state.
|
|
17
|
+
#[derive(Debug, Hash, PartialEq, Eq, Default, Clone)]
|
|
18
|
+
struct Repr {
|
|
19
|
+
/// The non-stroking alpha.
|
|
20
|
+
non_stroking_alpha: Option<NormalizedF32>,
|
|
21
|
+
/// The stroking alpha.
|
|
22
|
+
stroking_alpha: Option<NormalizedF32>,
|
|
23
|
+
/// The blend mode.
|
|
24
|
+
blend_mode: Option<BlendMode>,
|
|
25
|
+
/// An active mask.
|
|
26
|
+
mask: Option<Ref>,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// A graphics state containing information about
|
|
30
|
+
/// - The current stroking alpha.
|
|
31
|
+
/// - The current non-stroking alpha.
|
|
32
|
+
/// - The current blend mode.
|
|
33
|
+
/// - The current mask.
|
|
34
|
+
///
|
|
35
|
+
/// This struct provides exposes a builder pattern for setting the various properties
|
|
36
|
+
/// individually.
|
|
37
|
+
///
|
|
38
|
+
/// This type is cheap to clone.
|
|
39
|
+
#[derive(Debug, Clone, Hash, PartialEq, Eq, Default)]
|
|
40
|
+
pub(crate) struct ExtGState(Arc<Repr>);
|
|
41
|
+
|
|
42
|
+
impl ExtGState {
|
|
43
|
+
/// Create a new, empty graphics state.
|
|
44
|
+
pub(crate) fn new() -> Self {
|
|
45
|
+
Self::default()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// Create a new graphics state with a stroking alpha.
|
|
49
|
+
#[must_use]
|
|
50
|
+
pub(crate) fn stroking_alpha(mut self, stroking_alpha: NormalizedF32) -> Self {
|
|
51
|
+
Arc::make_mut(&mut self.0).stroking_alpha = Some(stroking_alpha);
|
|
52
|
+
self
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// Create a new graphics state with a non-stroking alpha.
|
|
56
|
+
#[must_use]
|
|
57
|
+
pub(crate) fn non_stroking_alpha(mut self, non_stroking_alpha: NormalizedF32) -> Self {
|
|
58
|
+
Arc::make_mut(&mut self.0).non_stroking_alpha = Some(non_stroking_alpha);
|
|
59
|
+
self
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/// Create a new graphics state with a blend mode.
|
|
63
|
+
#[must_use]
|
|
64
|
+
pub(crate) fn blend_mode(mut self, blend_mode: BlendMode) -> Self {
|
|
65
|
+
Arc::make_mut(&mut self.0).blend_mode = Some(blend_mode);
|
|
66
|
+
self
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// Create a new graphics state with a mask.
|
|
70
|
+
#[must_use]
|
|
71
|
+
pub(crate) fn mask(
|
|
72
|
+
mut self,
|
|
73
|
+
mask: Mask,
|
|
74
|
+
sc: &mut SerializeContext,
|
|
75
|
+
chunk_container: &mut ChunkContainer,
|
|
76
|
+
) -> Self {
|
|
77
|
+
let mask_ref = sc.register_cacheable(chunk_container, mask);
|
|
78
|
+
Arc::make_mut(&mut self.0).mask = Some(mask_ref);
|
|
79
|
+
self
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/// Check whether the graphics state is empty.
|
|
83
|
+
pub(crate) fn empty(&self) -> bool {
|
|
84
|
+
self.0.mask.is_none()
|
|
85
|
+
&& self.0.stroking_alpha.is_none()
|
|
86
|
+
&& self.0.non_stroking_alpha.is_none()
|
|
87
|
+
&& self.0.blend_mode.is_none()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// Integrate another graphics state into the current one. This is done by replacing
|
|
91
|
+
/// all active properties of the other graphics state in the current graphics state, while
|
|
92
|
+
/// leaving the inactive ones unchanged.
|
|
93
|
+
pub(crate) fn combine(&mut self, other: &ExtGState) {
|
|
94
|
+
if let Some(stroking_alpha) = other.0.stroking_alpha {
|
|
95
|
+
Arc::make_mut(&mut self.0).stroking_alpha = Some(stroking_alpha);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if let Some(non_stroking_alpha) = other.0.non_stroking_alpha {
|
|
99
|
+
Arc::make_mut(&mut self.0).non_stroking_alpha = Some(non_stroking_alpha);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if let Some(blend_mode) = other.0.blend_mode {
|
|
103
|
+
Arc::make_mut(&mut self.0).blend_mode = Some(blend_mode);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if let Some(mask) = other.0.mask {
|
|
107
|
+
Arc::make_mut(&mut self.0).mask = Some(mask);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
impl Cacheable for ExtGState {
|
|
113
|
+
fn serialize(
|
|
114
|
+
self,
|
|
115
|
+
sc: &mut SerializeContext,
|
|
116
|
+
chunk_container: &mut ChunkContainer,
|
|
117
|
+
root_ref: Ref,
|
|
118
|
+
) {
|
|
119
|
+
let chunk = &mut chunk_container.non_stream.ext_g_states;
|
|
120
|
+
|
|
121
|
+
let mut ext_st = chunk.ext_graphics(root_ref);
|
|
122
|
+
if let Some(nsa) = self.0.non_stroking_alpha {
|
|
123
|
+
if nsa != NormalizedF32::ONE {
|
|
124
|
+
sc.register_validation_error(ValidationError::Transparency(sc.location));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
ext_st.non_stroking_alpha(nsa.get());
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if let Some(sa) = self.0.stroking_alpha {
|
|
131
|
+
if sa != NormalizedF32::ONE {
|
|
132
|
+
sc.register_validation_error(ValidationError::Transparency(sc.location));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
ext_st.stroking_alpha(sa.get());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if let Some(bm) = self.0.blend_mode {
|
|
139
|
+
if bm != BlendMode::Normal {
|
|
140
|
+
sc.register_validation_error(ValidationError::Transparency(sc.location));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
ext_st.blend_mode(bm);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if let Some(mask_ref) = self.0.mask {
|
|
147
|
+
sc.register_validation_error(ValidationError::Transparency(sc.location));
|
|
148
|
+
|
|
149
|
+
ext_st.pair(Name(b"SMask"), mask_ref);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
ext_st.finish();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
impl Resourceable for ExtGState {
|
|
157
|
+
type Resource = resource::ExtGState;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/// A simulation of the PDF graphics state, so that we
|
|
161
|
+
/// can write our transforms/graphics state all at once
|
|
162
|
+
/// when adding an image/path instead of having to
|
|
163
|
+
/// use `save_state`/`restore_state` excessively.
|
|
164
|
+
#[derive(Debug, PartialEq, Clone)]
|
|
165
|
+
pub(crate) struct GraphicsState {
|
|
166
|
+
ext_g_state: ExtGState,
|
|
167
|
+
ctm: Transform,
|
|
168
|
+
}
|
|
169
|
+
impl Eq for GraphicsState {}
|
|
170
|
+
|
|
171
|
+
impl Hash for GraphicsState {
|
|
172
|
+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
173
|
+
self.ext_g_state.hash(state);
|
|
174
|
+
self.ctm.hash(state);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
impl Default for GraphicsState {
|
|
179
|
+
fn default() -> Self {
|
|
180
|
+
Self {
|
|
181
|
+
ext_g_state: ExtGState::new(),
|
|
182
|
+
ctm: Transform::identity(),
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
impl GraphicsState {
|
|
188
|
+
pub(crate) fn combine(&mut self, other: &ExtGState) {
|
|
189
|
+
self.ext_g_state.combine(other);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
pub(crate) fn concat_transform(&mut self, transform: Transform) {
|
|
193
|
+
self.ctm = self.ctm.pre_concat(transform);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
pub(crate) fn transform(&self) -> Transform {
|
|
197
|
+
self.ctm
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
pub(crate) fn ext_g_state(&self) -> &ExtGState {
|
|
201
|
+
&self.ext_g_state
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/// A collection of graphics states, simulates the stack-like
|
|
206
|
+
/// structure used.
|
|
207
|
+
#[derive(Debug, Hash, Eq, PartialEq)]
|
|
208
|
+
pub struct GraphicsStates {
|
|
209
|
+
graphics_states: Vec<GraphicsState>,
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
impl GraphicsStates {
|
|
213
|
+
pub(crate) fn new() -> Self {
|
|
214
|
+
GraphicsStates {
|
|
215
|
+
graphics_states: vec![GraphicsState::default()],
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
pub(crate) fn cur(&self) -> &GraphicsState {
|
|
220
|
+
self.graphics_states.last().unwrap()
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
pub(crate) fn cur_mut(&mut self) -> &mut GraphicsState {
|
|
224
|
+
self.graphics_states.last_mut().unwrap()
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
pub(crate) fn save_state(&mut self) {
|
|
228
|
+
let state = self.cur();
|
|
229
|
+
self.graphics_states.push(state.clone())
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
pub(crate) fn restore_state(&mut self) {
|
|
233
|
+
self.graphics_states.pop();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
pub(crate) fn combine(&mut self, other: &ExtGState) {
|
|
237
|
+
self.cur_mut().combine(other);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
pub(crate) fn transform(&mut self, transform: Transform) {
|
|
241
|
+
self.cur_mut().concat_transform(transform);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
pub(crate) fn transform_bbox(&self, bbox: Rect) -> Rect {
|
|
245
|
+
// Important: This does not take the root transform of the
|
|
246
|
+
// corresponding ContentBuilder into account, because we
|
|
247
|
+
// want it to be in krilla coordinates, not in PDF
|
|
248
|
+
// coordinates.
|
|
249
|
+
bbox.transform(self.cur().transform()).unwrap()
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
//! Using ICC profiles.
|
|
2
|
+
|
|
3
|
+
use std::ops::Deref;
|
|
4
|
+
use std::ops::DerefMut;
|
|
5
|
+
use std::sync::Arc;
|
|
6
|
+
|
|
7
|
+
use pdf_writer::{Finish, Name, Ref};
|
|
8
|
+
|
|
9
|
+
use crate::chunk_container::ChunkContainer;
|
|
10
|
+
use crate::resource;
|
|
11
|
+
use crate::resource::Resourceable;
|
|
12
|
+
use crate::serialize::{Cacheable, SerializeContext};
|
|
13
|
+
use crate::stream::{deflate_encode, FilterStreamBuilder};
|
|
14
|
+
use crate::util::Prehashed;
|
|
15
|
+
|
|
16
|
+
/// An ICC profile.
|
|
17
|
+
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
|
18
|
+
pub struct ICCProfile<const C: u8>(Arc<Prehashed<Repr>>);
|
|
19
|
+
|
|
20
|
+
impl<const C: u8> ICCProfile<C> {
|
|
21
|
+
/// Create a new ICC profile.
|
|
22
|
+
///
|
|
23
|
+
/// Returns `None` if the metadata of the profile couldn't be read or if the
|
|
24
|
+
/// number of channels of the underlying data does not correspond to the one
|
|
25
|
+
/// indicated in the constant parameter.
|
|
26
|
+
pub fn new(data: &[u8]) -> Option<Self> {
|
|
27
|
+
let metadata = ICCMetadata::from_data(data)?;
|
|
28
|
+
|
|
29
|
+
if metadata.color_space.num_components() != C {
|
|
30
|
+
return None;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Some(Self(Arc::new(Prehashed::new(Repr {
|
|
34
|
+
data: deflate_encode(data),
|
|
35
|
+
metadata,
|
|
36
|
+
}))))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
pub(crate) fn metadata(&self) -> &ICCMetadata {
|
|
40
|
+
&self.0.metadata
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
impl<const C: u8> Cacheable for ICCProfile<C> {
|
|
45
|
+
fn serialize(
|
|
46
|
+
self,
|
|
47
|
+
sc: &mut SerializeContext,
|
|
48
|
+
chunk_container: &mut ChunkContainer,
|
|
49
|
+
root_ref: Ref,
|
|
50
|
+
) {
|
|
51
|
+
let mut chunk = sc.new_chunk();
|
|
52
|
+
let icc_stream = FilterStreamBuilder::new_from_deflated(&self.0.deref().data)
|
|
53
|
+
.finish(&sc.serialize_settings());
|
|
54
|
+
|
|
55
|
+
let mut icc_profile = chunk.icc_profile(root_ref, icc_stream.encoded_data());
|
|
56
|
+
icc_profile.n(C as i32).range([0.0, 1.0].repeat(C as usize));
|
|
57
|
+
icc_stream.write_filters(icc_profile.deref_mut().deref_mut());
|
|
58
|
+
icc_profile.finish();
|
|
59
|
+
chunk_container.streams.icc_profiles.push(chunk);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#[cfg(feature = "raster-images")]
|
|
64
|
+
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
|
65
|
+
pub(crate) enum GenericICCProfile {
|
|
66
|
+
Luma(ICCProfile<1>),
|
|
67
|
+
Rgb(ICCProfile<3>),
|
|
68
|
+
Cmyk(ICCProfile<4>),
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#[cfg(feature = "raster-images")]
|
|
72
|
+
impl GenericICCProfile {
|
|
73
|
+
pub(crate) fn metadata(&self) -> &ICCMetadata {
|
|
74
|
+
match self {
|
|
75
|
+
GenericICCProfile::Luma(l) => l.metadata(),
|
|
76
|
+
GenericICCProfile::Rgb(r) => r.metadata(),
|
|
77
|
+
GenericICCProfile::Cmyk(c) => c.metadata(),
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#[cfg(feature = "raster-images")]
|
|
83
|
+
impl Cacheable for GenericICCProfile {
|
|
84
|
+
fn serialize(
|
|
85
|
+
self,
|
|
86
|
+
sc: &mut SerializeContext,
|
|
87
|
+
chunk_container: &mut ChunkContainer,
|
|
88
|
+
root_ref: Ref,
|
|
89
|
+
) {
|
|
90
|
+
match self {
|
|
91
|
+
GenericICCProfile::Luma(l) => l.serialize(sc, chunk_container, root_ref),
|
|
92
|
+
GenericICCProfile::Rgb(r) => r.serialize(sc, chunk_container, root_ref),
|
|
93
|
+
GenericICCProfile::Cmyk(c) => c.serialize(sc, chunk_container, root_ref),
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
|
99
|
+
pub(crate) struct ICCBasedColorSpace<const C: u8>(pub(crate) ICCProfile<C>);
|
|
100
|
+
|
|
101
|
+
impl<const C: u8> Cacheable for ICCBasedColorSpace<C> {
|
|
102
|
+
fn serialize(
|
|
103
|
+
self,
|
|
104
|
+
sc: &mut SerializeContext,
|
|
105
|
+
chunk_container: &mut ChunkContainer,
|
|
106
|
+
root_ref: Ref,
|
|
107
|
+
) {
|
|
108
|
+
let icc_ref = sc.register_cacheable(chunk_container, self.0.clone());
|
|
109
|
+
|
|
110
|
+
let chunk = &mut chunk_container.non_stream.color_spaces;
|
|
111
|
+
|
|
112
|
+
let mut array = chunk.indirect(root_ref).array();
|
|
113
|
+
array.item(Name(b"ICCBased"));
|
|
114
|
+
array.item(icc_ref);
|
|
115
|
+
array.finish();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
impl<const C: u8> Resourceable for ICCBasedColorSpace<C> {
|
|
120
|
+
type Resource = resource::ColorSpace;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
#[derive(Clone, Hash, Debug, Eq, PartialEq)]
|
|
124
|
+
pub(crate) enum ICCColorSpace {
|
|
125
|
+
Xyz,
|
|
126
|
+
Lab,
|
|
127
|
+
Luv,
|
|
128
|
+
Ycbr,
|
|
129
|
+
Yxy,
|
|
130
|
+
Lms,
|
|
131
|
+
Rgb,
|
|
132
|
+
Gray,
|
|
133
|
+
Hsv,
|
|
134
|
+
Hls,
|
|
135
|
+
Cmyk,
|
|
136
|
+
Cmy,
|
|
137
|
+
OneClr,
|
|
138
|
+
ThreeClr,
|
|
139
|
+
FourClr,
|
|
140
|
+
// There are more, but those should be the most important
|
|
141
|
+
// ones.
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
impl ICCColorSpace {
|
|
145
|
+
pub(crate) fn num_components(&self) -> u8 {
|
|
146
|
+
match self {
|
|
147
|
+
ICCColorSpace::Xyz => 3,
|
|
148
|
+
ICCColorSpace::Lab => 3,
|
|
149
|
+
ICCColorSpace::Luv => 3,
|
|
150
|
+
ICCColorSpace::Ycbr => 3,
|
|
151
|
+
ICCColorSpace::Yxy => 3,
|
|
152
|
+
ICCColorSpace::Lms => 3,
|
|
153
|
+
ICCColorSpace::Rgb => 3,
|
|
154
|
+
ICCColorSpace::Gray => 1,
|
|
155
|
+
ICCColorSpace::Hsv => 3,
|
|
156
|
+
ICCColorSpace::Hls => 3,
|
|
157
|
+
ICCColorSpace::Cmyk => 4,
|
|
158
|
+
ICCColorSpace::Cmy => 3,
|
|
159
|
+
ICCColorSpace::OneClr => 1,
|
|
160
|
+
ICCColorSpace::ThreeClr => 3,
|
|
161
|
+
ICCColorSpace::FourClr => 4,
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
impl TryFrom<u32> for ICCColorSpace {
|
|
167
|
+
type Error = ();
|
|
168
|
+
|
|
169
|
+
fn try_from(value: u32) -> Result<Self, Self::Error> {
|
|
170
|
+
match value {
|
|
171
|
+
0x58595A20 => Ok(ICCColorSpace::Xyz),
|
|
172
|
+
0x4C616220 => Ok(ICCColorSpace::Lab),
|
|
173
|
+
0x4C757620 => Ok(ICCColorSpace::Luv),
|
|
174
|
+
0x59436272 => Ok(ICCColorSpace::Ycbr),
|
|
175
|
+
0x59787920 => Ok(ICCColorSpace::Yxy),
|
|
176
|
+
0x4C4D5320 => Ok(ICCColorSpace::Lms),
|
|
177
|
+
0x52474220 => Ok(ICCColorSpace::Rgb),
|
|
178
|
+
0x47524159 => Ok(ICCColorSpace::Gray),
|
|
179
|
+
0x48535620 => Ok(ICCColorSpace::Hsv),
|
|
180
|
+
0x484C5320 => Ok(ICCColorSpace::Hls),
|
|
181
|
+
0x434D594B => Ok(ICCColorSpace::Cmyk),
|
|
182
|
+
0x434D5920 => Ok(ICCColorSpace::Cmy),
|
|
183
|
+
0x31434C52 => Ok(ICCColorSpace::OneClr),
|
|
184
|
+
0x33434C52 => Ok(ICCColorSpace::ThreeClr),
|
|
185
|
+
0x34434C52 => Ok(ICCColorSpace::FourClr),
|
|
186
|
+
_ => Err(()),
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
#[derive(Clone, Hash, Debug, Eq, PartialEq)]
|
|
192
|
+
pub(crate) struct ICCMetadata {
|
|
193
|
+
pub(crate) major: u8,
|
|
194
|
+
pub(crate) minor: u8,
|
|
195
|
+
pub(crate) color_space: ICCColorSpace,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
impl ICCMetadata {
|
|
199
|
+
pub(crate) fn from_data(data: &[u8]) -> Option<Self> {
|
|
200
|
+
let major = *data.get(8)?;
|
|
201
|
+
let minor = *data.get(9)? >> 4;
|
|
202
|
+
let color_space = {
|
|
203
|
+
let marker = u32::from_be_bytes(data.get(16..20)?.try_into().ok()?);
|
|
204
|
+
ICCColorSpace::try_from(marker).ok()?
|
|
205
|
+
};
|
|
206
|
+
Some(Self {
|
|
207
|
+
major,
|
|
208
|
+
minor,
|
|
209
|
+
color_space,
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#[derive(Clone, Hash, Debug)]
|
|
215
|
+
struct Repr {
|
|
216
|
+
data: Vec<u8>,
|
|
217
|
+
metadata: ICCMetadata,
|
|
218
|
+
}
|