66 lines
1.9 KiB
Rust

use std::{
ffi::CString,
fs::read_to_string,
io::{Read, Write},
path::Path,
};
use log::debug;
use pyo3::{
ffi::c_str,
prelude::*,
types::{PyList, PyTuple},
};
use tempfile::NamedTempFile;
pub fn subset(data: &[u8], unicodes: &[u32]) -> Vec<u8> {
pyo3::prepare_freethreaded_python();
let mut input = NamedTempFile::new().expect("input file");
input.write_all(data).expect("writing input");
let mut output = NamedTempFile::new().expect("output file");
let path = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/fonttools/Lib"));
let init_path = path.join("fontTools/subset/__init__.py");
let py_init = CString::new(read_to_string(init_path).unwrap()).unwrap();
let result = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
let syspath = py
.import("sys")?
.getattr("path")?
.downcast_into::<PyList>()?;
syspath.insert(0, path)?;
let app: Py<PyAny> = PyModule::from_code(py, py_init.as_c_str(), c_str!(""), c_str!(""))?
.getattr("main")?
.into();
let args = PyList::new(py, vec![
input.path().to_str().unwrap(),
&format_unicodes(unicodes),
&format!("--output-file={}", output.path().to_str().unwrap()),
])?;
debug!("Running pyftsubset with {:?}", args);
let args_tuple = PyTuple::new(py, &[args])?;
app.call1(py, args_tuple)
});
result.expect("subsetting");
let mut buf = vec![];
output.read_to_end(&mut buf).expect("reading output");
buf
}
fn format_unicodes(unicodes: &[u32]) -> String {
use std::fmt::Write;
let mut s = "--unicodes=".to_owned();
let mut first = true;
for u in unicodes {
if first {
write!(s, "{:x}", u).expect("append unicode");
first = false;
} else {
write!(s, ",{:x}", u).expect("append unicode");
}
}
s
}