Skip to content

Commit

Permalink
update API a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurenzV committed May 19, 2024
1 parent bef209f commit 2c10b33
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 52 deletions.
2 changes: 1 addition & 1 deletion src/cff/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ pub fn subset<'a>(ctx: &mut Context<'a>) -> Result<()> {
IntegerNumber::from_i32_as_int5(w.len() as i32);
// FDSelect
w.extend(&build_fd_index(
ctx.mapper,
&ctx.mapper,
table.cid_metadata.fd_select,
&fd_remapper,
)?);
Expand Down
18 changes: 7 additions & 11 deletions src/glyf.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use super::*;
use crate::Error::{MalformedFont, SubsetError};
use std::collections::HashSet;
use std::collections::{BTreeMap, HashSet};

pub(crate) fn glyph_closure(face: &Face, gid_mapper: &mut GidMapper) -> Result<()> {
pub(crate) fn glyph_closure(face: &Face, gid_set: &mut BTreeSet<u16>) -> Result<()> {
let table = Table::new(face).ok_or(MalformedFont)?;

let mut all_glyphs = HashSet::new();
let mut process_glyphs = gid_mapper.old_gids().collect::<Vec<_>>();
let mut process_glyphs = gid_set.iter().copied().collect::<Vec<_>>();

while let Some(glyph) = process_glyphs.pop() {
all_glyphs.insert(glyph);
gid_set.insert(glyph);

let glyph_data = match table.glyph_data(glyph) {
Some(glph_data) => glph_data,
None => unimplemented!(),
None => return Err(InvalidGidMapper),
};

if glyph_data.is_empty() {
Expand All @@ -24,17 +24,13 @@ pub(crate) fn glyph_closure(face: &Face, gid_mapper: &mut GidMapper) -> Result<(

if num_contours < 0 {
for component in component_glyphs(glyph_data).ok_or(MalformedFont)? {
if !all_glyphs.contains(&component) {
if !gid_set.contains(&component) {
process_glyphs.push(component);
}
}
}
}

for glyph in all_glyphs {
gid_mapper.remap(glyph);
}

Ok(())
}

Expand Down
37 changes: 17 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,42 +55,39 @@ pub use crate::remapper::GidMapper;
use crate::write::{Writeable, Writer};
use crate::Error::{InvalidGidMapper, MalformedFont, UnknownKind};
use std::borrow::Cow;
use std::collections::BTreeSet;
use std::fmt::{self, Debug, Display, Formatter};

/// Subset a font face to include less glyphs and tables.
///
/// - The `data` must be in the OpenType font format.
/// - The `index` is only relevant if the data contains a font collection
/// (`.ttc` or `.otc` file). Otherwise, it should be 0.
pub fn subset(data: &[u8], index: u32, mapper: &GidMapper) -> Result<Vec<u8>> {
let mut owned_mapper = mapper.clone();
let context = prepare_context(data, index, &mut owned_mapper)?;

pub fn subset(data: &[u8], index: u32, gids: &[u16]) -> Result<(Vec<u8>, GidMapper)> {
let context = prepare_context(data, index, gids)?;
_subset(context)
}

fn prepare_context<'a>(
data: &'a [u8],
index: u32,
mapper: &'a mut GidMapper,
) -> Result<Context<'a>> {
fn prepare_context<'a>(data: &'a [u8], index: u32, gids: &[u16]) -> Result<Context<'a>> {
let face = parse(data, index)?;
let kind = match (face.table(Tag::GLYF), face.table(Tag::CFF)) {
(Some(_), _) => FontKind::TrueType,
(_, Some(_)) => FontKind::Cff,
_ => return Err(UnknownKind),
};

let maxp = face.table(Tag::MAXP).ok_or(MalformedFont)?;
let mut r = Reader::new_at(maxp, 4);
let num_glyphs = r.read::<u16>().ok_or(MalformedFont)?;
let mut gid_set = BTreeSet::from_iter(gids.iter().copied());
// .notdef always is part of the subset.
gid_set.insert(0);

if mapper.old_gids().any(|g| g >= num_glyphs) {
return Err(InvalidGidMapper);
if kind == FontKind::TrueType {
glyf::glyph_closure(&face, &mut gid_set)?;
}

if kind == FontKind::TrueType {
glyf::glyph_closure(&face, mapper)?;
let mut mapper = GidMapper::new();

for gid in gid_set {
mapper.remap(gid);
}

Ok(Context {
Expand All @@ -102,7 +99,7 @@ fn prepare_context<'a>(
})
}

fn _subset(mut ctx: Context) -> Result<Vec<u8>> {
fn _subset(mut ctx: Context) -> Result<(Vec<u8>, GidMapper)> {
// See here for the required tables:
// https://learn.microsoft.com/en-us/typography/opentype/spec/otff#required-tables
// some of those are not strictly needed according to the PDF specification,
Expand Down Expand Up @@ -181,7 +178,7 @@ fn parse(data: &[u8], index: u32) -> Result<Face<'_>> {
}

/// Construct a brand new font.
fn construct(mut ctx: Context) -> Vec<u8> {
fn construct(mut ctx: Context) -> (Vec<u8>, GidMapper) {
let mut cloned = ctx.face.records.clone();
cloned.sort_by_key(|r| r.tag);

Expand Down Expand Up @@ -242,7 +239,7 @@ fn construct(mut ctx: Context) -> Vec<u8> {
data[i..i + 4].copy_from_slice(&val.to_be_bytes());
}

data
(data, ctx.mapper)
}

/// Calculate a checksum over the sliced data as a sum of u32s. If the data
Expand All @@ -263,7 +260,7 @@ struct Context<'a> {
/// Original face.
face: Face<'a>,
/// A map from old gids to new gids, and the reverse
mapper: &'a GidMapper,
mapper: GidMapper,
/// The kind of face.
kind: FontKind,
/// Subsetted tables.
Expand Down
11 changes: 1 addition & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,8 @@ fn main() {
// Read the raw font data.
let data = std::fs::read(&args[1]).unwrap();
let gids = parse_gids(&args.get(3).to_owned().unwrap_or(&"0-5".to_owned()));
let mapper = {
let mut mapper = GidMapper::new();

for gid in &gids {
mapper.remap(*gid);
}

mapper
};

let sub = subset(&data, 0, &mapper).unwrap();
let (sub, _) = subset(&data, 0, &gids).unwrap();

// Write the resulting file.
std::fs::write(&args.get(2).unwrap_or(&"res.otf".to_owned()), sub).unwrap();
Expand Down
11 changes: 1 addition & 10 deletions tests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,8 @@ fn get_test_context(font_file: &str, gids: &str) -> Result<TestContext> {
let face = ttf_parser::Face::parse(&data, 0).unwrap();

let gids: Vec<_> = parse_gids(gids, face.number_of_glyphs());
let mapper = {
let mut mapper = GidMapper::new();

for gid in &gids {
mapper.remap(*gid);
}

mapper
};

let subset = subset(&data, 0, &mapper)?;
let (subset, mapper) = subset(&data, 0, &gids)?;

if SAVE_SUBSETS {
save_font(&subset);
Expand Down

0 comments on commit 2c10b33

Please sign in to comment.