Bump pdf-writer

This commit is contained in:
Laurenz 2021-12-04 21:55:23 +01:00
parent d971ac9a8c
commit 2982020480
2 changed files with 36 additions and 34 deletions

View File

@ -23,7 +23,7 @@ fxhash = "0.2.1"
image = { version = "0.23", default-features = false, features = ["png", "jpeg"] }
itertools = "0.10"
miniz_oxide = "0.4"
pdf-writer = { git = "https://github.com/typst/pdf-writer", rev = "27b207a" }
pdf-writer = "0.4"
rustybuzz = "0.4"
serde = { version = "1", features = ["derive", "rc"] }
ttf-parser = "0.12"

View File

@ -7,11 +7,9 @@ use std::rc::Rc;
use image::{DynamicImage, GenericImageView, ImageFormat, ImageResult, Rgba};
use pdf_writer::types::{
ActionType, AnnotationType, CidFontType, ColorSpace, FontFlags, SystemInfo,
};
use pdf_writer::{
Content, Filter, Finish, Name, PdfWriter, Rect, Ref, Str, TextStr, UnicodeCmap,
ActionType, AnnotationType, CidFontType, FontFlags, SystemInfo, UnicodeCmap,
};
use pdf_writer::{Content, Filter, Finish, Name, PdfWriter, Rect, Ref, Str, TextStr};
use ttf_parser::{name_id, GlyphId, Tag};
use super::subset;
@ -121,13 +119,14 @@ impl<'a> PdfExporter<'a> {
// Write the CID font referencing the font descriptor.
self.writer
.cid_font(cid_ref, subtype)
.cid_font(cid_ref)
.subtype(subtype)
.base_font(base_font)
.system_info(system_info)
.font_descriptor(descriptor_ref)
.cid_to_gid_map_predefined(Name(b"Identity"))
.widths()
.individual(0, {
.consecutive(0, {
let num_glyphs = ttf.number_of_glyphs();
(0 .. num_glyphs).map(|g| {
let x = ttf.glyph_hor_advance(GlyphId(g)).unwrap_or(0);
@ -159,9 +158,9 @@ impl<'a> PdfExporter<'a> {
// Write the font descriptor (contains metrics about the font).
self.writer
.font_descriptor(descriptor_ref)
.font_name(base_font)
.font_flags(flags)
.font_bbox(bbox)
.name(base_font)
.flags(flags)
.bbox(bbox)
.italic_angle(italic_angle)
.ascent(ascender)
.descent(descender)
@ -219,14 +218,20 @@ impl<'a> PdfExporter<'a> {
let height = img.height();
// Add the primary image.
if let Ok((data, filter, color_space)) = encode_image(img) {
let mut image = self.writer.image(image_ref, &data);
if let Ok((data, filter, has_color)) = encode_image(img) {
let mut image = self.writer.image_xobject(image_ref, &data);
image.filter(filter);
image.width(width as i32);
image.height(height as i32);
image.color_space(color_space);
image.bits_per_component(8);
let space = image.color_space();
if has_color {
space.device_rgb();
} else {
space.device_gray();
}
// Add a second gray-scale image containing the alpha values if
// this image has an alpha channel.
if img.buf.color().has_alpha() {
@ -235,21 +240,22 @@ impl<'a> PdfExporter<'a> {
image.s_mask(mask_ref);
image.finish();
let mut mask = self.writer.image(mask_ref, &alpha_data);
let mut mask = self.writer.image_xobject(mask_ref, &alpha_data);
mask.filter(alpha_filter);
mask.width(width as i32);
mask.height(height as i32);
mask.color_space(ColorSpace::DeviceGray);
mask.color_space().device_gray();
mask.bits_per_component(8);
}
} else {
// TODO: Warn that image could not be encoded.
self.writer
.image(image_ref, &[])
.image_xobject(image_ref, &[])
.width(0)
.height(0)
.color_space(ColorSpace::DeviceGray)
.bits_per_component(1);
.bits_per_component(1)
.color_space()
.device_gray();
}
}
}
@ -293,7 +299,7 @@ impl<'a> PdfExporter<'a> {
}
let mut pages = self.writer.pages(page_tree_ref);
pages.kids(page_refs);
pages.count(page_refs.len() as i32).kids(page_refs);
let mut resources = pages.resources();
let mut fonts = resources.fonts();
@ -314,15 +320,10 @@ impl<'a> PdfExporter<'a> {
resources.finish();
pages.finish();
// The document information.
let mut doc_info = self.writer.document_info(self.alloc.bump());
doc_info.creator(TextStr("Typst"));
doc_info.finish();
// The document catalog.
let catalog_ref = self.alloc.bump();
self.writer.catalog(catalog_ref).pages(page_tree_ref);
self.writer.finish(catalog_ref)
// Write the document information, catalog and wrap it up!
self.writer.document_info(self.alloc.bump()).creator(TextStr("Typst"));
self.writer.catalog(self.alloc.bump()).pages(page_tree_ref);
self.writer.finish()
}
}
@ -631,23 +632,24 @@ impl<'a> PageExporter<'a> {
}
}
/// Encode an image with a suitable filter.
/// Encode an image with a suitable filter and return the data, filter and
/// whether the image has color.
///
/// Skips the alpha channel as that's encoded separately.
fn encode_image(img: &Image) -> ImageResult<(Vec<u8>, Filter, ColorSpace)> {
fn encode_image(img: &Image) -> ImageResult<(Vec<u8>, Filter, bool)> {
Ok(match (img.format, &img.buf) {
// 8-bit gray JPEG.
(ImageFormat::Jpeg, DynamicImage::ImageLuma8(_)) => {
let mut data = vec![];
img.buf.write_to(&mut data, img.format)?;
(data, Filter::DctDecode, ColorSpace::DeviceGray)
(data, Filter::DctDecode, false)
}
// 8-bit Rgb JPEG (Cmyk JPEGs get converted to Rgb earlier).
(ImageFormat::Jpeg, DynamicImage::ImageRgb8(_)) => {
let mut data = vec![];
img.buf.write_to(&mut data, img.format)?;
(data, Filter::DctDecode, ColorSpace::DeviceRgb)
(data, Filter::DctDecode, true)
}
// TODO: Encode flate streams with PNG-predictor?
@ -655,7 +657,7 @@ fn encode_image(img: &Image) -> ImageResult<(Vec<u8>, Filter, ColorSpace)> {
// 8-bit gray PNG.
(ImageFormat::Png, DynamicImage::ImageLuma8(luma)) => {
let data = deflate(luma.as_raw());
(data, Filter::FlateDecode, ColorSpace::DeviceGray)
(data, Filter::FlateDecode, false)
}
// Anything else (including Rgb(a) PNGs).
@ -669,7 +671,7 @@ fn encode_image(img: &Image) -> ImageResult<(Vec<u8>, Filter, ColorSpace)> {
}
let data = deflate(&pixels);
(data, Filter::FlateDecode, ColorSpace::DeviceRgb)
(data, Filter::FlateDecode, true)
}
})
}