diff options
Diffstat (limited to 'src/export/pdf')
| -rw-r--r-- | src/export/pdf/font.rs | 2 | ||||
| -rw-r--r-- | src/export/pdf/image.rs | 46 | ||||
| -rw-r--r-- | src/export/pdf/mod.rs | 43 | ||||
| -rw-r--r-- | src/export/pdf/page.rs | 21 |
4 files changed, 55 insertions, 57 deletions
diff --git a/src/export/pdf/font.rs b/src/export/pdf/font.rs index 99268f9c..b3481c43 100644 --- a/src/export/pdf/font.rs +++ b/src/export/pdf/font.rs @@ -9,7 +9,7 @@ use crate::util::SliceExt; /// Embed all used fonts into the PDF. pub fn write_fonts(ctx: &mut PdfContext) { - for font_id in ctx.font_map.layout_indices() { + for &font_id in ctx.font_map.items() { let type0_ref = ctx.alloc.bump(); let cid_ref = ctx.alloc.bump(); let descriptor_ref = ctx.alloc.bump(); diff --git a/src/export/pdf/image.rs b/src/export/pdf/image.rs index 90ab228f..7886524c 100644 --- a/src/export/pdf/image.rs +++ b/src/export/pdf/image.rs @@ -1,25 +1,26 @@ use std::io::Cursor; -use image::{DynamicImage, GenericImageView, ImageFormat, ImageResult, Rgba}; +use image::{DynamicImage, GenericImageView, ImageResult, Rgba}; use pdf_writer::{Filter, Finish}; use super::{deflate, PdfContext, RefExt}; -use crate::image::{Image, RasterImage}; +use crate::image::{DecodedImage, ImageFormat}; /// Embed all used images into the PDF. pub fn write_images(ctx: &mut PdfContext) { - for image_id in ctx.image_map.layout_indices() { + for image in ctx.image_map.items() { let image_ref = ctx.alloc.bump(); ctx.image_refs.push(image_ref); - let img = ctx.images.get(image_id); - let width = img.width(); - let height = img.height(); + let width = image.width(); + let height = image.height(); // Add the primary image. - match img { - Image::Raster(img) => { - if let Ok((data, filter, has_color)) = encode_image(img) { + match image.decode().unwrap() { + DecodedImage::Raster(dynamic) => { + if let Ok((data, filter, has_color)) = + encode_image(image.format(), &dynamic) + { let mut image = ctx.writer.image_xobject(image_ref, &data); image.filter(filter); image.width(width as i32); @@ -35,8 +36,8 @@ pub fn write_images(ctx: &mut PdfContext) { // Add a second gray-scale image containing the alpha values if // this image has an alpha channel. - if img.buf.color().has_alpha() { - let (alpha_data, alpha_filter) = encode_alpha(img); + if dynamic.color().has_alpha() { + let (alpha_data, alpha_filter) = encode_alpha(&dynamic); let mask_ref = ctx.alloc.bump(); image.s_mask(mask_ref); image.finish(); @@ -59,9 +60,9 @@ pub fn write_images(ctx: &mut PdfContext) { .device_gray(); } } - Image::Svg(img) => { + DecodedImage::Svg(svg) => { let next_ref = svg2pdf::convert_tree_into( - &img.0, + &svg, svg2pdf::Options::default(), &mut ctx.writer, image_ref, @@ -76,19 +77,22 @@ pub fn write_images(ctx: &mut PdfContext) { /// whether the image has color. /// /// Skips the alpha channel as that's encoded separately. -fn encode_image(img: &RasterImage) -> ImageResult<(Vec<u8>, Filter, bool)> { - Ok(match (img.format, &img.buf) { +fn encode_image( + format: ImageFormat, + dynamic: &DynamicImage, +) -> ImageResult<(Vec<u8>, Filter, bool)> { + Ok(match (format, dynamic) { // 8-bit gray JPEG. - (ImageFormat::Jpeg, DynamicImage::ImageLuma8(_)) => { + (ImageFormat::Jpg, DynamicImage::ImageLuma8(_)) => { let mut data = Cursor::new(vec![]); - img.buf.write_to(&mut data, img.format)?; + dynamic.write_to(&mut data, image::ImageFormat::Jpeg)?; (data.into_inner(), Filter::DctDecode, false) } // 8-bit RGB JPEG (CMYK JPEGs get converted to RGB earlier). - (ImageFormat::Jpeg, DynamicImage::ImageRgb8(_)) => { + (ImageFormat::Jpg, DynamicImage::ImageRgb8(_)) => { let mut data = Cursor::new(vec![]); - img.buf.write_to(&mut data, img.format)?; + dynamic.write_to(&mut data, image::ImageFormat::Jpeg)?; (data.into_inner(), Filter::DctDecode, true) } @@ -117,7 +121,7 @@ fn encode_image(img: &RasterImage) -> ImageResult<(Vec<u8>, Filter, bool)> { } /// Encode an image's alpha channel if present. -fn encode_alpha(img: &RasterImage) -> (Vec<u8>, Filter) { - let pixels: Vec<_> = img.buf.pixels().map(|(_, _, Rgba([_, _, _, a]))| a).collect(); +fn encode_alpha(dynamic: &DynamicImage) -> (Vec<u8>, Filter) { + let pixels: Vec<_> = dynamic.pixels().map(|(_, _, Rgba([_, _, _, a]))| a).collect(); (deflate(&pixels), Filter::FlateDecode) } diff --git a/src/export/pdf/mod.rs b/src/export/pdf/mod.rs index 9ab3df24..7468f7d7 100644 --- a/src/export/pdf/mod.rs +++ b/src/export/pdf/mod.rs @@ -17,7 +17,7 @@ use self::page::Page; use crate::font::{FontId, FontStore}; use crate::frame::Frame; use crate::geom::{Dir, Em, Length}; -use crate::image::{ImageId, ImageStore}; +use crate::image::Image; use crate::library::text::Lang; use crate::Context; @@ -46,7 +46,6 @@ const D65_GRAY: Name<'static> = Name(b"d65gray"); pub struct PdfContext<'a> { writer: PdfWriter, fonts: &'a FontStore, - images: &'a ImageStore, pages: Vec<Page>, page_heights: Vec<f32>, alloc: Ref, @@ -55,7 +54,7 @@ pub struct PdfContext<'a> { image_refs: Vec<Ref>, page_refs: Vec<Ref>, font_map: Remapper<FontId>, - image_map: Remapper<ImageId>, + image_map: Remapper<Image>, glyph_sets: HashMap<FontId, HashSet<u16>>, languages: HashMap<Lang, usize>, heading_tree: Vec<HeadingNode>, @@ -68,7 +67,6 @@ impl<'a> PdfContext<'a> { Self { writer: PdfWriter::new(), fonts: &ctx.fonts, - images: &ctx.images, pages: vec![], page_heights: vec![], alloc, @@ -147,36 +145,33 @@ fn deflate(data: &[u8]) -> Vec<u8> { miniz_oxide::deflate::compress_to_vec_zlib(data, COMPRESSION_LEVEL) } -/// Assigns new, consecutive PDF-internal indices to things. -struct Remapper<Index> { - /// Forwards from the old indices to the new pdf indices. - to_pdf: HashMap<Index, usize>, - /// Backwards from the pdf indices to the old indices. - to_layout: Vec<Index>, +/// Assigns new, consecutive PDF-internal indices to items. +struct Remapper<T> { + /// Forwards from the items to the pdf indices. + to_pdf: HashMap<T, usize>, + /// Backwards from the pdf indices to the items. + to_items: Vec<T>, } -impl<Index> Remapper<Index> +impl<T> Remapper<T> where - Index: Copy + Eq + Hash, + T: Eq + Hash + Clone, { fn new() -> Self { - Self { - to_pdf: HashMap::new(), - to_layout: vec![], - } + Self { to_pdf: HashMap::new(), to_items: vec![] } } - fn insert(&mut self, index: Index) { - let to_layout = &mut self.to_layout; - self.to_pdf.entry(index).or_insert_with(|| { + fn insert(&mut self, item: T) { + let to_layout = &mut self.to_items; + self.to_pdf.entry(item.clone()).or_insert_with(|| { let pdf_index = to_layout.len(); - to_layout.push(index); + to_layout.push(item); pdf_index }); } - fn map(&self, index: Index) -> usize { - self.to_pdf[&index] + fn map(&self, item: T) -> usize { + self.to_pdf[&item] } fn pdf_indices<'a>( @@ -186,8 +181,8 @@ where refs.iter().copied().zip(0 .. self.to_pdf.len()) } - fn layout_indices(&self) -> impl Iterator<Item = Index> + '_ { - self.to_layout.iter().copied() + fn items(&self) -> impl Iterator<Item = &T> + '_ { + self.to_items.iter() } } diff --git a/src/export/pdf/page.rs b/src/export/pdf/page.rs index e5739a82..6df7531b 100644 --- a/src/export/pdf/page.rs +++ b/src/export/pdf/page.rs @@ -11,7 +11,7 @@ use crate::geom::{ self, Color, Em, Geometry, Length, Numeric, Paint, Point, Ratio, Shape, Size, Stroke, Transform, }; -use crate::image::ImageId; +use crate::image::Image; /// Construct page objects. pub fn construct_pages(ctx: &mut PdfContext, frames: &[Frame]) { @@ -290,13 +290,12 @@ fn write_frame(ctx: &mut PageContext, frame: &Frame) { for &(pos, ref element) in frame.elements() { let x = pos.x.to_f32(); let y = pos.y.to_f32(); - match *element { - Element::Group(ref group) => write_group(ctx, pos, group), - Element::Text(ref text) => write_text(ctx, x, y, text), - Element::Shape(ref shape) => write_shape(ctx, x, y, shape), - Element::Image(id, size) => write_image(ctx, x, y, id, size), - Element::Link(ref dest, size) => write_link(ctx, pos, dest, size), - Element::Pin(_) => {} + match element { + Element::Group(group) => write_group(ctx, pos, group), + Element::Text(text) => write_text(ctx, x, y, text), + Element::Shape(shape) => write_shape(ctx, x, y, shape), + Element::Image(image, size) => write_image(ctx, x, y, image, *size), + Element::Link(dest, size) => write_link(ctx, pos, dest, *size), } } } @@ -449,9 +448,9 @@ fn write_path(ctx: &mut PageContext, x: f32, y: f32, path: &geom::Path) { } /// Encode a vector or raster image into the content stream. -fn write_image(ctx: &mut PageContext, x: f32, y: f32, id: ImageId, size: Size) { - ctx.parent.image_map.insert(id); - let name = format_eco!("Im{}", ctx.parent.image_map.map(id)); +fn write_image(ctx: &mut PageContext, x: f32, y: f32, image: &Image, size: Size) { + ctx.parent.image_map.insert(image.clone()); + let name = format_eco!("Im{}", ctx.parent.image_map.map(image.clone())); let w = size.x.to_f32(); let h = size.y.to_f32(); ctx.content.save_state(); |
