font subsetting: pyftsubset -> allsorts

This commit is contained in:
2025-12-05 14:02:13 -05:00
parent e9b8433117
commit 44fea82aaa
4 changed files with 297 additions and 135 deletions

View File

@@ -1,8 +1,14 @@
use epaint::{
FontFamily,
text::{FontData, FontDefinitions, FontTweak},
use allsorts::{
binary::read::ReadScope,
font::{Font, MatchingPresentation},
font_data::FontData as AllsortsFontData,
subset::subset,
tag,
};
use epaint::{
text::{FontData, FontDefinitions, FontTweak},
FontFamily,
};
use run_script::ScriptOptions;
use std::{
collections::BTreeMap,
env,
@@ -18,52 +24,44 @@ include!(concat!(
));
fn font_stripper(from: &str, out: &str, unicodes: Vec<char>) -> Result<Vec<u8>, String> {
let unicodes: Vec<String> = unicodes.iter().map(|c| to_unicode_hash(*c)).collect();
let font_path = format!("{}/assets/{}", env!("CARGO_MANIFEST_DIR"), from);
let font_data = std::fs::read(&font_path).map_err(|e| e.to_string())?;
let scope = ReadScope::new(&font_data);
let font_file = scope
.read::<AllsortsFontData>()
.map_err(|e| format!("Failed to read font data: {}", e))?;
let provider = font_file
.table_provider(0)
.map_err(|e| format!("Failed to get table provider: {}", e))?;
let mut font = Font::new(provider).map_err(|e| format!("Failed to create font: {:?}", e))?;
let mut glyph_ids = Vec::new();
for &ch in &unicodes {
let mut glyph_ids_curr = font
.map_glyphs(
&ch.to_string(),
tag::LATN,
MatchingPresentation::NotRequired,
)
.into_iter()
.map(|glyph| glyph.glyph_index)
.collect();
glyph_ids.append(&mut glyph_ids_curr);
}
// Include .notdef glyph
glyph_ids.push(0);
glyph_ids.sort();
glyph_ids.dedup();
let subset_data = subset(&font.font_table_provider, &glyph_ids)
.map_err(|e| format!("Failed to subset font: {}", e))?;
let new_path = [&env::var("OUT_DIR").unwrap(), out].concat();
let unicodes_formatted = unicodes
.iter()
.map(|u| format!("U+{}", u))
.collect::<Vec<String>>()
.join(",");
std::fs::write(&new_path, &subset_data)
.map_err(|e| format!("Failed to write subset font: {}", e))?;
// Test to see if pyftsubset is found
let pyftsubset_detect = run_script::run("whereis pyftsubset", &(vec![]), &ScriptOptions::new());
match pyftsubset_detect {
Ok((_i, s1, _s2)) => {
if s1 == "pyftsubset: " {
return Err(String::from("pyftsubset not found"));
}
}
// It was not, return an error and abort
Err(x) => return Err(x.to_string()),
}
let script_result = run_script::run(
&format!(
"pyftsubset {}/assets/{} --unicodes={}
mv {}/assets/{} {}",
env!("CARGO_MANIFEST_DIR"),
from,
unicodes_formatted,
env!("CARGO_MANIFEST_DIR"),
from.replace(".ttf", ".subset.ttf"),
new_path
),
&(vec![]),
&ScriptOptions::new(),
);
if let Ok((_, _, error)) = script_result {
if error.is_empty() {
return Ok(std::fs::read(new_path).unwrap());
} else {
return Err(error);
}
} else if let Err(error) = script_result {
return Err(error.to_string());
}
unreachable!()
Ok(subset_data)
}
fn main() {