1use super::*;
2use crate::object::TextStrLike;
3
4const CIE_D65: [f32; 3] = [0.9505, 1.0, 1.0888];
6
7const CIE_D50: [f32; 3] = [0.9642, 1.0, 0.82489];
9
10const CIE_E: [f32; 3] = [1.000, 1.000, 1.000];
12
13const CIE_C: [f32; 3] = [0.9807, 1.0000, 1.1822];
15
16#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
18#[allow(unused)]
19enum ColorSpaceType {
20 CalGray,
21 CalRgb,
22 Lab,
23 IccBased,
24 DeviceRgb,
25 DeviceCmyk,
26 DeviceGray,
27 Indexed,
28 Pattern,
29 Separation,
30 DeviceN,
31}
32
33impl ColorSpaceType {
34 pub(crate) fn to_name(self) -> Name<'static> {
35 match self {
36 Self::CalRgb => Name(b"CalRGB"),
37 Self::CalGray => Name(b"CalGray"),
38 Self::Lab => Name(b"Lab"),
39 Self::IccBased => Name(b"ICCBased"),
40 Self::DeviceRgb => Name(b"DeviceRGB"),
41 Self::DeviceCmyk => Name(b"DeviceCMYK"),
42 Self::DeviceGray => Name(b"DeviceGray"),
43 Self::Separation => Name(b"Separation"),
44 Self::DeviceN => Name(b"DeviceN"),
45 Self::Indexed => Name(b"Indexed"),
46 Self::Pattern => Name(b"Pattern"),
47 }
48 }
49}
50
51#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
53pub enum DeviceColorSpace {
54 Rgb,
56 Cmyk,
58 Gray,
60}
61
62impl DeviceColorSpace {
63 pub(crate) fn to_name(self) -> Name<'static> {
64 match self {
65 Self::Rgb => Name(b"DeviceRGB"),
66 Self::Cmyk => Name(b"DeviceCMYK"),
67 Self::Gray => Name(b"DeviceGray"),
68 }
69 }
70}
71
72pub struct ColorSpace<'a> {
78 obj: Obj<'a>,
79}
80
81writer!(ColorSpace: |obj| Self { obj });
82
83impl ColorSpace<'_> {
85 pub fn cal_rgb(
87 self,
88 white_point: [f32; 3],
89 black_point: Option<[f32; 3]>,
90 gamma: Option<[f32; 3]>,
91 matrix: Option<[f32; 9]>,
92 ) {
93 let mut array = self.obj.array();
94 array.item(ColorSpaceType::CalRgb.to_name());
95
96 let mut dict = array.push().dict();
97 dict.insert(Name(b"WhitePoint")).array().items(white_point);
98
99 if let Some(black_point) = black_point {
100 dict.insert(Name(b"BlackPoint")).array().items(black_point);
101 }
102
103 if let Some(gamma) = gamma {
104 dict.insert(Name(b"Gamma")).array().items(gamma);
105 }
106
107 if let Some(matrix) = matrix {
108 dict.insert(Name(b"Matrix")).array().items(matrix);
109 }
110 }
111
112 pub fn cal_gray(
114 self,
115 white_point: [f32; 3],
116 black_point: Option<[f32; 3]>,
117 gamma: Option<f32>,
118 ) {
119 let mut array = self.obj.array();
120 array.item(ColorSpaceType::CalGray.to_name());
121
122 let mut dict = array.push().dict();
123 dict.insert(Name(b"WhitePoint")).array().items(white_point);
124
125 if let Some(black_point) = black_point {
126 dict.insert(Name(b"BlackPoint")).array().items(black_point);
127 }
128
129 if let Some(gamma) = gamma {
130 dict.pair(Name(b"Gamma"), gamma);
131 }
132 }
133
134 pub fn lab(
136 self,
137 white_point: [f32; 3],
138 black_point: Option<[f32; 3]>,
139 range: Option<[f32; 4]>,
140 ) {
141 let mut array = self.obj.array();
142 array.item(ColorSpaceType::Lab.to_name());
143
144 let mut dict = array.push().dict();
145 dict.insert(Name(b"WhitePoint")).array().items(white_point);
146
147 if let Some(black_point) = black_point {
148 dict.insert(Name(b"BlackPoint")).array().items(black_point);
149 }
150
151 if let Some(range) = range {
152 dict.insert(Name(b"Range")).array().items(range);
153 }
154 }
155
156 pub fn icc_based(self, stream: Ref) {
161 let mut array = self.obj.array();
162 array.item(ColorSpaceType::IccBased.to_name());
163 array.item(stream);
164 }
165}
166
167pub struct IccProfile<'a> {
171 stream: Stream<'a>,
172}
173
174impl<'a> IccProfile<'a> {
175 pub(crate) fn start(stream: Stream<'a>) -> Self {
177 Self { stream }
178 }
179
180 pub fn n(&mut self, n: i32) -> &mut Self {
185 assert!(n == 1 || n == 3 || n == 4, "n must be 1, 3, or 4, but is {n}");
186 self.pair(Name(b"N"), n);
187 self
188 }
189
190 pub fn alternate(&mut self) -> ColorSpace<'_> {
197 ColorSpace::start(self.insert(Name(b"Alternate")))
198 }
199
200 pub fn alternate_name(&mut self, name: Name<'_>) -> &mut Self {
205 self.pair(Name(b"Alternate"), name);
206 self
207 }
208
209 pub fn range(&mut self, range: impl IntoIterator<Item = f32>) -> &mut Self {
217 self.insert(Name(b"Range")).array().typed().items(range);
218 self
219 }
220
221 pub fn metadata(&mut self, metadata: Ref) -> &mut Self {
226 self.pair(Name(b"Metadata"), metadata);
227 self
228 }
229}
230
231deref!('a, IccProfile<'a> => Stream<'a>, stream);
232
233impl ColorSpace<'_> {
235 pub fn srgb(self) {
239 self.cal_rgb(
240 CIE_D65,
241 None,
242 Some([2.2, 2.2, 2.2]),
243 Some([0.4124, 0.2126, 0.0193, 0.3576, 0.715, 0.1192, 0.1805, 0.0722, 0.9505]),
244 )
245 }
246
247 pub fn adobe_rgb(self) {
251 self.cal_rgb(
252 CIE_D65,
253 None,
254 Some([2.1992188, 2.1992188, 2.1992188]),
255 Some([
256 0.57667, 0.29734, 0.02703, 0.18556, 0.62736, 0.07069, 0.18823, 0.07529,
257 0.99134,
258 ]),
259 )
260 }
261
262 pub fn display_p3(self) {
266 self.cal_rgb(
267 CIE_D65,
268 None,
269 Some([2.6, 2.6, 2.6]),
270 Some([
271 0.48657, 0.2297, 0.0, 0.26567, 0.69174, 0.04511, 0.19822, 0.07929,
272 1.04394,
273 ]),
274 )
275 }
276
277 pub fn pro_photo(self) {
281 self.cal_rgb(
282 CIE_D50,
283 None,
284 Some([1.8, 1.8, 1.8]),
285 Some([
286 0.7976749, 0.2880402, 0.0, 0.1351917, 0.7118741, 0.0, 0.0313534,
287 0.0000857, 0.82521,
288 ]),
289 )
290 }
291
292 pub fn eci_rgb(self) {
294 self.cal_rgb(
295 CIE_D50,
296 None,
297 Some([1.8, 1.8, 1.8]),
298 Some([
299 0.6502043, 0.3202499, 0.0, 0.1780774, 0.6020711, 0.0678390, 0.1359384,
300 0.0776791, 0.757371,
301 ]),
302 )
303 }
304
305 pub fn ntsc(self) {
307 self.cal_rgb(
308 CIE_C,
309 None,
310 Some([2.2, 2.2, 2.2]),
311 Some([
312 0.6068909, 0.2989164, 0.0, 0.1735011, 0.586599, 0.0660957, 0.200348,
313 0.1144845, 1.1162243,
314 ]),
315 )
316 }
317
318 pub fn pal(self) {
320 self.cal_rgb(
321 CIE_D65,
322 None,
323 Some([2.2, 2.2, 2.2]),
324 Some([
325 0.430619, 0.2220379, 0.0201853, 0.3415419, 0.7066384, 0.1295504,
326 0.1783091, 0.0713236, 0.9390944,
327 ]),
328 )
329 }
330
331 pub fn d65_gray(self) {
334 self.cal_gray(CIE_D65, None, Some(2.2))
335 }
336
337 pub fn d50_gray(self, gamma: Option<f32>) {
340 self.cal_gray(CIE_D50, None, gamma)
341 }
342
343 pub fn c_gray(self) {
346 self.cal_gray(CIE_C, None, Some(2.2))
347 }
348
349 pub fn e_gray(self, gamma: Option<f32>) {
352 self.cal_gray(CIE_E, None, gamma)
353 }
354}
355
356impl ColorSpace<'_> {
363 pub fn device_rgb(self) {
365 self.obj.primitive(ColorSpaceType::DeviceRgb.to_name());
366 }
367
368 pub fn device_cmyk(self) {
370 self.obj.primitive(ColorSpaceType::DeviceCmyk.to_name());
371 }
372
373 pub fn device_gray(self) {
375 self.obj.primitive(ColorSpaceType::DeviceGray.to_name());
376 }
377}
378
379impl<'a> ColorSpace<'a> {
381 pub fn separation(self, color_name: Name) -> Separation<'a> {
386 let mut array = self.obj.array();
387 array.item(ColorSpaceType::Separation.to_name());
388 array.item(color_name);
389 Separation::start(array)
390 }
391
392 pub fn device_n<'n>(self, names: impl IntoIterator<Item = Name<'n>>) -> DeviceN<'a> {
397 let mut array = self.obj.array();
398 array.item(ColorSpaceType::DeviceN.to_name());
399 array.push().array().items(names);
400 DeviceN::start(array)
401 }
402
403 pub fn indexed(self, base: Name, hival: i32, lookup: &[u8]) {
408 let mut array = self.obj.array();
409 array.item(ColorSpaceType::Indexed.to_name());
410 array.item(base);
411 array.item(hival);
412 array.item(Str(lookup));
413 }
414
415 pub fn pattern(self, base: Name) {
420 let mut array = self.obj.array();
421 array.item(ColorSpaceType::Pattern.to_name());
422 array.item(base);
423 }
424}
425
426#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
428enum PatternType {
429 Tiling,
431 Shading,
433}
434
435impl PatternType {
436 pub(crate) fn to_int(self) -> i32 {
437 match self {
438 Self::Tiling => 1,
439 Self::Shading => 2,
440 }
441 }
442}
443
444pub struct Separation<'a> {
454 array: Array<'a>,
455 has_alternate: bool,
456}
457
458impl<'a> Separation<'a> {
459 pub(crate) fn start(array: Array<'a>) -> Self {
461 Self { array, has_alternate: false }
462 }
463
464 pub fn alternate_device(&mut self, device_space: DeviceColorSpace) -> &mut Self {
466 if self.has_alternate {
467 panic!("alternate space already specified");
468 }
469 self.array.item(device_space.to_name());
470 self.has_alternate = true;
471 self
472 }
473
474 pub fn alternate_color_space(&mut self) -> ColorSpace<'_> {
478 if self.has_alternate {
479 panic!("alternate space already specified");
480 }
481 self.has_alternate = true;
482 ColorSpace::start(self.array.push())
483 }
484
485 pub fn alternate_color_space_ref(&mut self, id: Ref) -> &mut Self {
489 if self.has_alternate {
490 panic!("alternate space already specified");
491 }
492 self.array.item(id);
493 self.has_alternate = true;
494 self
495 }
496
497 pub fn tint_exponential(&mut self) -> ExponentialFunction<'_> {
500 if !self.has_alternate {
501 panic!("alternate space must be specified before tint transform");
502 }
503 ExponentialFunction::start(self.array.push())
504 }
505
506 pub fn tint_stitching(&mut self) -> StitchingFunction<'_> {
508 if !self.has_alternate {
509 panic!("alternate space must be specified before tint transform");
510 }
511 StitchingFunction::start(self.array.push())
512 }
513
514 pub fn tint_ref(&mut self, id: Ref) -> &mut Self {
520 if !self.has_alternate {
521 panic!("alternate space must be specified before tint transform");
522 }
523 self.array.item(id);
524 self
525 }
526}
527
528pub struct DeviceN<'a> {
538 array: Array<'a>,
539 has_alternate: bool,
540 has_tint: bool,
541}
542
543impl<'a> DeviceN<'a> {
544 pub(crate) fn start(array: Array<'a>) -> Self {
546 Self { array, has_alternate: false, has_tint: false }
547 }
548
549 pub fn alternate_device(&mut self, device_space: DeviceColorSpace) -> &mut Self {
551 if self.has_alternate {
552 panic!("alternate space already specified");
553 }
554 self.array.item(device_space.to_name());
555 self.has_alternate = true;
556 self
557 }
558
559 pub fn alternate_color_space(&mut self) -> ColorSpace<'_> {
563 if self.has_alternate {
564 panic!("alternate space already specified");
565 }
566 self.has_alternate = true;
567 ColorSpace::start(self.array.push())
568 }
569
570 pub fn alternate_color_space_ref(&mut self, id: Ref) -> &mut Self {
574 if self.has_alternate {
575 panic!("alternate space already specified");
576 }
577 self.array.item(id);
578 self.has_alternate = true;
579 self
580 }
581
582 pub fn tint_exponential(&mut self) -> ExponentialFunction<'_> {
585 if !self.has_alternate {
586 panic!("alternate space must be specified before tint transform");
587 } else if self.has_tint {
588 panic!("tint transform already specified");
589 }
590
591 self.has_tint = true;
592 ExponentialFunction::start(self.array.push())
593 }
594
595 pub fn tint_stitching(&mut self) -> StitchingFunction<'_> {
597 if !self.has_alternate {
598 panic!("alternate space must be specified before tint transform");
599 } else if self.has_tint {
600 panic!("tint transform already specified");
601 }
602
603 self.has_tint = true;
604 StitchingFunction::start(self.array.push())
605 }
606
607 pub fn tint_ref(&mut self, id: Ref) -> &mut Self {
612 if !self.has_alternate {
613 panic!("alternate space must be specified before tint transform");
614 } else if self.has_tint {
615 panic!("tint transform already specified");
616 }
617
618 self.array.item(id);
619 self.has_tint = true;
620 self
621 }
622
623 pub fn attrs(&mut self) -> DeviceNAttrs<'_> {
625 if !self.has_alternate {
626 panic!(
627 "alternate space and tint transform must be specified before attributes"
628 );
629 } else if !self.has_tint {
630 panic!("tint transform must be specified before attributes");
631 }
632
633 DeviceNAttrs::start(self.array.push())
634 }
635}
636
637pub struct DeviceNAttrs<'a> {
641 dict: Dict<'a>,
642}
643
644writer!(DeviceNAttrs: |obj| Self { dict: obj.dict() });
645
646impl DeviceNAttrs<'_> {
647 pub fn subtype(&mut self, subtype: DeviceNSubtype) -> &mut Self {
649 self.dict.pair(Name(b"Subtype"), subtype.to_name());
650 self
651 }
652
653 pub fn colorants(&mut self) -> TypedDict<'_, Dict<'_>> {
659 self.dict.insert(Name(b"Colorants")).dict().typed()
660 }
661
662 pub fn process(&mut self) -> DeviceNProcess<'_> {
666 DeviceNProcess::start(self.dict.insert(Name(b"Process")))
667 }
668
669 pub fn mixing_hints(&mut self) -> DeviceNMixingHints<'_> {
671 DeviceNMixingHints::start(self.dict.insert(Name(b"MixingHints")))
672 }
673}
674
675pub struct DeviceNProcess<'a> {
679 dict: Dict<'a>,
680}
681
682writer!(DeviceNProcess: |obj| Self { dict: obj.dict() });
683
684impl DeviceNProcess<'_> {
685 pub fn color_space(&mut self, color_space: Name) -> &mut Self {
687 self.dict.pair(Name(b"ColorSpace"), color_space);
688 self
689 }
690
691 pub fn color_space_array(&mut self) -> ColorSpace<'_> {
693 ColorSpace::start(self.dict.insert(Name(b"ColorSpace")))
694 }
695
696 pub fn components<'n>(
701 &mut self,
702 components: impl IntoIterator<Item = Name<'n>>,
703 ) -> &mut Self {
704 self.dict
705 .insert(Name(b"Components"))
706 .array()
707 .typed()
708 .items(components);
709 self
710 }
711}
712
713pub enum DeviceNSubtype {
715 DeviceN,
717 NChannel,
719}
720
721impl DeviceNSubtype {
722 pub(crate) fn to_name(self) -> Name<'static> {
723 match self {
724 Self::DeviceN => Name(b"DeviceN"),
725 Self::NChannel => Name(b"NChannel"),
726 }
727 }
728}
729
730pub struct DeviceNMixingHints<'a> {
734 dict: Dict<'a>,
735}
736
737writer!(DeviceNMixingHints: |obj| Self { dict: obj.dict() });
738
739impl DeviceNMixingHints<'_> {
740 pub fn solidities(&mut self) -> TypedDict<'_, f32> {
745 self.dict.insert(Name(b"Solidities")).dict().typed()
746 }
747
748 pub fn printing_order<'n>(
753 &mut self,
754 order: impl IntoIterator<Item = Name<'n>>,
755 ) -> &mut Self {
756 self.dict.insert(Name(b"PrintingOrder")).array().typed().items(order);
757 self
758 }
759
760 pub fn dot_gain(&mut self) -> TypedDict<'_, f32> {
765 self.dict.insert(Name(b"DotGain")).dict().typed()
766 }
767}
768
769pub struct TilingPattern<'a> {
773 stream: Stream<'a>,
774}
775
776impl<'a> TilingPattern<'a> {
777 pub(crate) fn start_with_stream(mut stream: Stream<'a>) -> Self {
778 stream.pair(Name(b"Type"), Name(b"Pattern"));
779 stream.pair(Name(b"PatternType"), PatternType::Tiling.to_int());
780 Self { stream }
781 }
782
783 pub fn paint_type(&mut self, paint_type: PaintType) -> &mut Self {
787 self.stream.pair(Name(b"PaintType"), paint_type.to_int());
788 self
789 }
790
791 pub fn tiling_type(&mut self, tiling_type: TilingType) -> &mut Self {
795 self.stream.pair(Name(b"TilingType"), tiling_type.to_int());
796 self
797 }
798
799 pub fn bbox(&mut self, bbox: Rect) -> &mut Self {
804 self.stream.pair(Name(b"BBox"), bbox);
805 self
806 }
807
808 pub fn x_step(&mut self, x_step: f32) -> &mut Self {
814 assert!(x_step != 0.0, "x step must not be zero");
815 self.stream.pair(Name(b"XStep"), x_step);
816 self
817 }
818
819 pub fn y_step(&mut self, y_step: f32) -> &mut Self {
825 assert!(y_step != 0.0, "y step must not be zero");
826 self.stream.pair(Name(b"YStep"), y_step);
827 self
828 }
829
830 pub fn resources(&mut self) -> Resources<'_> {
834 self.insert(Name(b"Resources")).start()
835 }
836
837 pub fn matrix(&mut self, matrix: [f32; 6]) -> &mut Self {
842 self.stream.insert(Name(b"Matrix")).array().items(matrix);
843 self
844 }
845}
846
847deref!('a, TilingPattern<'a> => Stream<'a>, stream);
848
849#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
851pub enum PaintType {
852 Colored,
854 Uncolored,
856}
857
858impl PaintType {
859 pub(crate) fn to_int(self) -> i32 {
860 match self {
861 Self::Colored => 1,
862 Self::Uncolored => 2,
863 }
864 }
865}
866
867#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
869pub enum TilingType {
870 ConstantSpacing,
872 NoDistortion,
874 FastConstantSpacing,
876}
877
878impl TilingType {
879 pub(crate) fn to_int(self) -> i32 {
880 match self {
881 Self::ConstantSpacing => 1,
882 Self::NoDistortion => 2,
883 Self::FastConstantSpacing => 3,
884 }
885 }
886}
887
888pub struct ShadingPattern<'a> {
892 dict: Dict<'a>,
893}
894
895writer!(ShadingPattern: |obj| {
896 let mut dict = obj.dict();
897 dict.pair(Name(b"Type"), Name(b"Pattern"));
898 dict.pair(Name(b"PatternType"), PatternType::Shading.to_int());
899 Self { dict }
900});
901
902impl ShadingPattern<'_> {
903 pub fn function_shading(&mut self) -> FunctionShading<'_> {
905 self.dict.insert(Name(b"Shading")).start()
906 }
907
908 pub fn shading_ref(&mut self, id: Ref) -> &mut Self {
910 self.dict.pair(Name(b"Shading"), id);
911 self
912 }
913
914 pub fn matrix(&mut self, matrix: [f32; 6]) -> &mut Self {
918 self.dict.insert(Name(b"Matrix")).array().items(matrix);
919 self
920 }
921
922 pub fn ext_graphics(&mut self) -> ExtGraphicsState<'_> {
924 self.dict.insert(Name(b"ExtGState")).start()
925 }
926}
927
928deref!('a, ShadingPattern<'a> => Dict< 'a>, dict);
929
930pub struct FunctionShading<'a> {
935 dict: Dict<'a>,
936}
937
938writer!(FunctionShading: |obj| Self { dict: obj.dict() });
939
940impl FunctionShading<'_> {
941 pub fn shading_type(&mut self, kind: FunctionShadingType) -> &mut Self {
946 self.dict.pair(Name(b"ShadingType"), kind.to_int());
947 self
948 }
949
950 pub fn color_space(&mut self) -> ColorSpace<'_> {
955 self.dict.insert(Name(b"ColorSpace")).start()
956 }
957
958 pub fn background(&mut self, background: impl IntoIterator<Item = f32>) -> &mut Self {
964 self.dict.insert(Name(b"Background")).array().items(background);
965 self
966 }
967
968 pub fn bbox(&mut self, bbox: Rect) -> &mut Self {
972 self.dict.pair(Name(b"BBox"), bbox);
973 self
974 }
975
976 pub fn anti_alias(&mut self, anti_alias: bool) -> &mut Self {
980 self.dict.pair(Name(b"AntiAlias"), anti_alias);
981 self
982 }
983
984 pub fn domain(&mut self, domain: [f32; 4]) -> &mut Self {
990 self.dict.insert(Name(b"Domain")).array().items(domain);
991 self
992 }
993
994 pub fn matrix(&mut self, matrix: [f32; 6]) -> &mut Self {
1000 self.dict.insert(Name(b"Matrix")).array().items(matrix);
1001 self
1002 }
1003
1004 pub fn function(&mut self, function: Ref) -> &mut Self {
1009 self.dict.pair(Name(b"Function"), function);
1010 self
1011 }
1012
1013 pub fn coords(&mut self, coords: impl IntoIterator<Item = f32>) -> &mut Self {
1019 self.dict.insert(Name(b"Coords")).array().items(coords);
1020 self
1021 }
1022
1023 pub fn extend(&mut self, extend: [bool; 2]) -> &mut Self {
1028 self.dict.insert(Name(b"Extend")).array().items(extend);
1029 self
1030 }
1031}
1032
1033deref!('a, FunctionShading<'a> => Dict<'a>, dict);
1034
1035pub struct StreamShading<'a> {
1039 stream: Stream<'a>,
1040}
1041
1042impl<'a> StreamShading<'a> {
1043 pub(crate) fn start(stream: Stream<'a>) -> Self {
1045 Self { stream }
1046 }
1047
1048 pub fn shading_type(&mut self, kind: StreamShadingType) -> &mut Self {
1053 self.stream.pair(Name(b"ShadingType"), kind.to_int());
1054 self
1055 }
1056
1057 pub fn color_space(&mut self) -> ColorSpace<'_> {
1062 self.stream.insert(Name(b"ColorSpace")).start()
1063 }
1064
1065 pub fn background(&mut self, background: impl IntoIterator<Item = f32>) -> &mut Self {
1071 self.stream.insert(Name(b"Background")).array().items(background);
1072 self
1073 }
1074
1075 pub fn bbox(&mut self, bbox: Rect) -> &mut Self {
1079 self.stream.pair(Name(b"BBox"), bbox);
1080 self
1081 }
1082
1083 pub fn anti_alias(&mut self, anti_alias: bool) -> &mut Self {
1087 self.stream.pair(Name(b"AntiAlias"), anti_alias);
1088 self
1089 }
1090
1091 pub fn function(&mut self, function: Ref) -> &mut Self {
1096 self.stream.pair(Name(b"Function"), function);
1097 self
1098 }
1099
1100 pub fn bits_per_coordinate(&mut self, bits: i32) -> &mut Self {
1105 self.stream.pair(Name(b"BitsPerCoordinate"), bits);
1106 self
1107 }
1108
1109 pub fn bits_per_component(&mut self, bits: i32) -> &mut Self {
1114 self.stream.pair(Name(b"BitsPerComponent"), bits);
1115 self
1116 }
1117
1118 pub fn bits_per_flag(&mut self, bits: i32) -> &mut Self {
1123 self.stream.pair(Name(b"BitsPerFlag"), bits);
1124 self
1125 }
1126
1127 pub fn decode(&mut self, decode: impl IntoIterator<Item = f32>) -> &mut Self {
1131 self.stream.insert(Name(b"Decode")).array().items(decode);
1132 self
1133 }
1134
1135 pub fn vertices_per_row(&mut self, vertices: i32) -> &mut Self {
1140 self.stream.pair(Name(b"VerticesPerRow"), vertices);
1141 self
1142 }
1143}
1144
1145deref!('a, StreamShading<'a> => Stream<'a>, stream);
1146
1147#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1149pub enum FunctionShadingType {
1150 Function,
1152 Axial,
1154 Radial,
1157}
1158
1159impl FunctionShadingType {
1160 pub(crate) fn to_int(self) -> i32 {
1161 match self {
1162 Self::Function => 1,
1163 Self::Axial => 2,
1164 Self::Radial => 3,
1165 }
1166 }
1167}
1168
1169#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1171pub enum StreamShadingType {
1172 FreeformGouraud,
1175 LatticeGouraud,
1178 CoonsPatch,
1181 TensorProductPatch,
1184}
1185
1186impl StreamShadingType {
1187 pub(crate) fn to_int(self) -> i32 {
1188 match self {
1189 Self::FreeformGouraud => 4,
1190 Self::LatticeGouraud => 5,
1191 Self::CoonsPatch => 6,
1192 Self::TensorProductPatch => 7,
1193 }
1194 }
1195}
1196
1197pub struct SeparationInfo<'a> {
1201 dict: Dict<'a>,
1202}
1203
1204writer!(SeparationInfo: |obj| Self { dict: obj.dict() });
1205
1206impl SeparationInfo<'_> {
1207 pub fn pages(&mut self, pages: impl IntoIterator<Item = Ref>) -> &mut Self {
1212 self.dict.insert(Name(b"Pages")).array().typed().items(pages);
1213 self
1214 }
1215
1216 pub fn device_colorant(&mut self, colorant: Name) -> &mut Self {
1220 self.dict.pair(Name(b"DeviceColorant"), colorant);
1221 self
1222 }
1223
1224 pub fn device_colorant_str(&mut self, colorant: &str) -> &mut Self {
1228 self.dict.pair(Name(b"DeviceColorant"), TextStr(colorant));
1229 self
1230 }
1231
1232 pub fn color_space(&mut self) -> ColorSpace<'_> {
1237 self.dict.insert(Name(b"ColorSpace")).start()
1238 }
1239}
1240
1241pub struct OutputIntent<'a> {
1246 dict: Dict<'a>,
1247}
1248
1249writer!(OutputIntent: |obj| {
1250 let mut dict = obj.dict();
1251 dict.pair(Name(b"Type"), Name(b"OutputIntent"));
1252 Self { dict }
1253});
1254
1255impl OutputIntent<'_> {
1256 pub fn subtype(&mut self, subtype: OutputIntentSubtype) -> &mut Self {
1258 self.dict.pair(Name(b"S"), subtype.to_name());
1259 self
1260 }
1261
1262 pub fn output_condition(&mut self, condition: impl TextStrLike) -> &mut Self {
1266 self.dict.pair(Name(b"OutputCondition"), condition);
1267 self
1268 }
1269
1270 pub fn output_condition_identifier(
1274 &mut self,
1275 identifier: impl TextStrLike,
1276 ) -> &mut Self {
1277 self.dict.pair(Name(b"OutputConditionIdentifier"), identifier);
1278 self
1279 }
1280
1281 pub fn registry_name(&mut self, name: TextStr) -> &mut Self {
1285 self.dict.pair(Name(b"RegistryName"), name);
1286 self
1287 }
1288
1289 pub fn info(&mut self, info: impl TextStrLike) -> &mut Self {
1293 self.dict.pair(Name(b"Info"), info);
1294 self
1295 }
1296
1297 pub fn dest_output_profile(&mut self, profile: Ref) -> &mut Self {
1305 self.dict.pair(Name(b"DestOutputProfile"), profile);
1306 self
1307 }
1308}
1309
1310#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1312pub enum OutputIntentSubtype<'a> {
1313 PDFX,
1315 PDFA,
1319 PDFE,
1321 Custom(Name<'a>),
1323}
1324
1325impl<'a> OutputIntentSubtype<'a> {
1326 pub(crate) fn to_name(self) -> Name<'a> {
1327 match self {
1328 Self::PDFX => Name(b"GTS_PDFX"),
1329 Self::PDFA => Name(b"GTS_PDFA1"),
1330 Self::PDFE => Name(b"ISO_PDFE1"),
1331 Self::Custom(name) => name,
1332 }
1333 }
1334}