use std::io;
use write_fonts::FontBuilder;
use write_fonts::types::Tag;
use crate::formats::woff2::Woff2TransformCache;
use crate::input::{
LoadedSvgSource, ResolvedFileGenerationOptions, finalize_generate_webfonts_options,
resolve_generate_webfonts_options,
};
use crate::pipeline::build_font_outputs;
use crate::sfnt::{self, SerializedFontTables};
use crate::svg::types::{GlyphCache, ParsedGlyph, PreparedSvgFont};
use crate::svg::{
finalize_glyphs, parse_glyphs, prepare_svg_font, prepare_svg_font_incremental,
svg_options_from_options,
};
use crate::{GenerateWebfontsOptions, GenerateWebfontsResult};
pub struct BenchTsRenderer {
options: crate::input::ResolvedGenerationOptions,
names: Vec<String>,
}
impl BenchTsRenderer {
pub fn new(names: Vec<String>) -> Self {
Self {
options: crate::input::GenerationOptions::default()
.resolve(false)
.unwrap(),
names,
}
}
pub fn render(&self) -> String {
crate::rendering::ts::render_ts(
&self.options,
self.names.iter().map(String::as_str),
false,
None,
)
}
}
#[derive(Clone)]
pub struct BenchSvgSource {
pub path: String,
pub glyph_name: String,
pub contents: String,
}
#[derive(Clone, Default)]
pub struct BenchGlyphCache(GlyphCache);
pub struct BenchSvgPrepareInput {
options: ResolvedFileGenerationOptions,
sources: Vec<LoadedSvgSource>,
}
#[derive(Clone)]
pub struct BenchParsedGlyphs(Vec<ParsedGlyph>);
#[derive(Clone)]
pub struct BenchPreparedSvgFont(PreparedSvgFont);
#[derive(Clone)]
pub struct BenchSerializedFontTables(SerializedFontTables);
#[derive(Clone, Default)]
pub struct BenchWoff2TransformCache(Woff2TransformCache);
pub struct BenchPreparedWoff2(crate::formats::woff2::PreparedWoff2);
fn load_sources(sources: &[BenchSvgSource]) -> Vec<LoadedSvgSource> {
sources
.iter()
.map(|source| LoadedSvgSource {
contents: source.contents.clone().into(),
glyph_name: source.glyph_name.clone(),
id: source.path.clone(),
})
.collect()
}
fn resolve(
options: GenerateWebfontsOptions,
sources: &[LoadedSvgSource],
) -> io::Result<ResolvedFileGenerationOptions> {
let mut options = resolve_generate_webfonts_options(options)?;
finalize_generate_webfonts_options(&mut options, sources)?;
Ok(options)
}
pub fn svg_prepare_input(
options: GenerateWebfontsOptions,
sources: &[BenchSvgSource],
) -> io::Result<BenchSvgPrepareInput> {
let sources = load_sources(sources);
let options = resolve(options, &sources)?;
Ok(BenchSvgPrepareInput { options, sources })
}
pub fn prepare_svg_full(input: &BenchSvgPrepareInput) -> io::Result<usize> {
let svg_options = svg_options_from_options(&input.options);
let prepared = prepare_svg_font(&svg_options, &input.sources)?;
Ok(prepared.processed_glyphs.len())
}
pub fn parse_svg_only(
options: GenerateWebfontsOptions,
sources: &[BenchSvgSource],
) -> io::Result<BenchParsedGlyphs> {
let sources = load_sources(sources);
let options = resolve(options, &sources)?;
let svg_options = svg_options_from_options(&options);
parse_glyphs(&svg_options, &sources).map(BenchParsedGlyphs)
}
pub fn finalize_svg_only(
options: GenerateWebfontsOptions,
sources: &[BenchSvgSource],
parsed: BenchParsedGlyphs,
) -> io::Result<BenchPreparedSvgFont> {
let sources = load_sources(sources);
let options = resolve(options, &sources)?;
let svg_options = svg_options_from_options(&options);
finalize_glyphs(&svg_options, parsed.0).map(BenchPreparedSvgFont)
}
pub fn build_outputs_only(
options: GenerateWebfontsOptions,
sources: &[BenchSvgSource],
prepared: &BenchPreparedSvgFont,
) -> io::Result<usize> {
let sources = load_sources(sources);
let options = resolve(options, &sources)?;
let svg_options = svg_options_from_options(&options);
let fonts = build_font_outputs(&options, &svg_options, &prepared.0, None)?;
Ok(fonts.svg_font.as_ref().map_or(0, |v| v.len())
+ fonts.ttf_font.as_ref().map_or(0, |v| v.len())
+ fonts.woff_font.as_ref().map_or(0, |v| v.len())
+ fonts.woff2_font.as_ref().map_or(0, |v| v.len())
+ fonts.eot_font.as_ref().map_or(0, |v| v.len()))
}
pub fn build_serialized_ttf_tables(
options: GenerateWebfontsOptions,
sources: &[BenchSvgSource],
prepared: &BenchPreparedSvgFont,
) -> io::Result<BenchSerializedFontTables> {
let sources = load_sources(sources);
let options = resolve(options, &sources)?;
sfnt::build(
sfnt::ttf_options_from_options(&options),
&prepared.0.processed_glyphs,
None,
)
.map(BenchSerializedFontTables)
}
pub fn rewrap_serialized_ttf_tables(
tables: &BenchSerializedFontTables,
) -> io::Result<BenchSerializedFontTables> {
SerializedFontTables::new(tables.0.clone_raw_tables()).map(BenchSerializedFontTables)
}
pub fn serialized_ttf_uncached(tables: &BenchSerializedFontTables) -> Vec<u8> {
tables.0.uncached_ttf()
}
pub fn internal_woff2(tables: &BenchSerializedFontTables, quality: u8) -> io::Result<Vec<u8>> {
crate::formats::woff2::tables_to_woff2(&tables.0, quality, None)
}
pub fn prepare_internal_woff2(
tables: &BenchSerializedFontTables,
cache: &mut BenchWoff2TransformCache,
) -> io::Result<BenchPreparedWoff2> {
crate::formats::woff2::prepare_woff2(&tables.0, &mut cache.0).map(BenchPreparedWoff2)
}
pub fn compress_prepared_internal_woff2(
prepared: &BenchPreparedWoff2,
quality: u8,
) -> io::Result<usize> {
crate::formats::woff2::compress_prepared_woff2(&prepared.0, quality)
}
pub fn fontbuilder_ttf(tables: &BenchSerializedFontTables) -> Vec<u8> {
let mut builder = FontBuilder::new();
for table in tables.0.tables() {
builder.add_raw(Tag::new(&table.tag), table.bytes.as_slice());
}
builder.build()
}
pub fn clear_woff1_payload_cache(result: &mut GenerateWebfontsResult) {
if let Some(state) = result.regeneration_state.lock().unwrap().as_mut()
&& let Some(cache) = state.ttf_cache.as_mut()
{
cache.woff1_payloads.clear();
}
}
pub fn prepare_svg_incremental(
input: &BenchSvgPrepareInput,
cache: &mut BenchGlyphCache,
) -> io::Result<usize> {
let svg_options = svg_options_from_options(&input.options);
let prepared = prepare_svg_font_incremental(&svg_options, &input.sources, &mut cache.0)?;
Ok(prepared.processed_glyphs.len())
}