Skip to content

Commit febef24

Browse files
committed
Support one byte characters in CMaps (#32)
1 parent 8f509ad commit febef24

File tree

1 file changed

+61
-7
lines changed

1 file changed

+61
-7
lines changed

src/font.rs

+61-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::marker::PhantomData;
2+
13
use super::*;
24

35
/// Writer for a _Type-1 font dictionary_.
@@ -653,13 +655,17 @@ impl<'a> Cmap<'a> {
653655
deref!('a, Cmap<'a> => Stream<'a>, stream);
654656

655657
/// A builder for a `/ToUnicode` character map stream.
656-
pub struct UnicodeCmap {
658+
pub struct UnicodeCmap<G = u16> {
657659
buf: Vec<u8>,
658660
mappings: Vec<u8>,
659661
count: i32,
662+
glyph_id: PhantomData<G>,
660663
}
661664

662-
impl UnicodeCmap {
665+
impl<G> UnicodeCmap<G>
666+
where
667+
G: GlyphId,
668+
{
663669
/// Create a new, empty unicode character map.
664670
pub fn new(name: Name, info: SystemInfo) -> Self {
665671
// https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5014.CIDFont_Spec.pdf
@@ -710,25 +716,34 @@ impl UnicodeCmap {
710716

711717
// We just cover the whole unicode codespace.
712718
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");
714724
buf.extend(b"endcodespacerange\n");
715725

716-
Self { buf, mappings: vec![], count: 0 }
726+
Self {
727+
buf,
728+
mappings: vec![],
729+
count: 0,
730+
glyph_id: PhantomData,
731+
}
717732
}
718733

719734
/// 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) {
721736
self.pair_with_multiple(glyph, [codepoint]);
722737
}
723738

724739
/// Add a mapping from a glyph ID to multiple codepoints.
725740
pub fn pair_with_multiple(
726741
&mut self,
727-
glyph: u16,
742+
glyph: G,
728743
codepoints: impl IntoIterator<Item = char>,
729744
) {
730745
self.mappings.push(b'<');
731-
self.mappings.push_hex_u16(glyph);
746+
glyph.push(&mut self.mappings);
732747
self.mappings.extend(b"> <");
733748

734749
for c in codepoints {
@@ -775,6 +790,45 @@ impl UnicodeCmap {
775790
}
776791
}
777792

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+
778832
/// Specifics about a character collection.
779833
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
780834
pub struct SystemInfo<'a> {

0 commit comments

Comments
 (0)