1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
//! The result of a compilation
use write_fonts::{
dump_table,
read::TopLevelTable,
tables::{self as wtables, maxp::Maxp},
validate::Validate,
FontBuilder, FontWrite,
};
use super::{error::BinaryCompilationError, Opts};
use crate::{Diagnostic, GlyphMap};
/// The tables generated by this compilation.
///
/// All tables are optional, and the set of tables that are present depends
/// on the input file.
///
/// Each table is a type defined in the [`write-fonts`][] crate. The caller
/// may either interact with these directly, or else they may use the [`to_binary`]
/// method to generate a binary font.
///
/// [`to_binary`]: Compilation::to_binary
pub struct Compilation {
/// Any warnings encountered during parsing or compilation
pub warnings: Vec<Diagnostic>,
/// The `head` table, if one was generated
pub head: Option<wtables::head::Head>,
/// The `hhea` table, if one was generated
pub hhea: Option<wtables::hhea::Hhea>,
/// The `vhea` table, if one was generated
pub vhea: Option<wtables::vhea::Vhea>,
/// The `OS/2` table, if one was generated
pub os2: Option<wtables::os2::Os2>,
/// The `GDEF` table, if one was generated
pub gdef: Option<wtables::gdef::Gdef>,
/// The `BASE` table, if one was generated
pub base: Option<wtables::base::Base>,
/// The `name` table, if one was generated
pub name: Option<wtables::name::Name>,
/// The `STAT` table, if one was generated
pub stat: Option<wtables::stat::Stat>,
/// The `GSUB` table, if one was generated
pub gsub: Option<wtables::gsub::Gsub>,
/// The `GPOS` table, if one was generated
pub gpos: Option<wtables::gpos::Gpos>,
}
impl Compilation {
/// Assemble the output tables into a `FontBuilder`.
///
/// This is a convenience method. To compile a binary font you can use
/// [`to_binary`] instead, and for more fine-grained control you can inspect
/// and manipulate the raw tables directly.
///
/// [`to_binary`]: Compilation::to_binary
pub fn to_font_builder(&self) -> Result<FontBuilder, BinaryCompilationError> {
let mut builder = FontBuilder::default();
builder.add(self.head.as_ref())?;
builder.add(self.hhea.as_ref())?;
builder.add(self.vhea.as_ref())?;
builder.add(self.os2.as_ref())?;
builder.add(self.gdef.as_ref())?;
builder.add(self.base.as_ref())?;
builder.add(self.name.as_ref())?;
builder.add(self.stat.as_ref())?;
builder.add(self.gsub.as_ref())?;
builder.add(self.gpos.as_ref())?;
Ok(builder)
}
/// Compile the output tables into a font.
///
/// This is a convenience method used for things like testing; if you are
/// building a font compiler you will probably prefer to manipulate the
/// generated tables directly.
pub fn to_binary(
&self,
glyph_map: &GlyphMap,
opts: Opts,
) -> Result<Vec<u8>, BinaryCompilationError> {
// because we often inspect our output with ttx, and ttx fails if maxp is
// missing, we create a maxp table.
let mut builder = self.to_font_builder()?;
let maxp = Maxp::new(glyph_map.len().try_into().unwrap());
builder.add(Some(&maxp))?;
if opts.make_post_table {
let post = glyph_map.make_post_table();
builder.add(Some(&post))?;
}
Ok(builder.build())
}
}
// a little helper trait for adding raw tables to a FontBuilder
trait BuilderHelper {
fn add<T: FontWrite + Validate + TopLevelTable>(
&mut self,
table: Option<&T>,
) -> Result<(), BinaryCompilationError>;
}
impl BuilderHelper for FontBuilder<'_> {
fn add<T: FontWrite + Validate + TopLevelTable>(
&mut self,
table: Option<&T>,
) -> Result<(), BinaryCompilationError> {
let Some(table) = table else { return Ok(()) };
dump_table(table).map(|bytes| self.add_table(T::TAG, bytes))?;
Ok(())
}
}