blitz-pdf 0.1.1 → 0.1.3

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.
Files changed (115) hide show
  1. package/README.md +292 -12
  2. package/THIRD_PARTY_NOTICES.md +4 -2
  3. package/dist/browser.d.ts +1 -1
  4. package/dist/browser.d.ts.map +1 -1
  5. package/dist/document-options.d.ts +36 -0
  6. package/dist/document-options.d.ts.map +1 -0
  7. package/dist/document-options.js +236 -0
  8. package/dist/document-options.js.map +1 -0
  9. package/dist/node.d.ts +1 -1
  10. package/dist/node.d.ts.map +1 -1
  11. package/dist/options.d.ts +35 -1
  12. package/dist/options.d.ts.map +1 -1
  13. package/dist/options.js +21 -14
  14. package/dist/options.js.map +1 -1
  15. package/dist/types.d.ts +71 -1
  16. package/dist/types.d.ts.map +1 -1
  17. package/dist/validation.d.ts +2 -0
  18. package/dist/validation.d.ts.map +1 -0
  19. package/dist/validation.js +7 -0
  20. package/dist/validation.js.map +1 -0
  21. package/docs/pagination-regressions.md +88 -0
  22. package/examples/zugferd.mjs +41 -0
  23. package/licenses/RUST_DEPENDENCIES.txt +27 -0
  24. package/package.json +4 -2
  25. package/src/browser.ts +1 -1
  26. package/src/document-options.ts +218 -0
  27. package/src/node.ts +1 -1
  28. package/src/options.ts +18 -13
  29. package/src/types.ts +76 -1
  30. package/src/validation.ts +6 -0
  31. package/vendor/README.md +27 -2
  32. package/vendor/krilla/.cargo-ok +1 -0
  33. package/vendor/krilla/.cargo_vcs_info.json +6 -0
  34. package/vendor/krilla/Cargo.lock +1357 -0
  35. package/vendor/krilla/Cargo.toml +165 -0
  36. package/vendor/krilla/LICENSE_APACHE +202 -0
  37. package/vendor/krilla/LICENSE_MIT +21 -0
  38. package/vendor/krilla/README.md +156 -0
  39. package/vendor/krilla/examples/basic.rs +117 -0
  40. package/vendor/krilla/examples/empty_document.rs +25 -0
  41. package/vendor/krilla/examples/parley.rs +174 -0
  42. package/vendor/krilla/examples/simple_text.rs +118 -0
  43. package/vendor/krilla/examples/stream_builder.rs +93 -0
  44. package/vendor/krilla/icc/LICENSE +116 -0
  45. package/vendor/krilla/icc/README.md +1 -0
  46. package/vendor/krilla/icc/sGrey-v2-magic.icc +0 -0
  47. package/vendor/krilla/icc/sGrey-v4.icc +0 -0
  48. package/vendor/krilla/icc/sRGB-v2-magic.icc +0 -0
  49. package/vendor/krilla/icc/sRGB-v4.icc +0 -0
  50. package/vendor/krilla/src/chunk_container.rs +503 -0
  51. package/vendor/krilla/src/configure/PDF_A1.md +227 -0
  52. package/vendor/krilla/src/configure/PDF_A2.md +269 -0
  53. package/vendor/krilla/src/configure/PDF_A3.md +31 -0
  54. package/vendor/krilla/src/configure/PDF_A4.md +211 -0
  55. package/vendor/krilla/src/configure/PDF_UA1.md +202 -0
  56. package/vendor/krilla/src/configure/README.md +23 -0
  57. package/vendor/krilla/src/configure/mod.rs +197 -0
  58. package/vendor/krilla/src/configure/validate.rs +1244 -0
  59. package/vendor/krilla/src/configure/version.rs +134 -0
  60. package/vendor/krilla/src/content.rs +1352 -0
  61. package/vendor/krilla/src/data.rs +49 -0
  62. package/vendor/krilla/src/document.rs +156 -0
  63. package/vendor/krilla/src/error.rs +170 -0
  64. package/vendor/krilla/src/geom.rs +341 -0
  65. package/vendor/krilla/src/graphics/blend.rs +46 -0
  66. package/vendor/krilla/src/graphics/color.rs +552 -0
  67. package/vendor/krilla/src/graphics/graphic.rs +30 -0
  68. package/vendor/krilla/src/graphics/graphics_state.rs +251 -0
  69. package/vendor/krilla/src/graphics/icc.rs +218 -0
  70. package/vendor/krilla/src/graphics/image.rs +835 -0
  71. package/vendor/krilla/src/graphics/mask.rs +128 -0
  72. package/vendor/krilla/src/graphics/mod.rs +14 -0
  73. package/vendor/krilla/src/graphics/paint.rs +434 -0
  74. package/vendor/krilla/src/graphics/separation.rs +86 -0
  75. package/vendor/krilla/src/graphics/shading_function.rs +865 -0
  76. package/vendor/krilla/src/graphics/shading_pattern.rs +60 -0
  77. package/vendor/krilla/src/graphics/tiling_pattern.rs +119 -0
  78. package/vendor/krilla/src/graphics/xobject.rs +150 -0
  79. package/vendor/krilla/src/interactive/action.rs +68 -0
  80. package/vendor/krilla/src/interactive/annotation.rs +283 -0
  81. package/vendor/krilla/src/interactive/destination.rs +289 -0
  82. package/vendor/krilla/src/interactive/mod.rs +3 -0
  83. package/vendor/krilla/src/interchange/embed.rs +240 -0
  84. package/vendor/krilla/src/interchange/metadata.rs +564 -0
  85. package/vendor/krilla/src/interchange/mod.rs +4 -0
  86. package/vendor/krilla/src/interchange/outline.rs +263 -0
  87. package/vendor/krilla/src/interchange/tagging/fmt.rs +733 -0
  88. package/vendor/krilla/src/interchange/tagging/generate.toml +474 -0
  89. package/vendor/krilla/src/interchange/tagging/generated.rs +4754 -0
  90. package/vendor/krilla/src/interchange/tagging/mod.rs +1324 -0
  91. package/vendor/krilla/src/interchange/tagging/tag.rs +686 -0
  92. package/vendor/krilla/src/lib.rs +179 -0
  93. package/vendor/krilla/src/num.rs +26 -0
  94. package/vendor/krilla/src/page.rs +612 -0
  95. package/vendor/krilla/src/pdf.rs +313 -0
  96. package/vendor/krilla/src/resource.rs +436 -0
  97. package/vendor/krilla/src/serialize.rs +1101 -0
  98. package/vendor/krilla/src/stream.rs +368 -0
  99. package/vendor/krilla/src/surface.rs +664 -0
  100. package/vendor/krilla/src/text/cid.rs +488 -0
  101. package/vendor/krilla/src/text/font.rs +351 -0
  102. package/vendor/krilla/src/text/glyph/bitmap.rs +81 -0
  103. package/vendor/krilla/src/text/glyph/colr.rs +581 -0
  104. package/vendor/krilla/src/text/glyph/mod.rs +205 -0
  105. package/vendor/krilla/src/text/glyph/outline.rs +72 -0
  106. package/vendor/krilla/src/text/glyph/svg.rs +34 -0
  107. package/vendor/krilla/src/text/group.rs +463 -0
  108. package/vendor/krilla/src/text/mod.rs +232 -0
  109. package/vendor/krilla/src/text/shape.rs +102 -0
  110. package/vendor/krilla/src/text/type3.rs +514 -0
  111. package/vendor/krilla/src/util.rs +286 -0
  112. package/vendor/stylo/properties/longhands.toml +0 -1
  113. package/vendor/stylo/stylesheets/rule_parser.rs +1 -1
  114. package/wasm/blitz_pdf.js +10 -5
  115. package/wasm/blitz_pdf_bg.wasm +0 -0
