Add more tests for table parsers 🔋
This commit is contained in:
parent
030d301f0c
commit
7eec0b8dd7
@ -270,10 +270,18 @@ impl PdfFont {
|
||||
}
|
||||
|
||||
// Subset the font using the selected characters.
|
||||
let subsetted = font.subsetted(
|
||||
let subset_result = font.subsetted(
|
||||
chars.iter().cloned(),
|
||||
&["head", "hhea", "hmtx", "maxp", "cmap", "cvt ", "fpgm", "prep", "loca", "glyf"][..]
|
||||
)?;
|
||||
);
|
||||
|
||||
// Check if the subsetting was successful and if it could not handle this
|
||||
// font we just copy it plainly.
|
||||
let subsetted = match subset_result {
|
||||
Ok(font) => font,
|
||||
Err(FontError::UnsupportedFont(_)) => font.clone(),
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
|
||||
// Specify flags for the font.
|
||||
let mut flags = FontFlags::empty();
|
||||
|
@ -83,14 +83,15 @@ impl Font {
|
||||
|
||||
// Create a conversion function between font units and sizes.
|
||||
let font_unit_ratio = 1.0 / (head.units_per_em as f32);
|
||||
let font_unit_to_size = |x| Size::pt(font_unit_ratio * x as f32);
|
||||
let font_unit_to_size = |x| Size::pt(font_unit_ratio * x);
|
||||
|
||||
// Find out the name of the font.
|
||||
let font_name = name.get_decoded(NameEntry::PostScriptName)
|
||||
.unwrap_or_else(|| "unknown".to_owned());
|
||||
|
||||
// Convert the widths from font units to sizes.
|
||||
let widths = hmtx.metrics.iter().map(|m| font_unit_to_size(m.advance_width)).collect();
|
||||
let widths = hmtx.metrics.iter()
|
||||
.map(|m| font_unit_to_size(m.advance_width as f32)).collect();
|
||||
|
||||
// Calculate the typesetting-relevant metrics.
|
||||
let metrics = FontMetrics {
|
||||
@ -98,14 +99,14 @@ impl Font {
|
||||
monospace: post.is_fixed_pitch,
|
||||
italic_angle: post.italic_angle.to_f32(),
|
||||
bounding_box: [
|
||||
font_unit_to_size(head.x_min),
|
||||
font_unit_to_size(head.y_min),
|
||||
font_unit_to_size(head.x_max),
|
||||
font_unit_to_size(head.y_max),
|
||||
font_unit_to_size(head.x_min as f32),
|
||||
font_unit_to_size(head.y_min as f32),
|
||||
font_unit_to_size(head.x_max as f32),
|
||||
font_unit_to_size(head.y_max as f32),
|
||||
],
|
||||
ascender: font_unit_to_size(os2.s_typo_ascender),
|
||||
descender: font_unit_to_size(os2.s_typo_descender),
|
||||
cap_height: font_unit_to_size(os2.s_cap_height.unwrap_or(os2.s_typo_ascender)),
|
||||
ascender: font_unit_to_size(os2.s_typo_ascender as f32),
|
||||
descender: font_unit_to_size(os2.s_typo_descender as f32),
|
||||
cap_height: font_unit_to_size(os2.s_cap_height.unwrap_or(os2.s_typo_ascender) as f32),
|
||||
weight_class: os2.us_weight_class,
|
||||
};
|
||||
|
||||
@ -352,7 +353,6 @@ error_type! {
|
||||
OpentypeError::InvalidFont(message) => FontError::InvalidFont(message),
|
||||
OpentypeError::MissingTable(tag) => FontError::MissingTable(tag.to_string()),
|
||||
OpentypeError::Io(err) => FontError::Io(err),
|
||||
_ => panic!("unexpected extensible variant"),
|
||||
}),
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use std::io::{Cursor, Seek, SeekFrom};
|
||||
|
||||
use byteorder::{BE, ReadBytesExt, WriteBytesExt};
|
||||
use opentype::{OpenTypeReader, Outlines, Table, TableRecord, Tag};
|
||||
use opentype::tables::{CharMap, Locations, HorizontalMetrics, Glyphs};
|
||||
use opentype::tables::{Header, CharMap, Locations, HorizontalMetrics, Glyphs};
|
||||
|
||||
use crate::size::Size;
|
||||
use super::{Font, FontError, FontResult};
|
||||
@ -56,8 +56,7 @@ impl<'a> Subsetter<'a> {
|
||||
/// Do the subsetting.
|
||||
fn run<I, S>(mut self, tables: I) -> FontResult<Font>
|
||||
where I: IntoIterator<Item=S>, S: AsRef<str> {
|
||||
// Quit early if we cannot handle the font.
|
||||
if self.outlines != Outlines::TrueType {
|
||||
if self.outlines == Outlines::CFF {
|
||||
return Err(FontError::UnsupportedFont("CFF outlines".to_string()));
|
||||
}
|
||||
|
||||
@ -216,7 +215,7 @@ impl<'a> Subsetter<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Subset the `hhea` table by changing the glyph count in it.
|
||||
/// Subset the `hhea` table by changing the number of horizontal metrics in it.
|
||||
fn subset_hhea(&mut self) -> FontResult<()> {
|
||||
let tag = "hhea".parse().unwrap();
|
||||
let hhea = self.read_table_data(tag)?;
|
||||
@ -235,7 +234,7 @@ impl<'a> Subsetter<'a> {
|
||||
self.write_table_body(tag, |this| {
|
||||
for &glyph in &this.glyphs {
|
||||
let metrics = hmtx.get(glyph).take_invalid("missing glyph metrics")?;
|
||||
this.body.write_i16::<BE>(metrics.advance_width)?;
|
||||
this.body.write_u16::<BE>(metrics.advance_width)?;
|
||||
this.body.write_i16::<BE>(metrics.left_side_bearing)?;
|
||||
}
|
||||
Ok(())
|
||||
@ -352,8 +351,14 @@ impl<'a> Subsetter<'a> {
|
||||
break;
|
||||
}
|
||||
|
||||
let args_len = if flags & 0x0001 == 1 { 4 } else { 2 };
|
||||
cursor.seek(SeekFrom::Current(args_len))?;
|
||||
// Skip additional arguments.
|
||||
let skip = if flags & 1 != 0 { 4 } else { 2 }
|
||||
+ if flags & 8 != 0 { 2 }
|
||||
else if flags & 64 != 0 { 4 }
|
||||
else if flags & 128 != 0 { 8 }
|
||||
else { 0 };
|
||||
|
||||
cursor.seek(SeekFrom::Current(skip))?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,13 +370,19 @@ impl<'a> Subsetter<'a> {
|
||||
|
||||
/// Subset the `loca` table by changing to the new offsets.
|
||||
fn subset_loca(&mut self) -> FontResult<()> {
|
||||
let format = self.read_table::<Header>()?.index_to_loc_format;
|
||||
let tag = "loca".parse().unwrap();
|
||||
let loca = self.read_table::<Locations>()?;
|
||||
|
||||
self.write_table_body(tag, |this| {
|
||||
let mut offset = 0;
|
||||
for &glyph in &this.glyphs {
|
||||
this.body.write_u32::<BE>(offset)?;
|
||||
if format == 0 {
|
||||
this.body.write_u16::<BE>((offset / 2) as u16)?;
|
||||
} else {
|
||||
this.body.write_u32::<BE>(offset)?;
|
||||
}
|
||||
|
||||
let len = loca.length(glyph).take_invalid("missing loca entry")?;
|
||||
offset += len;
|
||||
}
|
||||
@ -458,7 +469,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn subset() {
|
||||
let program = std::fs::read("../fonts/NotoSans-Regular.ttf").unwrap();
|
||||
let program = std::fs::read("../fonts/SourceSansPro-Regular.ttf").unwrap();
|
||||
let font = Font::new(program).unwrap();
|
||||
|
||||
let subsetted = font.subsetted(
|
||||
@ -467,6 +478,6 @@ mod tests {
|
||||
"cvt ", "fpgm", "prep", "loca", "glyf"][..]
|
||||
).unwrap();
|
||||
|
||||
std::fs::write("../target/NotoSans-Subsetted.ttf", &subsetted.program).unwrap();
|
||||
std::fs::write("../target/SourceSansPro-Subsetted.ttf", &subsetted.program).unwrap();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user