Make SVG encoding in PDF export incremental (#2290)
This commit is contained in:
parent
077218db3a
commit
9e4a96cd42
@ -1,22 +1,18 @@
|
||||
use std::collections::HashMap;
|
||||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
|
||||
use image::{DynamicImage, GenericImageView, Rgba};
|
||||
use pdf_writer::{Filter, Finish};
|
||||
use pdf_writer::{Chunk, Filter, Finish, Ref};
|
||||
|
||||
use super::{deflate, PdfContext};
|
||||
use crate::{
|
||||
geom::ColorSpace,
|
||||
image::{ImageKind, RasterFormat, RasterImage},
|
||||
};
|
||||
use crate::geom::ColorSpace;
|
||||
use crate::image::{ImageKind, RasterFormat, RasterImage, SvgImage};
|
||||
|
||||
/// Embed all used images into the PDF.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub fn write_images(ctx: &mut PdfContext) {
|
||||
for image in ctx.image_map.items() {
|
||||
let image_ref = ctx.alloc.bump();
|
||||
ctx.image_refs.push(image_ref);
|
||||
|
||||
// Add the primary image.
|
||||
match image.kind() {
|
||||
ImageKind::Raster(raster) => {
|
||||
@ -25,6 +21,9 @@ pub fn write_images(ctx: &mut PdfContext) {
|
||||
let width = image.width();
|
||||
let height = image.height();
|
||||
|
||||
let image_ref = ctx.alloc.bump();
|
||||
ctx.image_refs.push(image_ref);
|
||||
|
||||
let mut image = ctx.pdf.image_xobject(image_ref, &data);
|
||||
image.filter(filter);
|
||||
image.width(width as i32);
|
||||
@ -74,19 +73,15 @@ pub fn write_images(ctx: &mut PdfContext) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Safety: We do not keep any references to tree nodes beyond the
|
||||
// scope of `with`.
|
||||
ImageKind::Svg(svg) => unsafe {
|
||||
svg.with(|tree| {
|
||||
let next_ref = svg2pdf::convert_tree_into(
|
||||
tree,
|
||||
svg2pdf::Options::default(),
|
||||
&mut ctx.pdf,
|
||||
image_ref,
|
||||
);
|
||||
ctx.alloc = next_ref;
|
||||
|
||||
ImageKind::Svg(svg) => {
|
||||
let chunk = encode_svg(svg);
|
||||
let mut map = HashMap::new();
|
||||
chunk.renumber_into(&mut ctx.pdf, |old| {
|
||||
*map.entry(old).or_insert_with(|| ctx.alloc.bump())
|
||||
});
|
||||
},
|
||||
ctx.image_refs.push(map[&Ref::new(1)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -149,3 +144,27 @@ fn encode_alpha(raster: &RasterImage) -> (Arc<Vec<u8>>, Filter) {
|
||||
.collect();
|
||||
(Arc::new(deflate(&pixels)), Filter::FlateDecode)
|
||||
}
|
||||
|
||||
/// Encode an SVG into a chunk of PDF objects.
|
||||
///
|
||||
/// The main XObject will have ID 1.
|
||||
#[comemo::memoize]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn encode_svg(svg: &SvgImage) -> Arc<Chunk> {
|
||||
let mut chunk = Chunk::new();
|
||||
|
||||
// Safety: We do not keep any references to tree nodes beyond the
|
||||
// scope of `with`.
|
||||
unsafe {
|
||||
svg.with(|tree| {
|
||||
svg2pdf::convert_tree_into(
|
||||
tree,
|
||||
svg2pdf::Options::default(),
|
||||
&mut chunk,
|
||||
Ref::new(1),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Arc::new(chunk)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user