summaryrefslogtreecommitdiff
path: root/src/font
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2019-06-25 21:07:06 +0200
committerLaurenz <laurmaedje@gmail.com>2019-06-25 21:07:06 +0200
commit7eec0b8dd70446803c9ffb84a253ebb7e68f3567 (patch)
tree1c1948b70e6ed2fcd03ac44aa3e08353de9d0fd8 /src/font
parent030d301f0c98b4d19a3f8ae22f553e22f74d592f (diff)
Add more tests for table parsers 🔋
Diffstat (limited to 'src/font')
-rw-r--r--src/font/mod.rs20
-rw-r--r--src/font/subset.rs31
2 files changed, 31 insertions, 20 deletions
diff --git a/src/font/mod.rs b/src/font/mod.rs
index 9c928938..5d257a9a 100644
--- a/src/font/mod.rs
+++ b/src/font/mod.rs
@@ -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"),
}),
}
diff --git a/src/font/subset.rs b/src/font/subset.rs
index bf3dc549..006c00e2 100644
--- a/src/font/subset.rs
+++ b/src/font/subset.rs
@@ -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();
}
}