diff --git a/otexplorer/src/main.rs b/otexplorer/src/main.rs index cff180199..bb1ae7d6c 100644 --- a/otexplorer/src/main.rs +++ b/otexplorer/src/main.rs @@ -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; @@ -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 + '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}'"), } diff --git a/otexplorer/src/query.rs b/otexplorer/src/query.rs index 4dad60d96..066f9188d 100644 --- a/otexplorer/src/query.rs +++ b/otexplorer/src/query.rs @@ -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, }; @@ -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()), }; diff --git a/read-fonts/src/traversal.rs b/read-fonts/src/traversal.rs index 7531f6afd..4c7abfa46 100644 --- a/read-fonts/src/traversal.rs +++ b/read-fonts/src/traversal.rs @@ -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. @@ -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 + 'a>, ReadError>; +} + +impl<'a, T> SomeTableProvider<'a> for T +where + T: TableProvider<'a>, +{ + fn expect_some_table(&self, tag: Tag) -> Result + 'a>, ReadError> { + fn as_some_table<'a, T: SomeTable<'a> + 'a>(table_ref: T) -> Box + '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,