From da602613769cc73aad3fbaf8aa3c83d5d0fb85dc Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 27 Feb 2019 18:42:33 +0100 Subject: [PATCH] =?UTF-8?q?Enhance=20PDF=20crate=20API=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pdf.rs | 133 +++++++++++++++++++++-------------------------------- 1 file changed, 53 insertions(+), 80 deletions(-) diff --git a/src/pdf.rs b/src/pdf.rs index d18d6fc42..7cc8e6da6 100644 --- a/src/pdf.rs +++ b/src/pdf.rs @@ -4,10 +4,12 @@ use std::fmt; use std::io::{self, Write, Cursor}; use crate::doc::Document; use pdf::{PdfWriter, Id, Rect, Version, Trailer}; -use pdf::doc::{DocumentCatalog, PageTree, Page, PageData, Resource, Content}; +use pdf::doc::{Catalog, PageTree, Page, Resource, Content}; use pdf::text::Text; -use pdf::font::{Type0Font, CMapEncoding, CIDFont, CIDFontType, CIDSystemInfo, - WidthRecord, FontDescriptor, EmbeddedFont, GlyphUnit}; +use pdf::font::{ + Type0Font, CMapEncoding, CIDFont, CIDFontType, CIDSystemInfo, + WidthRecord, FontDescriptor, FontFlags, EmbeddedFont, GlyphUnit +}; use opentype::{OpenTypeReader, tables}; @@ -52,18 +54,6 @@ impl fmt::Display for PdfWritingError { } -/// Shortcut macro to create bitflags from bools. -macro_rules! flags { - ($($bit:expr => $value:expr),*) => {{ - let mut flags = 0; - $( - flags |= if $value { 1 << ($bit - 1) } else { 0 }; - )* - flags - }}; - ($($bit:expr => $value:expr,)*) => (flags!($($bit => $value),*)); -} - /// Keeps track of the document while letting the pdf writer /// generate the _PDF_. struct PdfCreator<'a, W: Write> { @@ -140,9 +130,7 @@ impl<'a, W: Write> PdfCreator<'a, W> { self.writer.write_xref_table()?; // Trailer - self.writer.write_trailer(&Trailer { - root: self.offsets.catalog, - })?; + self.writer.write_trailer(&Trailer::new(self.offsets.catalog))?; Ok(self.writer.written()) } @@ -150,19 +138,13 @@ impl<'a, W: Write> PdfCreator<'a, W> { /// Write the document catalog, page tree and pages. fn write_pages(&mut self) -> PdfResult<()> { // The document catalog - self.writer.write_obj(self.offsets.catalog, &DocumentCatalog { - page_tree: self.offsets.page_tree, - })?; + self.writer.write_obj(self.offsets.catalog, &Catalog::new(self.offsets.page_tree))?; // Root page tree - self.writer.write_obj(self.offsets.page_tree, &PageTree { - parent: None, - kids: (self.offsets.pages.0 ..= self.offsets.pages.1).collect(), - data: PageData { - resources: Some(vec![Resource::Font { nr: 1, id: self.offsets.fonts.0 }]), - .. PageData::none() - }, - })?; + self.writer.write_obj(self.offsets.page_tree, PageTree::new() + .kids(self.offsets.pages.0 ..= self.offsets.pages.1) + .resource(Resource::Font { nr: 1, id: self.offsets.fonts.0 }) + )?; // The page objects let mut id = self.offsets.pages.0; @@ -170,15 +152,10 @@ impl<'a, W: Write> PdfCreator<'a, W> { let width = page.size[0].to_points(); let height = page.size[1].to_points(); - let contents = (self.offsets.contents.0 ..= self.offsets.contents.1).collect(); - self.writer.write_obj(id, &Page { - parent: self.offsets.page_tree, - data: PageData { - media_box: Some(Rect::new(0.0, 0.0, width, height)), - contents: Some(contents), - .. PageData::none() - }, - })?; + self.writer.write_obj(id, Page::new(self.offsets.page_tree) + .media_box(Rect::new(0.0, 0.0, width, height)) + .contents(self.offsets.contents.0 ..= self.offsets.contents.1) + )?; id += 1; } @@ -216,54 +193,50 @@ impl<'a, W: Write> PdfCreator<'a, W> { let base_font = font_data.name.post_script_name.as_ref() .unwrap_or(&self.doc.font); - self.writer.write_obj(id, &Type0Font { - base_font: base_font.clone(), - encoding: CMapEncoding::Predefined("Identity-H".to_owned()), - descendant_font: id + 1, - to_unicode: None, - }).unwrap(); + self.writer.write_obj(id, &Type0Font::new( + base_font.clone(), + CMapEncoding::Predefined("Identity-H".to_owned()), + id + 1 + )).unwrap(); - self.writer.write_obj(id + 1, &CIDFont { - subtype: CIDFontType::Type2, - base_font: base_font.clone(), - cid_system_info: CIDSystemInfo { - registry: "(Adobe)".to_owned(), - ordering: "(Identity)".to_owned(), - supplement: 0, - }, - font_descriptor: id + 2, - widths: Some(vec![WidthRecord::Start(0, - font_data.hmtx.metrics.iter() - .map(|m| convert(m.advance_width)) - .collect::>() - )]), - cid_to_gid_map: Some(CMapEncoding::Predefined("Identity".to_owned())), - }).unwrap(); + self.writer.write_obj(id + 1, + CIDFont::new( + CIDFontType::Type2, + base_font.clone(), + CIDSystemInfo::new("(Adobe)", "(Identity)", 0), + id + 2, + ).widths(vec![ + WidthRecord::start(0, font_data.hmtx.metrics.iter().map(|m| convert(m.advance_width)) + )]) + ).unwrap(); - self.writer.write_obj(id + 2, &FontDescriptor { - font_name: base_font.clone(), - flags: flags!( - 1 => font_data.post.is_fixed_pitch, - 2 => base_font.contains("Serif"), - 3 => true, 4 => false, 6 => false, - 7 => (font_data.head.mac_style & 1) != 0, - 17 => false, 18 => true, 19 => false, - ), - found_bbox: Rect::new( + let mut flags = FontFlags::empty(); + flags.set(FontFlags::FIXED_PITCH, font_data.post.is_fixed_pitch); + flags.set(FontFlags::SERIF, base_font.contains("Serif")); + flags.insert(FontFlags::SYMBOLIC); + flags.set(FontFlags::ITALIC, (font_data.head.mac_style & 1) != 0); + flags.insert(FontFlags::SMALL_CAP); + + self.writer.write_obj(id + 2, + FontDescriptor::new( + base_font.clone(), + flags, + font_data.post.italic_angle.to_f32(), + ) + .font_bbox(Rect::new( convert(font_data.head.x_min), convert(font_data.head.y_min), convert(font_data.head.x_max), convert(font_data.head.y_max) - ), - italic_angle: font_data.post.italic_angle.to_f32(), - ascent: convert(font_data.os2.s_typo_ascender), - descent: convert(font_data.os2.s_typo_descender), - cap_height: convert(font_data.os2.s_cap_height - .unwrap_or(font_data.os2.s_typo_ascender)), - stem_v: (10.0 + 220.0 * - (font_data.os2.us_weight_class as f32 - 50.0) / 900.0) as GlyphUnit, - font_file_3: Some(id + 3), - }).unwrap(); + )) + .ascent(convert(font_data.os2.s_typo_ascender)) + .descent(convert(font_data.os2.s_typo_descender)) + .cap_height(convert(font_data.os2.s_cap_height + .unwrap_or(font_data.os2.s_typo_ascender))) + .stem_v((10.0 + 220.0 * (font_data.os2.us_weight_class as f32 + - 50.0) / 900.0) as GlyphUnit) + .font_file_3(id + 3) + ).unwrap(); self.writer.write_obj(id + 3, &EmbeddedFont::OpenType(&font_data.data)).unwrap();