///|
// Fonts bundled in the program, so converting needs no font files: the
// files Ruby asciidoctor-pdf ships in its gem's `data/fonts` (the
// directory its themes call `GEM_FONTS_DIR`), and prawn-icon's icon fonts.
// The default theme's fonts are here; the fonts of the other bundled
// themes and the icon fonts live in packages of their own
// (`fonts/sans`, `fonts/fallback`, `fonts/icons`), so a program links only
// the ones it registers. Generated by scripts/pdf_bundle_fonts.mbtx; see
// pdf/NOTICE for the fonts' licenses.
///|
/// A set of bundled files, by the name they have in their directory
/// (`notoserif-regular-subset.ttf`, `fas/fa-solid.ttf`). Each is decoded
/// when it is first asked for, then kept.
pub struct Bundle {
priv files : Map[String, () -> Bytes]
priv decoded : Map[String, Bytes]
}
///|
/// A bundle of files: name → a function producing the contents (called
/// once, on the first `get`).
pub fn Bundle::new(files : Array[(String, () -> Bytes)]) -> Bundle {
{ files: Map::from_array(files), decoded: Map([]), }
}
///|
/// The contents of file `name`, when the bundle has it.
pub fn Bundle::get(self : Bundle, name : String) -> Bytes? {
match self.decoded.get(name) {
Some(data) => Some(data)
None =>
match self.files.get(name) {
Some(load) => {
let data = load()
self.decoded[name] = data
Some(data)
}
None => None
}
}
}
///|
/// Whether the bundle has file `name` (without decoding it).
pub fn Bundle::contains(self : Bundle, name : String) -> Bool {
self.files.contains(name)
}
///|
/// The names of the bundle's files.
pub fn Bundle::names(self : Bundle) -> Array[String] {
self.files.keys().collect()
}
///|
/// The bytes of generated data: the chunks of zlib-compressed,
/// ASCII85-armoured text that scripts/pdf_bundle_fonts.mbtx writes,
/// restored.
pub fn inflate_armoured(chunks : Array[Bytes]) -> Bytes {
let joined = Buffer()
for chunk in chunks {
joined.write_bytes(chunk)
}
// the generator wrote valid data: failing to decode it is a bug
@flate.pdf_flate_decode(@codec.pdf_ascii85_decode(joined.contents())) catch {
_ => abort("bundled font data does not decode")
}
}
///|
/// A bundle of generated data (see `inflate_armoured`).
pub fn Bundle::from_armoured(
files : Array[(String, () -> Array[Bytes])],
) -> Bundle {
Bundle::new(
files.map(file => {
let (name, chunks) = file
(name, () => inflate_armoured(chunks()))
}),
)
}
///|
let default_bundle : Bundle = Bundle::from_armoured(bundled_files())
///|
/// asciidoctor-pdf 2.3.27's default fonts, by their names in its
/// `data/fonts`: the default theme's Noto Serif
/// (`notoserif-regular-subset.ttf`, `-bold-`, `-italic-`, `-bold_italic-`)
/// and M+ 1mn (`mplus1mn-*-subset.ttf`), and its mapping of Font Awesome 4
/// icon names (`fa-legacy-mapping.yml`).
pub fn default_fonts() -> Bundle {
default_bundle
}