Insert default glyph when subsetting ⚙

This commit is contained in:
Laurenz 2019-03-31 15:47:57 +02:00
parent 0b2ae78534
commit a522a15a66
3 changed files with 29 additions and 21 deletions

View File

@ -187,7 +187,7 @@ impl Default for Style {
// Default font family, font size and line spacing. // Default font family, font size and line spacing.
font_families: vec![SansSerif, Serif, Monospace], font_families: vec![SansSerif, Serif, Monospace],
font_size: 12.0, font_size: 11.0,
line_spacing: 1.25, line_spacing: 1.25,
} }
} }

View File

@ -164,35 +164,33 @@ impl<'d, W: Write> PdfEngine<'d, W> {
let mut id = self.offsets.fonts.0; let mut id = self.offsets.fonts.0;
for font in &self.fonts { for font in &self.fonts {
let base_font = format!("ABCDEF+{}", font.name);
// Write the base font object referencing the CID font. // Write the base font object referencing the CID font.
self.writer.write_obj(id, self.writer.write_obj(id,
Type0Font::new( Type0Font::new(
font.name.clone(), base_font.clone(),
CMapEncoding::Predefined("Identity-H".to_owned()), CMapEncoding::Predefined("Identity-H".to_owned()),
id + 1 id + 1
).to_unicode(id + 2) ).to_unicode(id + 3)
)?; )?;
let system_info = CIDSystemInfo::new("(Adobe)", "(Identity)", 0); let system_info = CIDSystemInfo::new("Adobe", "Identity", 0);
// Write the CID font referencing the font descriptor. // Write the CID font referencing the font descriptor.
self.writer.write_obj(id + 1, self.writer.write_obj(id + 1,
CIDFont::new( CIDFont::new(
CIDFontType::Type2, CIDFontType::Type2,
font.name.clone(), base_font.clone(),
system_info.clone(), system_info.clone(),
id + 3, id + 2,
).widths(vec![WidthRecord::start(0, font.widths.clone())]) ).widths(vec![WidthRecord::start(0, font.widths.clone())])
)?; )?;
// The CMap, which maps glyphs to unicode codepoints.
let mapping = font.font.mapping.iter().map(|(&c, &cid)| (cid, c));
self.writer.write_obj(id + 2, &CMap::new("Custom", system_info, mapping))?;
// Write the font descriptor (contains the global information about the font). // Write the font descriptor (contains the global information about the font).
self.writer.write_obj(id + 3, self.writer.write_obj(id + 2,
FontDescriptor::new( FontDescriptor::new(
font.name.clone(), base_font,
font.flags, font.flags,
font.italic_angle, font.italic_angle,
) )
@ -204,6 +202,10 @@ impl<'d, W: Write> PdfEngine<'d, W> {
.font_file_3(id + 4) .font_file_3(id + 4)
)?; )?;
// The CMap, which maps glyphs to unicode codepoints.
let mapping = font.font.mapping.iter().map(|(&c, &cid)| (cid, c));
self.writer.write_obj(id + 3, &CMap::new("Custom", system_info, mapping))?;
// Finally write the subsetted font program. // Finally write the subsetted font program.
self.writer.write_obj(id + 4, &FontStream::new( self.writer.write_obj(id + 4, &FontStream::new(
&font.program, &font.program,
@ -249,7 +251,7 @@ impl PdfFont {
let subsetted = font.subsetted( let subsetted = font.subsetted(
chars.iter().cloned(), chars.iter().cloned(),
&["head", "hhea", "maxp", "hmtx", "loca", "glyf"][..], &["head", "hhea", "maxp", "hmtx", "loca", "glyf"][..],
&["cvt ", "prep", "fpgm"][..], &["cvt ", "prep", "fpgm", /* "OS/2", "cmap", "name", "post" */][..],
)?; )?;
// Specify flags for the font // Specify flags for the font

View File

@ -141,7 +141,7 @@ impl Font {
cmap: None, cmap: None,
hmtx: None, hmtx: None,
loca: None, loca: None,
glyphs: Vec::with_capacity(chars.len()), glyphs: Vec::with_capacity(1 + chars.len()),
chars, chars,
records: vec![], records: vec![],
body: vec![], body: vec![],
@ -445,12 +445,15 @@ impl<'d> Subsetter<'d> {
self.write_header()?; self.write_header()?;
// Build the new widths.
let widths = self.glyphs.iter() let widths = self.glyphs.iter()
.map(|&glyph| self.font.widths.get(glyph as usize).map(|&w| w) .map(|&glyph| {
.take_invalid("missing glyph metrics")) self.font.widths.get(glyph as usize).map(|&w| w)
.collect::<FontResult<Vec<_>>>()?; .take_invalid("missing glyph metrics")
}).collect::<FontResult<Vec<_>>>()?;
let mapping = self.chars.into_iter().enumerate().map(|(i, c)| (c, i as u16)) // We add one to the index here because we added the default glyph to the front.
let mapping = self.chars.into_iter().enumerate().map(|(i, c)| (c, 1 + i as u16))
.collect::<HashMap<char, u16>>(); .collect::<HashMap<char, u16>>();
Ok(Font { Ok(Font {
@ -467,12 +470,12 @@ impl<'d> Subsetter<'d> {
self.read_cmap()?; self.read_cmap()?;
let cmap = self.cmap.as_ref().unwrap(); let cmap = self.cmap.as_ref().unwrap();
// The default glyph should be always present.
self.glyphs.push(self.font.default_glyph);
for &c in &self.chars { for &c in &self.chars {
self.glyphs.push(cmap.get(c).ok_or_else(|| FontError::MissingCharacter(c))?) self.glyphs.push(cmap.get(c).ok_or_else(|| FontError::MissingCharacter(c))?)
} }
self.glyphs.push(self.font.default_glyph);
// Composite glyphs may need additional glyphs we have not yet in our list. // Composite glyphs may need additional glyphs we have not yet in our list.
// So now we have a look at the glyf table to check that and add glyphs // So now we have a look at the glyf table to check that and add glyphs
// we need additionally. // we need additionally.
@ -678,7 +681,10 @@ impl<'d> Subsetter<'d> {
while i + 1 < len && this.chars[i+1] as u32 == this.chars[i] as u32 + 1 { while i + 1 < len && this.chars[i+1] as u32 == this.chars[i] as u32 + 1 {
i += 1; i += 1;
} }
groups.push((this.chars[start], this.chars[i], start));
// Add one to the start because we inserted the default glyph in front.
let glyph = 1 + start;
groups.push((this.chars[start], this.chars[i], glyph));
i += 1; i += 1;
} }