diff --git a/src/bin/diffenator3.rs b/src/bin/diffenator3.rs index 49771fa..3976341 100644 --- a/src/bin/diffenator3.rs +++ b/src/bin/diffenator3.rs @@ -47,6 +47,10 @@ struct Cli { #[clap(long = "json")] json: bool, + /// Location in design space, in the form axis=123,other=456 + #[clap(long = "location")] + location: Option, + /// The first font file to compare font1: PathBuf, /// The second font file to compare @@ -93,8 +97,8 @@ fn main() { let font_binary_a = std::fs::read(cli.font1).expect("Couldn't open file"); let font_binary_b = std::fs::read(cli.font2).expect("Couldn't open file"); - let font_a = DFont::new(&font_binary_a); - let font_b = DFont::new(&font_binary_b); + let font_a = DFont::new(&font_binary_a, cli.location.as_deref()); + let font_b = DFont::new(&font_binary_b, cli.location.as_deref()); let mut diff = Map::new(); if cli.tables { let table_diff = table_diff(&font_a.fontref(), &font_b.fontref()); diff --git a/src/dfont.rs b/src/dfont.rs index fbb29ce..246ab5b 100644 --- a/src/dfont.rs +++ b/src/dfont.rs @@ -1,26 +1,29 @@ use font_types::NameId; use read_fonts::FontRef; -use skrifa::MetadataProvider; +use skrifa::{instance::Location, setting::VariationSetting, MetadataProvider}; use std::collections::HashSet; use ucd::Codepoint; pub struct DFont { pub backing: Vec, - variations: String, + pub location: Location, pub codepoints: HashSet, } impl DFont { - pub fn new(string: &[u8]) -> Self { + pub fn new(string: &[u8], variations: Option<&str>) -> Self { let backing: Vec = string.to_vec(); let mut fnt = DFont { backing, - variations: "".to_string(), codepoints: HashSet::new(), + location: Location::default(), }; let cmap = fnt.fontref().charmap(); fnt.codepoints = cmap.mappings().map(|(cp, _)| cp).collect(); + if let Some(variations) = variations { + fnt.location = fnt.parse_location(variations); + } fnt } @@ -53,6 +56,18 @@ impl DFont { .any(|tr| tr.tag() == "fvar") } + fn parse_location(&self, variations: &str) -> Location { + let mut settings: Vec = vec![]; + for variation in variations.split(',') { + let mut parts = variation.split('='); + let axis = parts.next().expect("No axis"); + let value = parts.next().expect("No value"); + let value = value.parse::().expect("Couldn't parse value"); + settings.push((axis, value).into()); + } + self.fontref().axes().location(&settings) + } + pub fn supported_scripts(&self) -> HashSet { let cmap = self.fontref().charmap(); let mut strings = HashSet::new(); diff --git a/src/render/renderer.rs b/src/render/renderer.rs index 13b6e10..d4b003b 100644 --- a/src/render/renderer.rs +++ b/src/render/renderer.rs @@ -55,22 +55,23 @@ pub struct Renderer<'a> { face: Face<'a>, scale: f32, font: skrifa::FontRef<'a>, + location: LocationRef<'a>, plan: ShapePlan, outlines: OutlineGlyphCollection<'a>, } impl<'a> Renderer<'a> { pub fn new( - font: &'a DFont, + dfont: &'a DFont, font_size: f32, direction: Direction, script: Option, ) -> Self { - let face = Face::from_slice(&font.backing, 0).expect("Foo"); - let font = skrifa::FontRef::new(&font.backing).unwrap_or_else(|_| { + let face = Face::from_slice(&dfont.backing, 0).expect("Foo"); + let font = skrifa::FontRef::new(&dfont.backing).unwrap_or_else(|_| { panic!( "error constructing a Font from data for {:}", - font.family_name() + dfont.family_name() ); }); let plan = ShapePlan::new(&face, direction, script, None, &[]); @@ -81,6 +82,7 @@ impl<'a> Renderer<'a> { font, plan, scale: font_size, + location: (&dfont.location).into(), outlines, } } @@ -104,7 +106,7 @@ impl<'a> Renderer<'a> { } pen.offset_x = cursor + (position.x_offset as f32 * factor); pen.offset_y = -position.y_offset as f32 * factor; - let settings = DrawSettings::unhinted(Size::new(self.scale), LocationRef::default()); + let settings = DrawSettings::unhinted(Size::new(self.scale), self.location); let _ = self .outlines @@ -186,7 +188,7 @@ mod tests { fn test_zeno_path() { let path = "NotoSansArabic-NewRegular.ttf"; let data = std::fs::read(path).unwrap(); - let font = DFont::new(&data); + let font = DFont::new(&data, None); let mut renderer = Renderer::new(&font, 40.0, Direction::RightToLeft, Some(script::ARABIC)); let (_serialized_buffer, commands) = renderer .string_to_positioned_glyphs("السلام عليكم")