Skip to content

Commit

Permalink
Handle variable fonts!
Browse files Browse the repository at this point in the history
  • Loading branch information
simoncozens committed May 12, 2024
1 parent 3951b56 commit 5099818
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 12 deletions.
8 changes: 6 additions & 2 deletions src/bin/diffenator3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,

/// The first font file to compare
font1: PathBuf,
/// The second font file to compare
Expand Down Expand Up @@ -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());
Expand Down
23 changes: 19 additions & 4 deletions src/dfont.rs
Original file line number Diff line number Diff line change
@@ -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<u8>,
variations: String,
pub location: Location,
pub codepoints: HashSet<u32>,
}

impl DFont {
pub fn new(string: &[u8]) -> Self {
pub fn new(string: &[u8], variations: Option<&str>) -> Self {
let backing: Vec<u8> = 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
}

Expand Down Expand Up @@ -53,6 +56,18 @@ impl DFont {
.any(|tr| tr.tag() == "fvar")
}

fn parse_location(&self, variations: &str) -> Location {
let mut settings: Vec<VariationSetting> = 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::<f32>().expect("Couldn't parse value");
settings.push((axis, value).into());
}
self.fontref().axes().location(&settings)
}

pub fn supported_scripts(&self) -> HashSet<String> {
let cmap = self.fontref().charmap();
let mut strings = HashSet::new();
Expand Down
14 changes: 8 additions & 6 deletions src/render/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<rustybuzz::Script>,
) -> 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, &[]);
Expand All @@ -81,6 +82,7 @@ impl<'a> Renderer<'a> {
font,
plan,
scale: font_size,
location: (&dfont.location).into(),
outlines,
}
}
Expand All @@ -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
Expand Down Expand Up @@ -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("السلام عليكم")
Expand Down

0 comments on commit 5099818

Please sign in to comment.