use lightweight_pdf_core::FontKey;
use lightweight_pdf_fonts::{EmbeddedFontMetrics, FontData, FontError};
use lightweight_pdf_layout::{FontMetrics, FontResolver};
#[cfg(feature = "default-fonts")]
const SANS_REGULAR_BYTES: &[u8] = include_bytes!("../assets/fonts/SourceSans3-Regular.ttf");
#[cfg(feature = "default-fonts")]
const SANS_BOLD_BYTES: &[u8] = include_bytes!("../assets/fonts/SourceSans3-Bold.ttf");
struct MetricsAdapter(pub(crate) EmbeddedFontMetrics);
impl FontMetrics for MetricsAdapter {
fn advance(&self, ch: char) -> f32 {
self.0.advance_1000(ch).unwrap_or(500.0)
}
fn ascent(&self) -> f32 {
self.0.ascent
}
fn descent(&self) -> f32 {
self.0.descent
}
}
pub struct FontEntry {
pub data: FontData,
pub base_font_name: &'static str,
adapter: MetricsAdapter,
}
impl FontEntry {
fn new(bytes: &[u8], base_font_name: &'static str) -> Result<Self, FontError> {
let data = FontData::load(bytes.to_vec())?;
let metrics = EmbeddedFontMetrics::from_font_data(&data)?;
Ok(FontEntry {
data,
base_font_name,
adapter: MetricsAdapter(metrics),
})
}
pub fn metrics(&self) -> &EmbeddedFontMetrics {
&self.adapter.0
}
}
pub struct FontRegistry {
pub regular: FontEntry,
pub bold: FontEntry,
}
impl FontRegistry {
#[cfg(feature = "default-fonts")]
pub fn with_defaults() -> Result<Self, FontError> {
Ok(FontRegistry {
regular: FontEntry::new(SANS_REGULAR_BYTES, "SourceSans3-Subset")?,
bold: FontEntry::new(SANS_BOLD_BYTES, "SourceSans3-Bold-Subset")?,
})
}
pub fn with_fonts(regular_bytes: &[u8], bold_bytes: &[u8]) -> Result<Self, FontError> {
Ok(FontRegistry {
regular: FontEntry::new(regular_bytes, "CustomFont-Regular-Subset")?,
bold: FontEntry::new(bold_bytes, "CustomFont-Bold-Subset")?,
})
}
pub fn font_entries(&self) -> [(FontKey, &FontEntry); 2] {
[(FontKey::SANS_REGULAR, &self.regular), (FontKey::SANS_BOLD, &self.bold)]
}
pub fn entry(&self, key: FontKey) -> &FontEntry {
if key == FontKey::SANS_BOLD {
&self.bold
} else {
&self.regular
}
}
}
impl FontResolver for FontRegistry {
fn metrics(&self, key: FontKey) -> &dyn FontMetrics {
&self.entry(key).adapter
}
}