@@ -0,0 +1,552 @@
1
+ //! Dealing with colors and color spaces.
2
+ //!
3
+ //! # Color spaces
4
+ //!
5
+ //! krilla currently supports four color models:
6
+ //! - RGB
7
+ //! - Luma
8
+ //! - CMYK
9
+ //! - Separation (also known as Spot)
10
+ //!
11
+ //! Each color space is associated with its specific color type, which you can use to create new
12
+ //! instances of a specific color in that color space.
13
+ //!
14
+ //! # Representation of colors
15
+ //!
16
+ //! When specifying colors in the process color spaces RGB, Luma, and CMYK, it is important
17
+ //! to understand the distinction between device-dependent and decide-independent color
18
+ //! specification. What follows is only a very brief explanation, if you want to dive into
19
+ //! more details, please look for appropriate resources on the web.
20
+ //!
21
+ //! When specifying colors in a *device-dependent way*, if I instruct the program to draw
22
+ //! the RGB color (145, 120, 45), then the program will use these literal values to activate
23
+ //! the R/G/B lights to achieve displaying a certain color. The problem is that specifying
24
+ //! colors in such a way can lead to slightly different results when actually displaying it,
25
+ //! depending on the screen that is used, since each screen is calibrated differently and
26
+ //! based on different display technologies. This is especially critical for printers, where
27
+ //! different values for CMYK colors might result in different-looking colors when being printed.
28
+ //!
29
+ //! This is why there is also the option to specify colors in a *device-independent* way,
30
+ //! which basically means that the color value (145, 120, 45) is represented in a well-specified
31
+ //! color space, and each device can then convert the colors to their native color space
32
+ //! so that they match the representation in the given color space as closely as possible.
33
+ //! This should lead to a more accurate color representation across different screens.
34
+ //!
35
+ //! In 90% of the cases, it is totally fine to just use a device-dependent colorspace, and it's
36
+ //! what krilla does by default. However, if you do care about that, then you can set the
37
+ //! `no_device_cs` property of [`SerializeSettings`] to true, in which case krilla will embed an ICC profile for the
38
+ //! sGrey and sRGB color spaces (for Luma and RGB colors, respectively). If a CMYK profile
39
+ //! was provided to the serialize settings, this will be used for CMYK colors. Otherwise,
40
+ //! it will fall back to device CMYK.
41
+ //!
42
+ //! # Separations
43
+ //!
44
+ //! An alternative way to achieve exact color reproduction in print are Separation colors.
45
+ //! Using these colors, you can request a specific colorant through its well-known name
46
+ //! (e.g. through a color registry such as PANTONE or RAL). Your production shop can then
47
+ //! supply that exact pigment.
48
+ //!
49
+ //! It is important to recognize that, when viewed on a computer or printed on a home printer,
50
+ //! the requested colorant won't be available. For that reason, you will need to supply a fallback
51
+ //! process color.
52
+ //!
53
+ //! Pay attention to remain consistent: Both in your use of colorant names and fallback colors. A
54
+ //! given colorant should not be referred to by multiple, slightly different names. Just the same
55
+ //! for fallback colors: For a given colorant, there should be only one fallback color. Using multiple
56
+ //! Separation color spaces with the same colorant and distinct fallback colors is considered a bad
57
+ //! practice and forbidden in PDF/A-2 and later.
58
+ //!
59
+ //! [`SerializeSettings`]: crate::SerializeSettings
60
+
61
+ use std::fmt::Debug;
62
+ use std::hash::Hash;
63
+
64
+ use crate::configure::ValidationError;
65
+ use crate::graphics::icc::ICCBasedColorSpace;
66
+ use crate::serialize::SerializeContext;
67
+
68
+ /// The PDF name for the device RGB color space.
69
+ pub(crate) const DEVICE_RGB: &str = "DeviceRGB";
70
+ /// The PDF name for the device gray color space.
71
+ pub(crate) const DEVICE_GRAY: &str = "DeviceGray";
72
+ /// The PDF name for the device CMYK color space.
73
+ pub(crate) const DEVICE_CMYK: &str = "DeviceCMYK";
74
+
75
+ /// A wrapper for storing colors from different color spaces.
76
+ #[derive(Debug, Hash, Eq, PartialEq, Clone)]
77
+ pub enum Color {
78
+ /// A device or CIE-based color.
79
+ Regular(RegularColor),
80
+ /// A special color space.
81
+ Special(SpecialColor),
82
+ }
83
+
84
+ /// A device or CIE-based color.
85
+ #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
86
+ pub enum RegularColor {
87
+ /// An RGB-based color.
88
+ Rgb(rgb::Color),
89
+ /// A luma-based color.
90
+ Luma(luma::Color),
91
+ /// A device CMYK color.
92
+ Cmyk(cmyk::Color),
93
+ }
94
+
95
+ /// A special color space color.
96
+ #[derive(Debug, Hash, Eq, PartialEq, Clone)]
97
+ pub enum SpecialColor {
98
+ /// A separation color.
99
+ Separation(separation::Color),
100
+ }
101
+
102
+ impl Color {
103
+ pub(crate) fn to_pdf_color(&self) -> Vec<f32> {
104
+ match self {
105
+ Color::Regular(RegularColor::Rgb(rgb)) => rgb.to_pdf_color().to_vec(),
106
+ Color::Regular(RegularColor::Luma(l)) => vec![l.to_pdf_color()],
107
+ Color::Regular(RegularColor::Cmyk(cmyk)) => cmyk.to_pdf_color().to_vec(),
108
+ Color::Special(SpecialColor::Separation(spot)) => vec![spot.to_pdf_color()],
109
+ }
110
+ }
111
+
112
+ pub(crate) fn color_space(&self, sc: &mut SerializeContext) -> ColorSpace {
113
+ match self {
114
+ Color::Regular(c) => c.color_space(sc).into(),
115
+ Color::Special(c) => c.color_space().into(),
116
+ }
117
+ }
118
+
119
+ /// Convert a color to a regular color for use with constructs like tags or
120
+ /// annotations that don't support special color spaces
121
+ pub(crate) fn to_regular(&self) -> RegularColor {
122
+ match self {
123
+ Color::Regular(c) => *c,
124
+ Color::Special(SpecialColor::Separation(c)) => c.space.fallback,
125
+ }
126
+ }
127
+ }
128
+
129
+ impl RegularColor {
130
+ pub(crate) fn color_space(&self, sc: &mut SerializeContext) -> RegularColorSpace {
131
+ match self {
132
+ Self::Rgb(r) => r.color_space(sc.serialize_settings().no_device_cs),
133
+ Self::Luma(_) => luma::color_space(sc.serialize_settings().no_device_cs),
134
+ Self::Cmyk(_) => match cmyk::color_space(&sc.serialize_settings()) {
135
+ None => {
136
+ sc.register_validation_error(ValidationError::MissingCMYKProfile);
137
+ DeviceColorSpace::Cmyk.into()
138
+ }
139
+ Some(cs) => cs,
140
+ },
141
+ }
142
+ }
143
+
144
+ /// Return the current color as RGB for use with colored glyphs (SVG and
145
+ /// COLR).
146
+ pub(crate) fn as_rgb(self) -> Option<rgb::Color> {
147
+ Some(match self {
148
+ Self::Rgb(r) => r,
149
+ Self::Luma(l) => rgb::Color::new(l.0, l.0, l.0),
150
+ Self::Cmyk(_) => return None,
151
+ })
152
+ }
153
+
154
+ /// Returns true if this is a subtractive color space (CMYK), false otherwise (RGB, Luma).
155
+ /// Used for determining the correct tint transform behavior in Separation color spaces.
156
+ pub(crate) fn is_subtractive(self) -> bool {
157
+ matches!(self, Self::Cmyk(_))
158
+ }
159
+ }
160
+
161
+ impl SpecialColor {
162
+ pub(crate) fn color_space(&self) -> SpecialColorSpace {
163
+ match self {
164
+ Self::Separation(spot) => spot.color_space().into(),
165
+ }
166
+ }
167
+ }
168
+
169
+ /// Gray-scale colors.
170
+ pub mod luma {
171
+ use crate::color::{CieBasedColorSpace, DeviceColorSpace, RegularColor, RegularColorSpace};
172
+
173
+ /// A luma color.
174
+ #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
175
+ pub struct Color(pub(crate) u8);
176
+
177
+ impl Color {
178
+ /// Create a new luma color.
179
+ pub fn new(lightness: u8) -> Color {
180
+ Color(lightness)
181
+ }
182
+
183
+ /// Create a black luma color.
184
+ pub fn black() -> Self {
185
+ Self::new(0)
186
+ }
187
+
188
+ /// Create a white RGB color.
189
+ pub fn white() -> Self {
190
+ Self::new(255)
191
+ }
192
+
193
+ pub(crate) fn to_pdf_color(self) -> f32 {
194
+ self.0 as f32 / 255.0
195
+ }
196
+ }
197
+
198
+ impl From<Color> for super::RegularColor {
199
+ fn from(val: Color) -> Self {
200
+ super::RegularColor::Luma(val)
201
+ }
202
+ }
203
+
204
+ impl From<Color> for super::Color {
205
+ fn from(val: Color) -> Self {
206
+ RegularColor::from(val).into()
207
+ }
208
+ }
209
+
210
+ impl Default for Color {
211
+ fn default() -> Self {
212
+ Color::new(0)
213
+ }
214
+ }
215
+
216
+ pub(crate) fn color_space(no_device_cs: bool) -> RegularColorSpace {
217
+ if no_device_cs {
218
+ CieBasedColorSpace::Luma.into()
219
+ } else {
220
+ DeviceColorSpace::Gray.into()
221
+ }
222
+ }
223
+ }
224
+
225
+ impl From<RegularColor> for Color {
226
+ fn from(value: RegularColor) -> Self {
227
+ Self::Regular(value)
228
+ }
229
+ }
230
+
231
+ impl From<SpecialColor> for Color {
232
+ fn from(value: SpecialColor) -> Self {
233
+ Self::Special(value)
234
+ }
235
+ }
236
+
237
+ /// CMYK colors.
238
+ pub mod cmyk {
239
+ use crate::color::{CieBasedColorSpace, DeviceColorSpace, RegularColorSpace};
240
+ use crate::graphics::icc::ICCBasedColorSpace;
241
+ use crate::SerializeSettings;
242
+
243
+ /// A CMYK color.
244
+ #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
245
+ pub struct Color(pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8);
246
+
247
+ impl Color {
248
+ /// Create a new CMYK color.
249
+ pub fn new(cyan: u8, magenta: u8, yellow: u8, black: u8) -> Color {
250
+ Color(cyan, magenta, yellow, black)
251
+ }
252
+
253
+ pub(crate) fn to_pdf_color(self) -> [f32; 4] {
254
+ [
255
+ self.0 as f32 / 255.0,
256
+ self.1 as f32 / 255.0,
257
+ self.2 as f32 / 255.0,
258
+ self.3 as f32 / 255.0,
259
+ ]
260
+ }
261
+ }
262
+
263
+ impl From<Color> for super::RegularColor {
264
+ fn from(val: Color) -> Self {
265
+ super::RegularColor::Cmyk(val)
266
+ }
267
+ }
268
+
269
+ impl From<Color> for super::Color {
270
+ fn from(val: Color) -> Self {
271
+ super::RegularColor::from(val).into()
272
+ }
273
+ }
274
+
275
+ impl Default for Color {
276
+ fn default() -> Self {
277
+ Color::new(0, 0, 0, 255)
278
+ }
279
+ }
280
+
281
+ pub(crate) fn color_space(ss: &SerializeSettings) -> Option<RegularColorSpace> {
282
+ if ss.no_device_cs {
283
+ ss.clone()
284
+ .cmyk_profile
285
+ .map(|p| CieBasedColorSpace::Cmyk(ICCBasedColorSpace::<4>(p.clone())).into())
286
+ } else {
287
+ Some(DeviceColorSpace::Cmyk.into())
288
+ }
289
+ }
290
+ }
291
+
292
+ /// RGB colors.
293
+ pub mod rgb {
294
+ use crate::color::{CieBasedColorSpace, DeviceColorSpace, RegularColorSpace};
295
+
296
+ /// An RGB color.
297
+ #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
298
+ pub struct Color(pub(crate) u8, pub(crate) u8, pub(crate) u8);
299
+
300
+ impl Default for Color {
301
+ fn default() -> Self {
302
+ Color::black()
303
+ }
304
+ }
305
+
306
+ impl Color {
307
+ /// Create a new RGB color.
308
+ pub fn new(red: u8, green: u8, blue: u8) -> Self {
309
+ Color(red, green, blue)
310
+ }
311
+
312
+ /// Create a new linear RGB color.
313
+ pub fn new_linear(red: u8, green: u8, blue: u8) -> Self {
314
+ Color(red, green, blue)
315
+ }
316
+
317
+ /// Create a black RGB color.
318
+ pub fn black() -> Self {
319
+ Self::new(0, 0, 0)
320
+ }
321
+
322
+ /// Create a white RGB color.
323
+ pub fn white() -> Self {
324
+ Self::new(255, 255, 255)
325
+ }
326
+
327
+ /// The `red` component of the color.
328
+ pub fn red(&self) -> u8 {
329
+ self.0
330
+ }
331
+
332
+ /// The `green` component of the color.
333
+ pub fn green(&self) -> u8 {
334
+ self.1
335
+ }
336
+
337
+ /// The `blue` component of the color.
338
+ pub fn blue(&self) -> u8 {
339
+ self.2
340
+ }
341
+
342
+ pub(crate) fn to_pdf_color(self) -> [f32; 3] {
343
+ [
344
+ self.0 as f32 / 255.0,
345
+ self.1 as f32 / 255.0,
346
+ self.2 as f32 / 255.0,
347
+ ]
348
+ }
349
+
350
+ pub(super) fn color_space(&self, no_device_cs: bool) -> RegularColorSpace {
351
+ color_space(no_device_cs)
352
+ }
353
+ }
354
+
355
+ impl From<Color> for super::RegularColor {
356
+ fn from(val: Color) -> Self {
357
+ super::RegularColor::Rgb(val)
358
+ }
359
+ }
360
+
361
+ impl From<Color> for super::Color {
362
+ fn from(val: Color) -> Self {
363
+ super::RegularColor::from(val).into()
364
+ }
365
+ }
366
+
367
+ pub(crate) fn color_space(no_device_cs: bool) -> RegularColorSpace {
368
+ if no_device_cs {
369
+ CieBasedColorSpace::Srgb.into()
370
+ } else {
371
+ DeviceColorSpace::Rgb.into()
372
+ }
373
+ }
374
+ }
375
+
376
+ /// Separation (spot) colors.
377
+ pub mod separation {
378
+ use crate::color::RegularColor;
379
+
380
+ /// A spot color.
381
+ #[derive(Debug, Hash, Eq, PartialEq, Clone)]
382
+ pub struct Color {
383
+ pub(crate) tint: u8,
384
+ pub(crate) space: SeparationSpace,
385
+ }
386
+
387
+ impl Color {
388
+ /// Create a new spot color.
389
+ pub fn new(tint: u8, space: SeparationSpace) -> Self {
390
+ Self { tint, space }
391
+ }
392
+
393
+ pub(crate) fn to_pdf_color(&self) -> f32 {
394
+ self.tint as f32 / 255.0
395
+ }
396
+
397
+ pub(crate) fn color_space(&self) -> SeparationSpace {
398
+ self.space.clone()
399
+ }
400
+ }
401
+
402
+ impl Default for Color {
403
+ fn default() -> Self {
404
+ Color::new(0, SeparationSpace::default())
405
+ }
406
+ }
407
+
408
+ impl From<Color> for super::SpecialColor {
409
+ fn from(val: Color) -> Self {
410
+ super::SpecialColor::Separation(val)
411
+ }
412
+ }
413
+
414
+ impl From<Color> for super::Color {
415
+ fn from(val: Color) -> Self {
416
+ super::SpecialColor::from(val).into()
417
+ }
418
+ }
419
+
420
+ /// A Separation color space (also known as spot colors).
421
+ ///
422
+ /// Separation color spaces use a single, subtractive colorant and allow
423
+ /// achieving exact color reproduction in print.
424
+ ///
425
+ /// Krilla automatically linearly scales the fallback color with the separation
426
+ /// tint.
427
+ #[derive(Debug, Eq, PartialEq, Hash, Clone)]
428
+ pub struct SeparationSpace {
429
+ pub(crate) colorant: SeparationColorant,
430
+ pub(crate) fallback: RegularColor,
431
+ }
432
+
433
+ impl SeparationSpace {
434
+ /// Create a new Separation space.
435
+ ///
436
+ /// To export PDF/A-2 and later, make sure that a single Separation Colorant
437
+ /// is always used with the same fallback color.
438
+ pub fn new(colorant: SeparationColorant, fallback: RegularColor) -> Self {
439
+ Self { colorant, fallback }
440
+ }
441
+ }
442
+
443
+ impl From<SeparationSpace> for super::SpecialColorSpace {
444
+ fn from(value: SeparationSpace) -> Self {
445
+ Self::Separation(value)
446
+ }
447
+ }
448
+
449
+ impl Default for SeparationSpace {
450
+ fn default() -> Self {
451
+ Self {
452
+ colorant: SeparationColorant::default(),
453
+ fallback: super::rgb::Color::default().into(),
454
+ }
455
+ }
456
+ }
457
+
458
+ /// What colorant to use for colors in this space.
459
+ #[derive(Debug, Eq, PartialEq, Hash, Clone, Default)]
460
+ pub enum SeparationColorant {
461
+ /// Don't apply colorant at all. Sometimes used to indicate other production
462
+ /// info, such as cuts.
463
+ #[default]
464
+ NoColorant,
465
+ /// Apply the same amount of each available colorants.
466
+ AllColorants,
467
+ /// Specify a colorant name.
468
+ Custom(String),
469
+ }
470
+
471
+ impl SeparationColorant {
472
+ pub(crate) fn to_pdf<'a>(&'a self) -> pdf_writer::Name<'a> {
473
+ match self {
474
+ Self::AllColorants => pdf_writer::Name(b"All"),
475
+ Self::NoColorant => pdf_writer::Name(b"None"),
476
+ Self::Custom(s) => pdf_writer::Name(s.as_bytes()),
477
+ }
478
+ }
479
+ }
480
+ }
481
+
482
+ #[derive(Debug, Eq, PartialEq, Hash, Clone)]
483
+ pub(crate) enum ColorSpace {
484
+ Device(DeviceColorSpace),
485
+ CieBased(CieBasedColorSpace),
486
+ Special(SpecialColorSpace),
487
+ }
488
+
489
+ #[derive(Debug, Eq, PartialEq, Hash, Clone)]
490
+ pub(crate) enum RegularColorSpace {
491
+ Device(DeviceColorSpace),
492
+ CieBased(CieBasedColorSpace),
493
+ }
494
+
495
+ impl From<RegularColorSpace> for ColorSpace {
496
+ fn from(value: RegularColorSpace) -> Self {
497
+ match value {
498
+ RegularColorSpace::Device(s) => Self::Device(s),
499
+ RegularColorSpace::CieBased(s) => Self::CieBased(s),
500
+ }
501
+ }
502
+ }
503
+
504
+ #[derive(Debug, Eq, PartialEq, Hash, Clone)]
505
+ pub(crate) enum DeviceColorSpace {
506
+ Rgb,
507
+ Gray,
508
+ Cmyk,
509
+ }
510
+
511
+ impl From<DeviceColorSpace> for ColorSpace {
512
+ fn from(value: DeviceColorSpace) -> Self {
513
+ Self::Device(value)
514
+ }
515
+ }
516
+
517
+ impl From<DeviceColorSpace> for RegularColorSpace {
518
+ fn from(value: DeviceColorSpace) -> Self {
519
+ Self::Device(value)
520
+ }
521
+ }
522
+
523
+ #[derive(Debug, Eq, PartialEq, Hash, Clone)]
524
+ pub(crate) enum CieBasedColorSpace {
525
+ Srgb,
526
+ Luma,
527
+ Cmyk(ICCBasedColorSpace<4>),
528
+ }
529
+
530
+ impl From<CieBasedColorSpace> for ColorSpace {
531
+ fn from(value: CieBasedColorSpace) -> Self {
532
+ Self::CieBased(value)
533
+ }
534
+ }
535
+
536
+ impl From<CieBasedColorSpace> for RegularColorSpace {
537
+ fn from(value: CieBasedColorSpace) -> Self {
538
+ Self::CieBased(value)
539
+ }
540
+ }
541
+
542
+ #[derive(Debug, Eq, PartialEq, Hash, Clone)]
543
+ pub(crate) enum SpecialColorSpace {
544
+ /// A Separation color space with its colorant and fallback.
545
+ Separation(separation::SeparationSpace),
546
+ }
547
+
548
+ impl From<SpecialColorSpace> for ColorSpace {
549
+ fn from(value: SpecialColorSpace) -> Self {
550
+ Self::Special(value)
551
+ }
552
+ }
@@ -0,0 +1,30 @@
1
+ //! Drawing graphics. This allows you to reuse the same graphical content
2
+ //! multiple times in the PDF without incurring any overhead in terms of file size.
3
+
4
+ use crate::graphics::xobject::XObject;
5
+ use crate::stream::Stream;
6
+
7
+ /// A cacheable graphic. You can use this for large graphics objects which you
8
+ /// want to reuse in multiple locations in the same document. Embedding the same
9
+ /// graphic multiple times will ensure that it is only actually written once in the
10
+ /// PDF document, which might lead to better file sizes.
11
+ ///
12
+ /// IMPORTANT: Note that you must only use a graphic in the document that you created it with!
13
+ /// If you use it in a different document, you will end up with an invalid PDF file.
14
+ #[derive(PartialEq, Eq, Debug, Hash, Clone)]
15
+ pub struct Graphic {
16
+ /// The stream of the graphic.
17
+ pub(crate) x_object: XObject,
18
+ }
19
+
20
+ impl Graphic {
21
+ /// Create a new graphic.
22
+ /// `stream` contains the content description of the graphic.
23
+ /// `isolated` indicates whether the contents of the graphic should be isolated
24
+ /// from wherever the graphic is invoked.
25
+ pub fn new(stream: Stream, isolated: bool) -> Self {
26
+ Self {
27
+ x_object: XObject::new(stream, isolated, false, None),
28
+ }
29
+ }
30
+ }