use hayro::hayro_interpret::InterpreterSettings;
use hayro::hayro_interpret::font::{FontData, FontQuery, StandardFont};
use hayro::hayro_interpret::hayro_cmap::CidFamily;
use hayro::hayro_syntax::Pdf;
use hayro::{RenderCache, RenderSettings, render};
use std::path::Path;
use std::sync::Arc;
use vello_cpu::color::palette::css::WHITE;
fn load_asset(name: &str) -> Option<(FontData, u32)> {
let base = Path::new(env!("CARGO_MANIFEST_DIR")).join("../hayro-tests/assets");
let path = base.join(name);
let data = std::fs::read(&path).ok()?;
Some((Arc::new(data), 0))
}
fn main() {
if let Ok(()) = log::set_logger(&LOGGER) {
log::set_max_level(log::LevelFilter::Trace);
}
let file = std::fs::read(std::env::args().nth(1).unwrap()).unwrap();
let output_dir = std::env::args().nth(2).unwrap_or_else(|| ".".to_string());
let scale = std::env::args()
.nth(3)
.and_then(|s| s.parse::<f32>().ok())
.unwrap_or(1.0);
std::fs::create_dir_all(&output_dir).unwrap();
let pdf = Pdf::new(file).unwrap();
let interpreter_settings = InterpreterSettings {
font_resolver: Arc::new(move |query| match query {
FontQuery::Standard(s) => {
let name = pick_standard_font(s);
load_asset(name).or_else(|| Some(s.get_font_data()))
}
FontQuery::Fallback(f) => {
if let Some(cc) = &f.character_collection {
let name = match cc.family {
CidFamily::AdobeGB1 | CidFamily::AdobeCNS1 => {
if f.is_bold {
"NotoSansCJKsc-Bold.otf"
} else {
"NotoSansCJKsc-Regular.otf"
}
}
CidFamily::AdobeJapan1 => {
if f.is_bold {
"NotoSansCJKjp-Bold.otf"
} else {
"NotoSansCJKjp-Regular.otf"
}
}
CidFamily::AdobeKorea1 => {
if f.is_bold {
"NotoSansCJKkr-Bold.otf"
} else {
"NotoSansCJKkr-Regular.otf"
}
}
_ => {
let name = pick_standard_font(&f.pick_standard_font());
return load_asset(name)
.or_else(|| Some(f.pick_standard_font().get_font_data()));
}
};
if let Some(data) = load_asset(name) {
return Some(data);
}
}
let name = pick_standard_font(&f.pick_standard_font());
load_asset(name).or_else(|| Some(f.pick_standard_font().get_font_data()))
}
}),
..Default::default()
};
let render_settings = RenderSettings {
x_scale: scale,
y_scale: scale,
bg_color: WHITE,
..Default::default()
};
let cache = RenderCache::new();
for (idx, page) in pdf.pages().iter().enumerate() {
let pixmap = render(page, &cache, &interpreter_settings, &render_settings);
let output_path = format!("{}/rendered_{idx}.png", output_dir);
std::fs::write(output_path, pixmap.into_png().unwrap()).unwrap();
}
}
fn pick_standard_font(font: &StandardFont) -> &'static str {
match font {
StandardFont::Helvetica => "LiberationSans-Regular.ttf",
StandardFont::HelveticaBold => "LiberationSans-Bold.ttf",
StandardFont::HelveticaOblique => "LiberationSans-Italic.ttf",
StandardFont::HelveticaBoldOblique => "LiberationSans-BoldItalic.ttf",
StandardFont::Courier => "LiberationMono-Regular.ttf",
StandardFont::CourierBold => "LiberationMono-Bold.ttf",
StandardFont::CourierOblique => "LiberationMono-Italic.ttf",
StandardFont::CourierBoldOblique => "LiberationMono-BoldItalic.ttf",
StandardFont::TimesRoman => "LiberationSerif-Regular.ttf",
StandardFont::TimesBold => "LiberationSerif-Bold.ttf",
StandardFont::TimesItalic => "LiberationSerif-Italic.ttf",
StandardFont::TimesBoldItalic => "LiberationSerif-BoldItalic.ttf",
StandardFont::ZapfDingBats => "FoxitDingbats.pfb",
StandardFont::Symbol => "FoxitSymbol.pfb",
}
}
static LOGGER: SimpleLogger = SimpleLogger;
struct SimpleLogger;
impl log::Log for SimpleLogger {
fn enabled(&self, metadata: &log::Metadata<'_>) -> bool {
metadata.level() <= log::LevelFilter::Warn
}
fn log(&self, record: &log::Record<'_>) {
if self.enabled(record.metadata()) {
let target = if !record.target().is_empty() {
record.target()
} else {
record.module_path().unwrap_or_default()
};
let line = record.line().unwrap_or(0);
let args = record.args();
match record.level() {
log::Level::Error => eprintln!("Error (in {target}:{line}): {args}"),
log::Level::Warn => eprintln!("Warning (in {target}:{line}): {args}"),
log::Level::Info => eprintln!("Info (in {target}:{line}): {args}"),
log::Level::Debug => eprintln!("Debug (in {target}:{line}): {args}"),
log::Level::Trace => eprintln!("Trace (in {target}:{line}): {args}"),
}
}
}
fn flush(&self) {}
}