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.
font_families: vec![SansSerif, Serif, Monospace],
font_size: 12.0,
font_size: 11.0,
line_spacing: 1.25,
}
}

View File

@ -164,35 +164,33 @@ impl<'d, W: Write> PdfEngine<'d, W> {
let mut id = self.offsets.fonts.0;
for font in &self.fonts {
let base_font = format!("ABCDEF+{}", font.name);
// Write the base font object referencing the CID font.
self.writer.write_obj(id,
Type0Font::new(
font.name.clone(),
base_font.clone(),
CMapEncoding::Predefined("Identity-H".to_owned()),
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.
self.writer.write_obj(id + 1,
CIDFont::new(
CIDFontType::Type2,
font.name.clone(),
base_font.clone(),
system_info.clone(),
id + 3,
id + 2,
).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).
self.writer.write_obj(id + 3,
self.writer.write_obj(id + 2,
FontDescriptor::new(
font.name.clone(),
base_font,
font.flags,
font.italic_angle,
)
@ -204,6 +202,10 @@ impl<'d, W: Write> PdfEngine<'d, W> {
.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.
self.writer.write_obj(id + 4, &FontStream::new(
&font.program,
@ -249,7 +251,7 @@ impl PdfFont {
let subsetted = font.subsetted(
chars.iter().cloned(),
&["head", "hhea", "maxp", "hmtx", "loca", "glyf"][..],
&["cvt ", "prep", "fpgm"][..],
&["cvt ", "prep", "fpgm", /* "OS/2", "cmap", "name", "post" */][..],
)?;
// Specify flags for the font

View File

@ -141,7 +141,7 @@ impl Font {
cmap: None,
hmtx: None,
loca: None,
glyphs: Vec::with_capacity(chars.len()),
glyphs: Vec::with_capacity(1 + chars.len()),
chars,
records: vec![],
body: vec![],
@ -445,12 +445,15 @@ impl<'d> Subsetter<'d> {
self.write_header()?;
// Build the new widths.
let widths = self.glyphs.iter()
.map(|&glyph| self.font.widths.get(glyph as usize).map(|&w| w)
.take_invalid("missing glyph metrics"))
.collect::<FontResult<Vec<_>>>()?;
.map(|&glyph| {
self.font.widths.get(glyph as usize).map(|&w| w)
.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>>();
Ok(Font {
@ -467,12 +470,12 @@ impl<'d> Subsetter<'d> {
self.read_cmap()?;
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 {
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.
// So now we have a look at the glyf table to check that and add glyphs
// 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 {
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;
}