|
| 1 | +use std::marker::PhantomData; |
| 2 | + |
1 | 3 | use super::*; |
2 | 4 |
|
3 | 5 | /// Writer for a _Type-1 font dictionary_. |
@@ -653,13 +655,17 @@ impl<'a> Cmap<'a> { |
653 | 655 | deref!('a, Cmap<'a> => Stream<'a>, stream); |
654 | 656 |
|
655 | 657 | /// A builder for a `/ToUnicode` character map stream. |
656 | | -pub struct UnicodeCmap { |
| 658 | +pub struct UnicodeCmap<G = u16> { |
657 | 659 | buf: Vec<u8>, |
658 | 660 | mappings: Vec<u8>, |
659 | 661 | count: i32, |
| 662 | + glyph_id: PhantomData<G>, |
660 | 663 | } |
661 | 664 |
|
662 | | -impl UnicodeCmap { |
| 665 | +impl<G> UnicodeCmap<G> |
| 666 | +where |
| 667 | + G: GlyphId, |
| 668 | +{ |
663 | 669 | /// Create a new, empty unicode character map. |
664 | 670 | pub fn new(name: Name, info: SystemInfo) -> Self { |
665 | 671 | // https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5014.CIDFont_Spec.pdf |
@@ -710,25 +716,34 @@ impl UnicodeCmap { |
710 | 716 |
|
711 | 717 | // We just cover the whole unicode codespace. |
712 | 718 | buf.extend(b"1 begincodespacerange\n"); |
713 | | - buf.extend(b"<0000> <ffff>\n"); |
| 719 | + buf.push(b'<'); |
| 720 | + G::MIN.push(&mut buf); |
| 721 | + buf.extend(b"> <"); |
| 722 | + G::MAX.push(&mut buf); |
| 723 | + buf.extend(b">\n"); |
714 | 724 | buf.extend(b"endcodespacerange\n"); |
715 | 725 |
|
716 | | - Self { buf, mappings: vec![], count: 0 } |
| 726 | + Self { |
| 727 | + buf, |
| 728 | + mappings: vec![], |
| 729 | + count: 0, |
| 730 | + glyph_id: PhantomData, |
| 731 | + } |
717 | 732 | } |
718 | 733 |
|
719 | 734 | /// Add a mapping from a glyph ID to a codepoint. |
720 | | - pub fn pair(&mut self, glyph: u16, codepoint: char) { |
| 735 | + pub fn pair(&mut self, glyph: G, codepoint: char) { |
721 | 736 | self.pair_with_multiple(glyph, [codepoint]); |
722 | 737 | } |
723 | 738 |
|
724 | 739 | /// Add a mapping from a glyph ID to multiple codepoints. |
725 | 740 | pub fn pair_with_multiple( |
726 | 741 | &mut self, |
727 | | - glyph: u16, |
| 742 | + glyph: G, |
728 | 743 | codepoints: impl IntoIterator<Item = char>, |
729 | 744 | ) { |
730 | 745 | self.mappings.push(b'<'); |
731 | | - self.mappings.push_hex_u16(glyph); |
| 746 | + glyph.push(&mut self.mappings); |
732 | 747 | self.mappings.extend(b"> <"); |
733 | 748 |
|
734 | 749 | for c in codepoints { |
@@ -775,6 +790,45 @@ impl UnicodeCmap { |
775 | 790 | } |
776 | 791 | } |
777 | 792 |
|
| 793 | +/// Type3 fonts require (in Acrobat at least) IDs in CMaps to be encoded with |
| 794 | +/// one byte only, whereas other font types use two bytes. |
| 795 | +/// |
| 796 | +/// This trait provides an abstraction to support both. |
| 797 | +pub trait GlyphId: private::Sealed {} |
| 798 | + |
| 799 | +impl GlyphId for u8 {} |
| 800 | + |
| 801 | +impl GlyphId for u16 {} |
| 802 | + |
| 803 | +/// Module to seal the `GlyphId` trait. |
| 804 | +mod private { |
| 805 | + use crate::buf::BufExt; |
| 806 | + |
| 807 | + pub trait Sealed { |
| 808 | + const MIN: Self; |
| 809 | + const MAX: Self; |
| 810 | + fn push(self, buf: &mut Vec<u8>); |
| 811 | + } |
| 812 | + |
| 813 | + impl Sealed for u8 { |
| 814 | + const MIN: Self = u8::MIN; |
| 815 | + const MAX: Self = u8::MAX; |
| 816 | + |
| 817 | + fn push(self, buf: &mut Vec<u8>) { |
| 818 | + buf.push_hex(self); |
| 819 | + } |
| 820 | + } |
| 821 | + |
| 822 | + impl Sealed for u16 { |
| 823 | + const MIN: Self = u16::MIN; |
| 824 | + const MAX: Self = u16::MAX; |
| 825 | + |
| 826 | + fn push(self, buf: &mut Vec<u8>) { |
| 827 | + buf.push_hex_u16(self); |
| 828 | + } |
| 829 | + } |
| 830 | +} |
| 831 | + |
778 | 832 | /// Specifics about a character collection. |
779 | 833 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] |
780 | 834 | pub struct SystemInfo<'a> { |
|
0 commit comments