summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/export/pdf/font.rs25
-rw-r--r--src/export/pdf/image.rs37
2 files changed, 35 insertions, 27 deletions
diff --git a/src/export/pdf/font.rs b/src/export/pdf/font.rs
index c6142599..d5de5118 100644
--- a/src/export/pdf/font.rs
+++ b/src/export/pdf/font.rs
@@ -7,7 +7,8 @@ use ttf_parser::{name_id, GlyphId, Tag};
use unicode_general_category::GeneralCategory;
use super::{deflate, EmExt, PdfContext, RefExt};
-use crate::util::SliceExt;
+use crate::font::Font;
+use crate::util::{Buffer, SliceExt};
const CMAP_NAME: Name = Name(b"Custom");
const SYSTEM_INFO: SystemInfo = SystemInfo {
@@ -138,16 +139,8 @@ pub fn write_fonts(ctx: &mut PdfContext) {
ctx.writer.cmap(cmap_ref, &cmap.finish());
// Subset and write the font's bytes.
- let data = font.data();
- let subsetted = {
- let glyphs: Vec<_> = glyph_set.keys().copied().collect();
- let profile = subsetter::Profile::pdf(&glyphs);
- subsetter::subset(data, font.index(), profile)
- };
-
- // Compress and write the font's bytes.
- let data = subsetted.as_deref().unwrap_or(data);
- let data = deflate(data);
+ let glyphs: Vec<_> = glyph_set.keys().copied().collect();
+ let data = subset_font(font, &glyphs);
let mut stream = ctx.writer.stream(data_ref, &data);
stream.filter(Filter::FlateDecode);
@@ -159,6 +152,16 @@ pub fn write_fonts(ctx: &mut PdfContext) {
}
}
+/// Subset a font to the given glyphs.
+#[comemo::memoize]
+fn subset_font(font: &Font, glyphs: &[u16]) -> Buffer {
+ let data = font.data();
+ let profile = subsetter::Profile::pdf(glyphs);
+ let subsetted = subsetter::subset(data, font.index(), profile);
+ let data = subsetted.as_deref().unwrap_or(data);
+ deflate(data).into()
+}
+
/// Create a /ToUnicode CMap.
fn create_cmap(
ttf: &ttf_parser::Face,
diff --git a/src/export/pdf/image.rs b/src/export/pdf/image.rs
index 7d5656ca..a7ec4744 100644
--- a/src/export/pdf/image.rs
+++ b/src/export/pdf/image.rs
@@ -1,10 +1,11 @@
use std::io::Cursor;
-use image::{DynamicImage, GenericImageView, ImageResult, Rgba};
+use image::{DynamicImage, GenericImageView, Rgba};
use pdf_writer::{Filter, Finish};
use super::{deflate, PdfContext, RefExt};
-use crate::image::{DecodedImage, RasterFormat};
+use crate::image::{DecodedImage, Image, RasterFormat};
+use crate::util::Buffer;
/// Embed all used images into the PDF.
#[tracing::instrument(skip_all)]
@@ -20,9 +21,9 @@ pub fn write_images(ctx: &mut PdfContext) {
// Add the primary image.
// TODO: Error if image could not be encoded.
match image.decoded().as_ref() {
- DecodedImage::Raster(dynamic, icc, format) => {
+ DecodedImage::Raster(dynamic, icc, _) => {
// TODO: Error if image could not be encoded.
- let (data, filter, has_color) = encode_image(*format, dynamic).unwrap();
+ let (data, filter, has_color) = encode_image(image);
let mut image = ctx.writer.image_xobject(image_ref, &data);
image.filter(filter);
image.width(width as i32);
@@ -86,24 +87,28 @@ pub fn write_images(ctx: &mut PdfContext) {
/// whether the image has color.
///
/// Skips the alpha channel as that's encoded separately.
+#[comemo::memoize]
#[tracing::instrument(skip_all)]
-fn encode_image(
- format: RasterFormat,
- dynamic: &DynamicImage,
-) -> ImageResult<(Vec<u8>, Filter, bool)> {
- Ok(match (format, dynamic) {
+fn encode_image(image: &Image) -> (Buffer, Filter, bool) {
+ let decoded = image.decoded();
+ let (dynamic, format) = match decoded.as_ref() {
+ DecodedImage::Raster(dynamic, _, format) => (dynamic, *format),
+ _ => panic!("can only encode raster image"),
+ };
+
+ match (format, dynamic) {
// 8-bit gray JPEG.
(RasterFormat::Jpg, DynamicImage::ImageLuma8(_)) => {
let mut data = Cursor::new(vec![]);
- dynamic.write_to(&mut data, image::ImageFormat::Jpeg)?;
- (data.into_inner(), Filter::DctDecode, false)
+ dynamic.write_to(&mut data, image::ImageFormat::Jpeg).unwrap();
+ (data.into_inner().into(), Filter::DctDecode, false)
}
// 8-bit RGB JPEG (CMYK JPEGs get converted to RGB earlier).
(RasterFormat::Jpg, DynamicImage::ImageRgb8(_)) => {
let mut data = Cursor::new(vec![]);
- dynamic.write_to(&mut data, image::ImageFormat::Jpeg)?;
- (data.into_inner(), Filter::DctDecode, true)
+ dynamic.write_to(&mut data, image::ImageFormat::Jpeg).unwrap();
+ (data.into_inner().into(), Filter::DctDecode, true)
}
// TODO: Encode flate streams with PNG-predictor?
@@ -111,7 +116,7 @@ fn encode_image(
// 8-bit gray PNG.
(RasterFormat::Png, DynamicImage::ImageLuma8(luma)) => {
let data = deflate(luma.as_raw());
- (data, Filter::FlateDecode, false)
+ (data.into(), Filter::FlateDecode, false)
}
// Anything else (including Rgb(a) PNGs).
@@ -125,9 +130,9 @@ fn encode_image(
}
let data = deflate(&pixels);
- (data, Filter::FlateDecode, true)
+ (data.into(), Filter::FlateDecode, true)
}
- })
+ }
}
/// Encode an image's alpha channel if present.