Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 5 additions & 32 deletions otexplorer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
use std::{collections::HashSet, str::FromStr};

use font_types::Tag;
use read_fonts::{traversal::SomeTable, FileRef, FontRef, ReadError, TableProvider, TopLevelTable};
use read_fonts::{
traversal::{SomeTable, SomeTableProvider},
FileRef, FontRef,
};

mod print;
mod query;
Expand Down Expand Up @@ -96,38 +99,8 @@ fn hex_width(val: u32) -> usize {
}
}

/// Given a font and a tag, return the appropriate table as a [`dyn SomeTable`][SomeTable].
fn get_some_table<'a>(
font: &FontRef<'a>,
tag: Tag,
) -> Result<Box<dyn SomeTable<'a> + 'a>, ReadError> {
use read_fonts::tables;
match tag {
tables::gpos::Gpos::TAG => font.gpos().map(|x| Box::new(x) as _),
tables::gsub::Gsub::TAG => font.gsub().map(|x| Box::new(x) as _),
tables::cmap::Cmap::TAG => font.cmap().map(|x| Box::new(x) as _),
tables::fvar::Fvar::TAG => font.fvar().map(|x| Box::new(x) as _),
tables::avar::Avar::TAG => font.avar().map(|x| Box::new(x) as _),
tables::gdef::Gdef::TAG => font.gdef().map(|x| Box::new(x) as _),
tables::glyf::Glyf::TAG => font.glyf().map(|x| Box::new(x) as _),
tables::head::Head::TAG => font.head().map(|x| Box::new(x) as _),
tables::hhea::Hhea::TAG => font.hhea().map(|x| Box::new(x) as _),
tables::hmtx::Hmtx::TAG => font.hmtx().map(|x| Box::new(x) as _),
tables::loca::Loca::TAG => font.loca(None).map(|x| Box::new(x) as _),
tables::maxp::Maxp::TAG => font.maxp().map(|x| Box::new(x) as _),
tables::name::Name::TAG => font.name().map(|x| Box::new(x) as _),
tables::post::Post::TAG => font.post().map(|x| Box::new(x) as _),
tables::colr::Colr::TAG => font.colr().map(|x| Box::new(x) as _),
tables::stat::Stat::TAG => font.stat().map(|x| Box::new(x) as _),
tables::vhea::Vhea::TAG => font.vhea().map(|x| Box::new(x) as _),
tables::vmtx::Vmtx::TAG => font.vmtx().map(|x| Box::new(x) as _),
tables::svg::Svg::TAG => font.svg().map(|x| Box::new(x) as _),
_ => Err(ReadError::TableIsMissing(tag)),
}
}

