pdf_writer/
font.rs

1use super::*;
2use std::marker::PhantomData;
3
4/// Writer for a _Type-1 font dictionary_.
5///
6/// This struct is created by [`Chunk::type1_font`].
7pub struct Type1Font<'a> {
8    dict: Dict<'a>,
9}
10
11writer!(Type1Font: |obj| {
12    let mut dict = obj.dict();
13    dict.pair(Name(b"Type"), Name(b"Font"));
14    dict.pair(Name(b"Subtype"), Name(b"Type1"));
15    Self { dict }
16});
17
18impl Type1Font<'_> {
19    /// Write the `/Name` attribute, which is the name of the font in the
20    /// current resource dictionary. Required in PDF 1.0, discouraged in PDF
21    /// 1.1+.
22    pub fn name(&mut self, name: Name) -> &mut Self {
23        self.pair(Name(b"Name"), name);
24        self
25    }
26
27    /// Write the `/BaseFont` attribute. This is the PostScript name of the
28    /// font. Required.
29    ///
30    /// In PDF/A files, the standard 14 fonts are unavailable, so you must
31    /// embed the font data.
32    pub fn base_font(&mut self, name: Name) -> &mut Self {
33        self.pair(Name(b"BaseFont"), name);
34        self
35    }
36
37    /// Write the `FirstChar` attribute, defining the first character code in
38    /// the font's widths array. Required (except for standard 14 fonts
39    /// before PDF 1.5).
40    pub fn first_char(&mut self, first: u8) -> &mut Self {
41        self.pair(Name(b"FirstChar"), i32::from(first));
42        self
43    }
44
45    /// Write the `LastChar` attribute, defining the last character code in the
46    /// font's widths array. Required (except for standard 14 fonts before
47    /// PDF 1.5).
48    pub fn last_char(&mut self, last: u8) -> &mut Self {
49        self.pair(Name(b"LastChar"), i32::from(last));
50        self
51    }
52
53    /// Write the `/Widths` array. Should be of length `last - first + 1`.
54    /// Required (except for standard 14 fonts before PDF 1.5).
55    pub fn widths(&mut self, widths: impl IntoIterator<Item = f32>) -> &mut Self {
56        self.insert(Name(b"Widths")).array().items(widths);
57        self
58    }
59
60    /// Write the `/FontDescriptor` attribute. Required (except for standard 14
61    /// fonts before PDF 1.5).
62    pub fn font_descriptor(&mut self, id: Ref) -> &mut Self {
63        self.pair(Name(b"FontDescriptor"), id);
64        self
65    }
66
67    /// Write the `/Encoding` attribute as a predefined encoding. Either this or
68    /// [`encoding_custom`](Self::encoding_custom) is required.
69    pub fn encoding_predefined(&mut self, encoding: Name) -> &mut Self {
70        self.pair(Name(b"Encoding"), encoding);
71        self
72    }
73
74    /// Start writing an `/Encoding` dictionary. Either this or
75    /// [`encoding_predefined`](Self::encoding_predefined) is required.
76    pub fn encoding_custom(&mut self) -> Encoding<'_> {
77        self.insert(Name(b"Encoding")).start()
78    }
79
80    /// Write the `/ToUnicode` attribute. PDF 1.2+.
81    ///
82    /// A suitable character map can be built with [`UnicodeCmap`].
83    pub fn to_unicode(&mut self, id: Ref) -> &mut Self {
84        self.pair(Name(b"ToUnicode"), id);
85        self
86    }
87}
88
89deref!('a, Type1Font<'a> => Dict<'a>, dict);
90
91/// Writer for a _Type-3 font dictionary_.
92///
93/// This struct is created by [`Chunk::type3_font`].
94pub struct Type3Font<'a> {
95    dict: Dict<'a>,
96}
97
98writer!(Type3Font: |obj| {
99    let mut dict = obj.dict();
100    dict.pair(Name(b"Type"), Name(b"Font"));
101    dict.pair(Name(b"Subtype"), Name(b"Type3"));
102    Self { dict }
103});
104
105impl Type3Font<'_> {
106    /// Write the `/Name` attribute, which is the name of the font in the
107    /// current resource dictionary. Always required in PDF 1.0, required if
108    /// `FontName` is set in child font descriptor.
109    pub fn name(&mut self, name: Name) -> &mut Self {
110        self.pair(Name(b"Name"), name);
111        self
112    }
113
114    /// Write the `/FontBBox` attribute. Required.
115    pub fn bbox(&mut self, bbox: Rect) -> &mut Self {
116        self.pair(Name(b"FontBBox"), bbox);
117        self
118    }
119
120    /// Write the `/FontMatrix` attribute, which defines the mapping from glyph
121    /// space to text space. Required.
122    pub fn matrix(&mut self, matrix: [f32; 6]) -> &mut Self {
123        self.insert(Name(b"FontMatrix")).array().items(matrix);
124        self
125    }
126
127    /// Start writing the `/CharProcs` dictionary, which maps glyph names to
128    /// glyph content streams. Required.
129    ///
130    /// Each glyph's content stream must start with either the
131    /// [`d0`](crate::Content::start_color_glyph) or
132    /// [`d1`](crate::Content::start_shape_glyph) operator.
133    pub fn char_procs(&mut self) -> TypedDict<'_, Ref> {
134        self.insert(Name(b"CharProcs")).dict().typed()
135    }
136
137    /// Write the `/Encoding` attribute as a predefined encoding. Either this or
138    /// [`encoding_custom`](Self::encoding_custom) is required.
139    pub fn encoding_predefined(&mut self, encoding: Name) -> &mut Self {
140        self.pair(Name(b"Encoding"), encoding);
141        self
142    }
143
144    /// Start writing an `/Encoding` dictionary. Either this or
145    /// [`encoding_predefined`](Self::encoding_predefined) is required.
146    pub fn encoding_custom(&mut self) -> Encoding<'_> {
147        self.insert(Name(b"Encoding")).start()
148    }
149
150    /// Write the `FirstChar` attribute, defining the first character code in
151    /// the font's widths array. Required.
152    pub fn first_char(&mut self, first: u8) -> &mut Self {
153        self.pair(Name(b"FirstChar"), i32::from(first));
154        self
155    }
156
157    /// Write the `LastChar` attribute, defining the last character code in the
158    /// font's widths array. Required.
159    pub fn last_char(&mut self, last: u8) -> &mut Self {
160        self.pair(Name(b"LastChar"), i32::from(last));
161        self
162    }
163
164    /// Write the `/Widths` array. Should be of length `last - first + 1`.
165    /// Required.
166    pub fn widths(&mut self, widths: impl IntoIterator<Item = f32>) -> &mut Self {
167        self.insert(Name(b"Widths")).array().items(widths);
168        self
169    }
170
171    /// Write the `/FontDescriptor` attribute. Required in Tagged PDFs.
172    pub fn font_descriptor(&mut self, id: Ref) -> &mut Self {
173        self.pair(Name(b"FontDescriptor"), id);
174        self
175    }
176
177    /// Start writing the `/Resources` dictionary.
178    pub fn resources(&mut self) -> Resources<'_> {
179        self.insert(Name(b"Resources")).start()
180    }
181
182    /// Write the `/ToUnicode` attribute. PDF 1.2+.
183    ///
184    /// A suitable character map can be built with [`UnicodeCmap`].
185    ///
186    /// This attribute is required in some profiles of PDF/A-2, PDF/A-3, and
187    /// PDF/A-4 for some fonts. When present, these standards require that no
188    /// character may be mapped to `0`, `U+FEFF`, or `U+FFFE`.
189    pub fn to_unicode(&mut self, id: Ref) -> &mut Self {
190        self.pair(Name(b"ToUnicode"), id);
191        self
192    }
193}
194
195deref!('a, Type3Font<'a> => Dict<'a>, dict);
196
197/// Writer for a _simple font encoding dictionary_.
198///
199/// This struct is created by [`Type1Font::encoding_custom`] and
200/// [`Type3Font::encoding_custom`].
201pub struct Encoding<'a> {
202    dict: Dict<'a>,
203}
204
205writer!(Encoding: |obj| {
206    let mut dict = obj.dict();
207    dict.pair(Name(b"Type"), Name(b"Encoding"));
208    Self { dict }
209});
210
211impl Encoding<'_> {
212    /// Write the `BaseEncoding` attribute, from which this encoding is
213    /// described through differences.
214    pub fn base_encoding(&mut self, name: Name) -> &mut Self {
215        self.pair(Name(b"BaseEncoding"), name);
216        self
217    }
218
219    /// Start writing the `/Differences` array.
220    pub fn differences(&mut self) -> Differences<'_> {
221        self.insert(Name(b"Differences")).start()
222    }
223}
224
225deref!('a, Encoding<'a> => Dict<'a>, dict);
226
227/// Writer for an _encoding differences array_.
228///
229/// This struct is created by [`Encoding::differences`].
230pub struct Differences<'a> {
231    array: Array<'a>,
232}
233
234writer!(Differences: |obj| Self { array: obj.array() });
235
236impl Differences<'_> {
237    /// Maps consecutive character codes starting at `start` to the given glyph
238    /// names.
239    pub fn consecutive<'n>(
240        &mut self,
241        start: u8,
242        names: impl IntoIterator<Item = Name<'n>>,
243    ) -> &mut Self {
244        self.item(i32::from(start));
245        for name in names {
246            self.item(name);
247        }
248        self
249    }
250}
251
252deref!('a, Differences<'a> => Array<'a>, array);
253
254/// Writer for a _Type-0 (composite) font dictionary_. PDF 1.2+.
255///
256/// This struct is created by [`Chunk::type0_font`].
257pub struct Type0Font<'a> {
258    dict: Dict<'a>,
259}
260
261writer!(Type0Font: |obj| {
262    let mut dict = obj.dict();
263    dict.pair(Name(b"Type"), Name(b"Font"));
264    dict.pair(Name(b"Subtype"), Name(b"Type0"));
265    Self { dict }
266});
267
268impl Type0Font<'_> {
269    /// Write the `/BaseFont` attribute. This is the PostScript name of the
270    /// font. Required.
271    pub fn base_font(&mut self, name: Name) -> &mut Self {
272        self.pair(Name(b"BaseFont"), name);
273        self
274    }
275
276    /// Write the `/Encoding` attribute as a predefined encoding. Either this or
277    /// [`encoding_cmap`](Self::encoding_cmap) is required.
278    pub fn encoding_predefined(&mut self, encoding: Name) -> &mut Self {
279        self.pair(Name(b"Encoding"), encoding);
280        self
281    }
282
283    /// Write the `/Encoding` attribute as a reference to a character map.
284    /// Either this or [`encoding_predefined`](Self::encoding_predefined) is
285    /// required.
286    pub fn encoding_cmap(&mut self, cmap: Ref) -> &mut Self {
287        self.pair(Name(b"Encoding"), cmap);
288        self
289    }
290
291    /// Write the `/DescendantFonts` attribute as a one-element array containing
292    /// a reference to a [`CidFont`]. Required.
293    pub fn descendant_font(&mut self, cid_font: Ref) -> &mut Self {
294        self.insert(Name(b"DescendantFonts")).array().item(cid_font);
295        self
296    }
297
298    /// Write the `/ToUnicode` attribute.
299    ///
300    /// A suitable character map can be built with [`UnicodeCmap`].
301    pub fn to_unicode(&mut self, cmap: Ref) -> &mut Self {
302        self.pair(Name(b"ToUnicode"), cmap);
303        self
304    }
305}
306
307deref!('a, Type0Font<'a> => Dict<'a>, dict);
308
309/// Writer for a _CID font dictionary_. PDF 1.2+.
310///
311/// This struct is created by [`Chunk::cid_font`].
312pub struct CidFont<'a> {
313    dict: Dict<'a>,
314}
315
316writer!(CidFont: |obj| {
317    let mut dict = obj.dict();
318    dict.pair(Name(b"Type"), Name(b"Font"));
319    Self { dict }
320});
321
322impl CidFont<'_> {
323    /// Write the `/Subtype` attribute. Required.
324    pub fn subtype(&mut self, subtype: CidFontType) -> &mut Self {
325        self.pair(Name(b"Subtype"), subtype.to_name());
326        self
327    }
328
329    /// Write the `/BaseFont` attribute. Required.
330    pub fn base_font(&mut self, name: Name) -> &mut Self {
331        self.pair(Name(b"BaseFont"), name);
332        self
333    }
334
335    /// Write the `/CIDSystemInfo` dictionary. Required.
336    pub fn system_info(&mut self, info: SystemInfo) -> &mut Self {
337        info.write(self.insert(Name(b"CIDSystemInfo")));
338        self
339    }
340
341    /// Write the `/FontDescriptor` attribute. Required.
342    pub fn font_descriptor(&mut self, id: Ref) -> &mut Self {
343        self.pair(Name(b"FontDescriptor"), id);
344        self
345    }
346
347    /// Write the `/DW` attribute, specifying the default glyph width.
348    pub fn default_width(&mut self, width: f32) -> &mut Self {
349        self.pair(Name(b"DW"), width);
350        self
351    }
352
353    /// Start writing the `/W` (widths) array.
354    pub fn widths(&mut self) -> Widths<'_> {
355        self.insert(Name(b"W")).start()
356    }
357
358    /// Write the `/CIDToGIDMap` attribute as a predefined name.
359    ///
360    /// The attribute must be present for PDF/A. The only permissible predefined
361    /// name is `Identity`, otherwise [`Self::cid_to_gid_map_stream`] must be
362    /// used.
363    pub fn cid_to_gid_map_predefined(&mut self, name: Name) -> &mut Self {
364        self.pair(Name(b"CIDToGIDMap"), name);
365        self
366    }
367
368    /// Write the `/CIDToGIDMap` attribute as a reference to a stream, whose
369    /// bytes directly map from CIDs to glyph indices.
370    ///
371    /// The attribute must be present for PDF/A.
372    pub fn cid_to_gid_map_stream(&mut self, stream: Ref) -> &mut Self {
373        self.pair(Name(b"CIDToGIDMap"), stream);
374        self
375    }
376}
377
378deref!('a, CidFont<'a> => Dict<'a>, dict);
379
380/// The subtype of a CID font.
381#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
382pub enum CidFontType {
383    /// A CID font containing CFF glyph descriptions.
384    Type0,
385    /// A CID font containing TrueType glyph descriptions.
386    Type2,
387}
388
389impl CidFontType {
390    pub(crate) fn to_name(self) -> Name<'static> {
391        match self {
392            Self::Type0 => Name(b"CIDFontType0"),
393            Self::Type2 => Name(b"CIDFontType2"),
394        }
395    }
396}
397
398/// Writer for a _CID font widths array_.
399///
400/// This struct is created by [`CidFont::widths`].
401pub struct Widths<'a> {
402    array: Array<'a>,
403}
404
405writer!(Widths: |obj| Self { array: obj.array() });
406
407impl Widths<'_> {
408    /// Specifies individual widths for a range of consecutive CIDs starting at
409    /// `start`.
410    pub fn consecutive(
411        &mut self,
412        start: u16,
413        widths: impl IntoIterator<Item = f32>,
414    ) -> &mut Self {
415        self.item(i32::from(start));
416        self.push().array().items(widths);
417        self
418    }
419
420    /// Specifies the same width for all CIDs between `first` and `last`.
421    pub fn same(&mut self, first: u16, last: u16, width: f32) -> &mut Self {
422        self.item(i32::from(first));
423        self.item(i32::from(last));
424        self.item(width);
425        self
426    }
427}
428
429deref!('a, Widths<'a> => Array<'a>, array);
430
431/// Writer for a _font descriptor dictionary_.
432///
433/// This struct is created by [`Chunk::font_descriptor`].
434pub struct FontDescriptor<'a> {
435    dict: Dict<'a>,
436}
437
438writer!(FontDescriptor: |obj| {
439    let mut dict = obj.dict();
440    dict.pair(Name(b"Type"), Name(b"FontDescriptor"));
441    Self { dict }
442});
443
444impl FontDescriptor<'_> {
445    /// Write the `/FontName` attribute. Required, except for Type 3 fonts.
446    pub fn name(&mut self, name: Name) -> &mut Self {
447        self.pair(Name(b"FontName"), name);
448        self
449    }
450
451    /// Write the `/FontFamily` attribute. Recommended for Type 3 fonts in
452    /// Tagged PDFs. PDF 1.5+.
453    pub fn family(&mut self, family: Str) -> &mut Self {
454        self.pair(Name(b"FontFamily"), family);
455        self
456    }
457
458    /// Write the `/FontStretch` attribute. Recommended for Type 3 fonts in
459    /// Tagged PDFs. PDF 1.5+.
460    pub fn stretch(&mut self, stretch: FontStretch) -> &mut Self {
461        self.pair(Name(b"FontStretch"), stretch.to_name());
462        self
463    }
464
465    /// Write the `/FontWeight` attribute. Should be between 100 (lightest) and
466    /// 900 (heaviest), 400 is normal weight, 700 is bold. Recommended
467    /// for Type 3 fonts in Tagged PDFs. PDF 1.5+.
468    pub fn weight(&mut self, weight: u16) -> &mut Self {
469        self.pair(Name(b"FontWeight"), i32::from(weight));
470        self
471    }
472
473    /// Write the `/Flags` attribute. Required.
474    pub fn flags(&mut self, flags: FontFlags) -> &mut Self {
475        self.pair(Name(b"Flags"), flags.bits() as i32);
476        self
477    }
478
479    /// Write the `/FontBBox` attribute. Required, except for Type 3 fonts.
480    pub fn bbox(&mut self, bbox: Rect) -> &mut Self {
481        self.pair(Name(b"FontBBox"), bbox);
482        self
483    }
484
485    /// Write the `/ItalicAngle` attribute. Required.
486    pub fn italic_angle(&mut self, angle: f32) -> &mut Self {
487        self.pair(Name(b"ItalicAngle"), angle);
488        self
489    }
490
491    /// Write the `/Ascent` attribute. Required.
492    pub fn ascent(&mut self, ascent: f32) -> &mut Self {
493        self.pair(Name(b"Ascent"), ascent);
494        self
495    }
496
497    /// Write the `/Descent` attribute. Required.
498    pub fn descent(&mut self, descent: f32) -> &mut Self {
499        self.pair(Name(b"Descent"), descent);
500        self
501    }
502
503    /// Write the `/Leading` attribute.
504    pub fn leading(&mut self, leading: f32) -> &mut Self {
505        self.pair(Name(b"Leading"), leading);
506        self
507    }
508
509    /// Write the `/CapHeight` attribute. Required for fonts with Latin
510    /// characters, except for Type 3 fonts.
511    pub fn cap_height(&mut self, cap_height: f32) -> &mut Self {
512        self.pair(Name(b"CapHeight"), cap_height);
513        self
514    }
515
516    /// Write the `/XHeight` attribute.
517    pub fn x_height(&mut self, x_height: f32) -> &mut Self {
518        self.pair(Name(b"XHeight"), x_height);
519        self
520    }
521
522    /// Write the `/StemV` attribute. Required, except for Type 3 fonts.
523    pub fn stem_v(&mut self, stem_v: f32) -> &mut Self {
524        self.pair(Name(b"StemV"), stem_v);
525        self
526    }
527
528    /// Write the `/StemH` attribute.
529    pub fn stem_h(&mut self, stem_h: f32) -> &mut Self {
530        self.pair(Name(b"StemH"), stem_h);
531        self
532    }
533
534    /// Write the `/AvgWidth` attribute.
535    pub fn avg_width(&mut self, avg_width: f32) -> &mut Self {
536        self.pair(Name(b"AvgWidth"), avg_width);
537        self
538    }
539
540    /// Write the `/MaxWidth` attribute.
541    pub fn max_width(&mut self, max_width: f32) -> &mut Self {
542        self.pair(Name(b"MaxWidth"), max_width);
543        self
544    }
545
546    /// Write the `/MissingWidth` attribute.
547    pub fn missing_width(&mut self, missing_width: f32) -> &mut Self {
548        self.pair(Name(b"MissingWidth"), missing_width);
549        self
550    }
551
552    /// Write the `/FontFile` attribute, referecing Type 1 font data.
553    pub fn font_file(&mut self, id: Ref) -> &mut Self {
554        self.pair(Name(b"FontFile"), id);
555        self
556    }
557
558    /// Write the `/FontFile2` attribute, referencing TrueType font data. PDF
559    /// 1.1+.
560    pub fn font_file2(&mut self, id: Ref) -> &mut Self {
561        self.pair(Name(b"FontFile2"), id);
562        self
563    }
564
565    /// Write the `/FontFile3` attribute, referencing CFF font data. PDF 1.2+ or
566    /// PDF 1.3+ for CID-keyed fonts.
567    pub fn font_file3(&mut self, id: Ref) -> &mut Self {
568        self.pair(Name(b"FontFile3"), id);
569        self
570    }
571
572    /// Write the `/CharSet` attribute, encoding the character names of a font
573    /// subset as a string. This is only relevant for Type 1 fonts. PDF 1.1+.
574    ///
575    /// If present in PDF/A, this must include all characters in the subset,
576    /// even if they are not used in the document.
577    pub fn char_set(&mut self, names: Str) -> &mut Self {
578        self.pair(Name(b"CharSet"), names);
579        self
580    }
581}
582
583/// Additional `FontDescriptor` attributes for CIDFonts.
584impl FontDescriptor<'_> {
585    /// Write the `/Style` attribute. Optional.
586    ///
587    /// The class and subclass values should be extracted from the
588    /// `sFamilyClass` field of the OS/2 table. The `panose` array should be
589    /// extracted from the `panose` field of the OS/2 table.
590    pub fn style(&mut self, class: u8, subclass: u8, panose: [u8; 10]) -> &mut Self {
591        let mut bytes = [0; 12];
592        bytes[0] = class;
593        bytes[1] = subclass;
594        bytes[2..].copy_from_slice(&panose);
595        self.insert(Name(b"Style")).dict().pair(Name(b"Panose"), Str(&bytes));
596        self
597    }
598
599    /// Start writing the `/FD` attribute. Optional.
600    ///
601    /// Overrides the global font descriptor for specific glyphs.
602    pub fn descriptor_override(&mut self) -> FontDescriptorOverride<'_> {
603        self.insert(Name(b"FD")).start()
604    }
605
606    /// Write the `/CIDSet` attribute.
607    ///
608    /// If present in PDF/A, this must include all characters in the subset,
609    /// even if they are not used in the document.
610    pub fn cid_set(&mut self, id: Ref) -> &mut Self {
611        self.pair(Name(b"CIDSet"), id);
612        self
613    }
614}
615
616deref!('a, FontDescriptor<'a> => Dict<'a>, dict);
617
618/// Writer for a _font descriptor override dictionary_.
619///
620/// This struct is created by [`FontDescriptor::descriptor_override`].
621///
622/// The font descriptor dictionaries within can only contain metrics data.
623pub struct FontDescriptorOverride<'a> {
624    dict: Dict<'a>,
625}
626
627writer!(FontDescriptorOverride: |obj| {
628    Self { dict: obj.dict() }
629});
630
631impl FontDescriptorOverride<'_> {
632    /// Start writing a `FontDescriptor` dictionary for a custom character
633    /// class.
634    pub fn custom_class(&mut self, class: Name) -> FontDescriptor<'_> {
635        self.insert(class).start()
636    }
637
638    /// Write a class override referencing a `FontDescriptor` dictionary
639    /// indirectly.
640    pub fn custom_class_ref(&mut self, class: Name, id: Ref) -> &mut Self {
641        self.pair(class, id);
642        self
643    }
644
645    /// Start writing a `FontDescriptor` dictionary for a predefined CJK class.
646    pub fn cjk_class(&mut self, class: CjkClass) -> FontDescriptor<'_> {
647        self.insert(class.to_name()).start()
648    }
649
650    /// Write a class override for a predefined CJK class referencing a
651    /// `FontDescriptor` dictionary indirectly.
652    pub fn cjk_class_ref(&mut self, class: CjkClass, id: Ref) -> &mut Self {
653        self.pair(class.to_name(), id);
654        self
655    }
656}
657
658deref!('a, FontDescriptorOverride<'a> => Dict<'a>, dict);
659
660/// Glyph classes for CJK fonts as defined in ISO 32000-1:2008.
661#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
662#[allow(missing_docs)]
663pub enum CjkClass {
664    Alphabetic,
665    AlphaNum,
666    Dingbats,
667    DingbatsRot,
668    Generic,
669    GenericRot,
670    Hangul,
671    Hanja,
672    Hanzi,
673    HRoman,
674    HRomanRot,
675    HKana,
676    HKanaRot,
677    HojoKanji,
678    Kana,
679    Kanji,
680    Proportional,
681    ProportionalRot,
682    Ruby,
683}
684
685impl CjkClass {
686    pub(crate) fn to_name(self) -> Name<'static> {
687        match self {
688            Self::Alphabetic => Name(b"Alphabetic"),
689            Self::AlphaNum => Name(b"AlphaNum"),
690            Self::Dingbats => Name(b"Dingbats"),
691            Self::DingbatsRot => Name(b"DingbatsRot"),
692            Self::Generic => Name(b"Generic"),
693            Self::GenericRot => Name(b"GenericRot"),
694            Self::Hangul => Name(b"Hangul"),
695            Self::Hanja => Name(b"Hanja"),
696            Self::Hanzi => Name(b"Hanzi"),
697            Self::HRoman => Name(b"HRoman"),
698            Self::HRomanRot => Name(b"HRomanRot"),
699            Self::HKana => Name(b"HKana"),
700            Self::HKanaRot => Name(b"HKanaRot"),
701            Self::HojoKanji => Name(b"HojoKanji"),
702            Self::Kana => Name(b"Kana"),
703            Self::Kanji => Name(b"Kanji"),
704            Self::Proportional => Name(b"Proportional"),
705            Self::ProportionalRot => Name(b"ProportionalRot"),
706            Self::Ruby => Name(b"Ruby"),
707        }
708    }
709}
710
711/// The width of a font's glyphs.
712#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
713#[allow(missing_docs)]
714pub enum FontStretch {
715    UltraCondensed,
716    ExtraCondensed,
717    Condensed,
718    SemiCondensed,
719    Normal,
720    SemiExpanded,
721    Expanded,
722    ExtraExpanded,
723    UltraExpanded,
724}
725
726impl FontStretch {
727    pub(crate) fn to_name(self) -> Name<'static> {
728        match self {
729            Self::UltraCondensed => Name(b"UltraCondensed"),
730            Self::ExtraCondensed => Name(b"ExtraCondensed"),
731            Self::Condensed => Name(b"Condensed"),
732            Self::SemiCondensed => Name(b"SemiCondensed"),
733            Self::Normal => Name(b"Normal"),
734            Self::SemiExpanded => Name(b"SemiExpanded"),
735            Self::Expanded => Name(b"Expanded"),
736            Self::ExtraExpanded => Name(b"ExtraExpanded"),
737            Self::UltraExpanded => Name(b"UltraExpanded"),
738        }
739    }
740}
741
742bitflags::bitflags! {
743    /// Bitflags describing various characteristics of fonts.
744    pub struct FontFlags: u32 {
745        /// All glyphs have the same width.
746        const FIXED_PITCH = 1 << 0;
747        /// Glyphs have short strokes at their stems.
748        const SERIF = 1 << 1;
749        /// The font contains glyphs not in the Adobe standard Latin character
750        /// set.
751        const SYMBOLIC = 1 << 2;
752        /// The glyphs resemeble cursive handwritiwng.
753        const SCRIPT = 1 << 3;
754        /// The font only uses glyphs in the Adobe standard Latin character set.
755        const NON_SYMBOLIC = 1 << 5;
756        /// The glyphs are slanted to the right.
757        const ITALIC = 1 << 6;
758        /// The font does not contain lowercase letters.
759        const ALL_CAP = 1 << 16;
760        /// The font's lowercase letters are similar to the uppercase ones, but
761        /// smaller.
762        const SMALL_CAP = 1 << 17;
763        /// Ensures that bold glyphs are painted with more pixels than normal
764        /// glyphs even at very small sizes.
765        const FORCE_BOLD = 1 << 18;
766    }
767}
768
769/// Writer for a _character map stream_.
770///
771/// This struct is created by [`Chunk::cmap`].
772pub struct Cmap<'a> {
773    stream: Stream<'a>,
774}
775
776impl<'a> Cmap<'a> {
777    /// Create a new character map writer.
778    pub(crate) fn start(mut stream: Stream<'a>) -> Self {
779        stream.pair(Name(b"Type"), Name(b"CMap"));
780        Self { stream }
781    }
782
783    /// Write the `/CMapName` attribute. Required.
784    pub fn name(&mut self, name: Name) -> &mut Self {
785        self.pair(Name(b"CMapName"), name);
786        self
787    }
788
789    /// Write the `/CIDSystemInfo` attribute. Required.
790    pub fn system_info(&mut self, info: SystemInfo) -> &mut Self {
791        info.write(self.insert(Name(b"CIDSystemInfo")));
792        self
793    }
794
795    /// Write the `/WMode` attribute. Optional.
796    ///
797    /// This describes whether the CMap applies to a font with horizontal or
798    /// vertical writing mode. The default is whatever is specified in the CMap.
799    ///
800    /// This is required in PDF/A and must match the writing mode of the
801    /// embedded CMap.
802    pub fn writing_mode(&mut self, mode: WMode) -> &mut Self {
803        self.pair(Name(b"WMode"), mode.to_int());
804        self
805    }
806
807    /// Write the `/UseCMap` attribute using a stream reference. Optional.
808    ///
809    /// This allows specifying a base CMap to extend.
810    ///
811    /// Note that this attribute is restricted in PDF/A and may only be used
812    /// with the well-known CMap names from the PDF standard. Use
813    /// [`Self::use_cmap_predefined`] to specify a predefined name.
814    pub fn use_cmap_stream(&mut self, cmap: Ref) -> &mut Self {
815        self.pair(Name(b"UseCMap"), cmap);
816        self
817    }
818
819    /// Write the `/UseCMap` attribute using a predefined name. Optional.
820    ///
821    /// This allows specifying a base CMap to extend.
822    ///
823    /// Note that this attribute is restricted in PDF/A.
824    pub fn use_cmap_predefined(&mut self, name: Name) -> &mut Self {
825        self.pair(Name(b"UseCMap"), name);
826        self
827    }
828}
829
830deref!('a, Cmap<'a> => Stream<'a>, stream);
831
832/// The writing mode of a character map.
833#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
834#[allow(missing_docs)]
835pub enum WMode {
836    #[default]
837    Horizontal,
838    Vertical,
839}
840
841impl WMode {
842    pub(crate) fn to_int(self) -> i32 {
843        match self {
844            Self::Horizontal => 0,
845            Self::Vertical => 1,
846        }
847    }
848}
849
850/// A builder for a `/ToUnicode` character map stream.
851pub struct UnicodeCmap<G = u16> {
852    buf: Buf,
853    mappings: Buf,
854    count: i32,
855    glyph_id: PhantomData<G>,
856}
857
858impl<G> UnicodeCmap<G>
859where
860    G: GlyphId,
861{
862    /// Create a new, empty unicode character map for a horizontal writing mode
863    /// font.
864    pub fn new(name: Name, info: SystemInfo) -> Self {
865        Self::with_writing_mode(name, info, WMode::Horizontal)
866    }
867
868    /// Create a new, empty unicode character map while specifying the writing
869    /// mode.
870    pub fn with_writing_mode(name: Name, info: SystemInfo, mode: WMode) -> Self {
871        // https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5014.CIDFont_Spec.pdf
872
873        let mut buf = Buf::new();
874
875        // Static header.
876        buf.extend(b"%!PS-Adobe-3.0 Resource-CMap\n");
877        buf.extend(b"%%DocumentNeededResources: procset CIDInit\n");
878        buf.extend(b"%%IncludeResource: procset CIDInit\n");
879
880        // Dynamic header.
881        buf.extend(b"%%BeginResource: CMap ");
882        buf.extend(name.0);
883        buf.push(b'\n');
884        buf.extend(b"%%Title: (");
885        buf.extend(name.0);
886        buf.push(b' ');
887        buf.extend(info.registry.0);
888        buf.push(b' ');
889        buf.extend(info.ordering.0);
890        buf.push(b' ');
891        buf.push_int(info.supplement);
892        buf.extend(b")\n");
893        buf.extend(b"%%Version: 1\n");
894        buf.extend(b"%%EndComments\n");
895
896        // General body.
897        buf.extend(b"/CIDInit /ProcSet findresource begin\n");
898        buf.extend(b"12 dict begin\n");
899        buf.extend(b"begincmap\n");
900        buf.extend(b"/CIDSystemInfo 3 dict dup begin\n");
901        buf.extend(b"    /Registry ");
902        buf.push_val(info.registry);
903        buf.extend(b" def\n");
904        buf.extend(b"    /Ordering ");
905        buf.push_val(info.ordering);
906        buf.extend(b" def\n");
907        buf.extend(b"    /Supplement ");
908        buf.push_val(info.supplement);
909        buf.extend(b" def\n");
910        buf.extend(b"end def\n");
911        buf.extend(b"/CMapName ");
912        buf.push_val(name);
913        buf.extend(b" def\n");
914        buf.extend(b"/CMapVersion 1 def\n");
915        buf.extend(b"/CMapType 0 def\n");
916        buf.extend(b"/WMode ");
917        buf.push_int(mode.to_int());
918        buf.extend(b" def\n");
919
920        // We just cover the whole unicode codespace.
921        buf.extend(b"1 begincodespacerange\n");
922        buf.push(b'<');
923        G::MIN.push(&mut buf);
924        buf.extend(b"> <");
925        G::MAX.push(&mut buf);
926        buf.extend(b">\n");
927        buf.extend(b"endcodespacerange\n");
928
929        Self {
930            buf,
931            mappings: Buf::new(),
932            count: 0,
933            glyph_id: PhantomData,
934        }
935    }
936
937    /// Add a mapping from a glyph ID to a codepoint.
938    pub fn pair(&mut self, glyph: G, codepoint: char) {
939        self.pair_with_multiple(glyph, [codepoint]);
940    }
941
942    /// Add a mapping from a glyph ID to multiple codepoints.
943    pub fn pair_with_multiple(
944        &mut self,
945        glyph: G,
946        codepoints: impl IntoIterator<Item = char>,
947    ) {
948        self.mappings.push(b'<');
949        glyph.push(&mut self.mappings);
950        self.mappings.extend(b"> <");
951
952        for c in codepoints {
953            for &mut part in c.encode_utf16(&mut [0; 2]) {
954                self.mappings.push_hex_u16(part);
955            }
956        }
957
958        self.mappings.extend(b">\n");
959        self.count += 1;
960
961        // At most 100 lines per range.
962        if self.count >= 100 {
963            self.flush_range();
964        }
965    }
966
967    /// Finish building the character map.
968    pub fn finish(mut self) -> Buf {
969        // Flush the in-progress range.
970        self.flush_range();
971
972        // End of body.
973        self.buf.extend(b"endcmap\n");
974        self.buf.extend(b"CMapName currentdict /CMap defineresource pop\n");
975        self.buf.extend(b"end\n");
976        self.buf.extend(b"end\n");
977        self.buf.extend(b"%%EndResource\n");
978        self.buf.extend(b"%%EOF");
979
980        self.buf
981    }
982
983    fn flush_range(&mut self) {
984        if self.count > 0 {
985            self.buf.push_int(self.count);
986            self.buf.extend(b" beginbfchar\n");
987            self.buf.extend(self.mappings.as_slice());
988            self.buf.extend(b"endbfchar\n");
989        }
990
991        self.count = 0;
992        self.mappings.inner.clear();
993    }
994}
995
996/// Type3 fonts require (in Acrobat at least) IDs in CMaps to be encoded with
997/// one byte only, whereas other font types use two bytes.
998///
999/// This trait provides an abstraction to support both.
1000pub trait GlyphId: private::Sealed {}
1001
1002impl GlyphId for u8 {}
1003
1004impl GlyphId for u16 {}
1005
1006/// Module to seal the `GlyphId` trait.
1007mod private {
1008    use crate::buf::Buf;
1009
1010    pub trait Sealed {
1011        const MIN: Self;
1012        const MAX: Self;
1013        fn push(self, buf: &mut Buf);
1014    }
1015
1016    impl Sealed for u8 {
1017        const MIN: Self = u8::MIN;
1018        const MAX: Self = u8::MAX;
1019
1020        fn push(self, buf: &mut Buf) {
1021            buf.push_hex(self);
1022        }
1023    }
1024
1025    impl Sealed for u16 {
1026        const MIN: Self = u16::MIN;
1027        const MAX: Self = u16::MAX;
1028
1029        fn push(self, buf: &mut Buf) {
1030            buf.push_hex_u16(self);
1031        }
1032    }
1033}
1034
1035/// Specifics about a character collection.
1036#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1037pub struct SystemInfo<'a> {
1038    /// The issuer of the collection.
1039    pub registry: Str<'a>,
1040    /// A unique name of the collection within the registry.
1041    pub ordering: Str<'a>,
1042    /// The supplement number (i.e. the version).
1043    pub supplement: i32,
1044}
1045
1046impl SystemInfo<'_> {
1047    fn write(&self, obj: Obj<'_>) {
1048        obj.dict()
1049            .pair(Name(b"Registry"), self.registry)
1050            .pair(Name(b"Ordering"), self.ordering)
1051            .pair(Name(b"Supplement"), self.supplement);
1052    }
1053}