I would like to use the low-level pdf-writer crate in version 0.14.0 (latest) to add the liberation sans font to my PDF.
So far, I have
use pdf_writer::{Finish, Name, Pdf, Rect, Ref, Str, Obj};
use pdf_writer::types::{CidFontType, FontFlags, SystemInfo, UnicodeCmap};
use ttf_parser::{Face, GlyphId};
pub const LIBERATION_SANS_REGULAR_TTF: &[u8] =
include_bytes!("../../assets/fonts/LiberationSansRegular.ttf");
pub const LIBERATION_SANS_BOLD_TTF: &[u8] =
include_bytes!("../../assets/fonts/LiberationSansBold.ttf");
const SYSTEM_INFO: SystemInfo = SystemInfo {
registry: Str(b"Adobe"),
ordering: Str(b"Identity"),
supplement: 0,
};
pub struct EmbeddedFont {
pub type0_ref: Ref,
}
pub fn embed_ttf_font(pdf: &mut Pdf, next_id: &mut Ref, font_data: &[u8]) -> EmbeddedFont {
let face = Face::parse(font_data, 0).expect("Invalid font data");
// Allocate IDs
let type0_ref = next_id.bump();
let cid_ref = next_id.bump();
let desc_ref = next_id.bump();
let stream_ref = next_id.bump();
let cmap_ref = next_id.bump();
// Extract unicode cmap from .ttf
let mut cmap = UnicodeCmap::::new(Name(b"Custom"), SYSTEM_INFO);
for subtable in face
.tables()
.cmap
.iter()
.flat_map(|c| c.subtables) {
if subtable.is_unicode() {
subtable.codepoints(|cp| {
if let (Some(c), Some(gid)) = (char::from_u32(cp), subtable.glyph_index(cp)) {
cmap.pair(gid.0, c);
}
});
break;
}
}
pdf.stream(cmap_ref, &cmap.finish()).finish();
// Width
// PDF CIDFont widths are: [first_gid [w1 w2 w3]]
let mut widths = Vec::new();
for gid in 0..face.number_of_glyphs() {
let width = face.glyph_hor_advance(GlyphId(gid)).unwrap_or(0);
widths.push(width as f32);
}
// Here I am stuck
EmbeddedFont {
type0_ref
}
Where I am stuck now is that I have to add that to the pdf stream using something like:
pdf.font_stream(stream_ref, font_data)
.pair(Name(b"Length1"), font_data.len() as i32)
.finish();
But the API complains that neither does font_stream exist nor does the normal stream contain pair() or insert(). There seems to have been some API change which is undocumented. At the moment, I am thinking about moving to a more high-level crate, but I would love to have as few dependencies as possible.