fn print_table(font: &FontRef, tag: Tag) {
match get_some_table(font, tag) {
match font.expect_some_table(tag) {
Ok(table) => fancy_print_table(&table).unwrap(),
Err(err) => println!("{tag}: Error '{err}'"),
}
Expand Down
4 changes: 2 additions & 2 deletions otexplorer/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{borrow::Cow, fmt::Write, str::FromStr};

use font_types::Tag;
use read_fonts::{
traversal::{Field, FieldType, ResolvedOffset, SomeTable},
traversal::{Field, FieldType, ResolvedOffset, SomeTable, SomeTableProvider},
FontRef,
};

Expand All @@ -21,7 +21,7 @@ pub enum QueryElement {
}

pub fn print_query(font: &FontRef, query: &Query) -> Result<(), String> {
let table = match super::get_some_table(font, query.tag) {
let table = match font.expect_some_table(query.tag) {
Ok(table) => table,
Err(err) => return Err(err.to_string()),
};
Expand Down
75 changes: 74 additions & 1 deletion read-fonts/src/traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use types::{
use crate::{
array::{ComputedArray, VarLenArray},
read::{ComputeSize, ReadArgs},
FontData, FontRead, FontReadWithArgs, ReadError, VarSize,
tables, FontData, FontRead, FontReadWithArgs, ReadError, TableProvider, TopLevelTable, VarSize,
};

/// Types of fields in font tables.
Expand Down Expand Up @@ -285,6 +285,79 @@ impl<'a> dyn SomeTable<'a> + 'a {
}
}

/// The dynamic equivalent of [`TableProvider`]. It allows you to look up a table
/// by its tag.
pub trait SomeTableProvider<'a> {
/// Access the table for the given tag as a [`SomeTable`].
fn expect_some_table(&self, tag: Tag) -> Result<Box<dyn SomeTable<'a> + 'a>, ReadError>;
}

impl<'a, T> SomeTableProvider<'a> for T
where
T: TableProvider<'a>,
{
fn expect_some_table(&self, tag: Tag) -> Result<Box<dyn SomeTable<'a> + 'a>, ReadError> {
fn as_some_table<'a, T: SomeTable<'a> + 'a>(table_ref: T) -> Box<dyn SomeTable<'a> + 'a> {
Box::new(table_ref) as _
}

match tag {
tables::head::Head::TAG => self.head().map(as_some_table),
tables::name::Name::TAG => self.name().map(as_some_table),
tables::hhea::Hhea::TAG => self.hhea().map(as_some_table),
tables::vhea::Vhea::TAG => self.vhea().map(as_some_table),
tables::hmtx::Hmtx::TAG => self.hmtx().map(as_some_table),
tables::hdmx::Hdmx::TAG => self.hdmx().map(as_some_table),
tables::vmtx::Vmtx::TAG => self.vmtx().map(as_some_table),
tables::vorg::Vorg::TAG => self.vorg().map(as_some_table),
tables::fvar::Fvar::TAG => self.fvar().map(as_some_table),
tables::avar::Avar::TAG => self.avar().map(as_some_table),
tables::hvar::Hvar::TAG => self.hvar().map(as_some_table),
tables::vvar::Vvar::TAG => self.vvar().map(as_some_table),
tables::mvar::Mvar::TAG => self.mvar().map(as_some_table),
tables::maxp::Maxp::TAG => self.maxp().map(as_some_table),
tables::os2::Os2::TAG => self.os2().map(as_some_table),
tables::post::Post::TAG => self.post().map(as_some_table),
tables::gasp::Gasp::TAG => self.gasp().map(as_some_table),
tables::loca::Loca::TAG => self.loca(None).map(as_some_table),
tables::glyf::Glyf::TAG => self.glyf().map(as_some_table),
tables::gvar::Gvar::TAG => self.gvar().map(as_some_table),
// cvt not implemented
tables::cvar::Cvar::TAG => self.cvar().map(as_some_table),
// cff not implemented
// cff2 not implemented
tables::cmap::Cmap::TAG => self.cmap().map(as_some_table),
tables::gdef::Gdef::TAG => self.gdef().map(as_some_table),
tables::gpos::Gpos::TAG => self.gpos().map(as_some_table),
tables::gsub::Gsub::TAG => self.gsub().map(as_some_table),
tables::feat::Feat::TAG => self.feat().map(as_some_table),
tables::ltag::Ltag::TAG => self.ltag().map(as_some_table),
tables::ankr::Ankr::TAG => self.ankr().map(as_some_table),
tables::trak::Trak::TAG => self.trak().map(as_some_table),
tables::morx::Morx::TAG => self.morx().map(as_some_table),
tables::kerx::Kerx::TAG => self.kerx().map(as_some_table),
// kern not implemented
tables::colr::Colr::TAG => self.colr().map(as_some_table),
tables::cpal::Cpal::TAG => self.cpal().map(as_some_table),
tables::cblc::Cblc::TAG => self.cblc().map(as_some_table),
tables::cbdt::Cbdt::TAG => self.cbdt().map(as_some_table),
tables::eblc::Eblc::TAG => self.eblc().map(as_some_table),
tables::ebdt::Ebdt::TAG => self.ebdt().map(as_some_table),
tables::sbix::Sbix::TAG => self.sbix().map(as_some_table),
tables::stat::Stat::TAG => self.stat().map(as_some_table),
tables::svg::Svg::TAG => self.svg().map(as_some_table),
tables::varc::Varc::TAG => self.varc().map(as_some_table),
#[cfg(feature = "ift")]
tables::ift::IFT_TAG => self.ift().map(as_some_table),
#[cfg(feature = "ift")]
tables::ift::IFTX_TAG => self.iftx().map(as_some_table),
tables::meta::Meta::TAG => self.meta().map(as_some_table),
tables::base::Base::TAG => self.base().map(as_some_table),
_ => Err(ReadError::TableIsMissing(tag)),
}
}
}

struct FieldIter<'a, 'b> {
table: &'b dyn SomeTable<'a>,
idx: usize,
Expand Down