summaryrefslogtreecommitdiff
path: root/src/export
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-09-19 12:49:36 +0200
committerLaurenz <laurmaedje@gmail.com>2022-09-19 12:49:36 +0200
commit59f67b79c7ff50f0bc9a27373d0fa36d1523e08a (patch)
tree4687eea50b231b630563dd14e5de85551f661efb /src/export
parent30be75c6687f1e03cf867d258b3ddba353cc7aa2 (diff)
Remove image store
Diffstat (limited to 'src/export')
-rw-r--r--src/export/pdf/font.rs2
-rw-r--r--src/export/pdf/image.rs46
-rw-r--r--src/export/pdf/mod.rs43
-rw-r--r--src/export/pdf/page.rs21
-rw-r--r--src/export/render.rs42
5 files changed, 77 insertions, 77 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();
diff --git a/src/export/render.rs b/src/export/render.rs
index 525d764d..688cf979 100644
--- a/src/export/render.rs
+++ b/src/export/render.rs
@@ -12,7 +12,7 @@ use crate::frame::{Element, Frame, Group, Text};
use crate::geom::{
self, Geometry, Length, Paint, PathElement, Shape, Size, Stroke, Transform,
};
-use crate::image::{Image, RasterImage, Svg};
+use crate::image::{DecodedImage, Image};
use crate::Context;
/// Export a frame into a rendered image.
@@ -49,21 +49,20 @@ fn render_frame(
let y = pos.y.to_f32();
let ts = ts.pre_translate(x, y);
- match *element {
- Element::Group(ref group) => {
+ match element {
+ Element::Group(group) => {
render_group(canvas, ts, mask, ctx, group);
}
- Element::Text(ref text) => {
+ Element::Text(text) => {
render_text(canvas, ts, mask, ctx, text);
}
- Element::Shape(ref shape) => {
+ Element::Shape(shape) => {
render_shape(canvas, ts, mask, shape);
}
- Element::Image(id, size) => {
- render_image(canvas, ts, mask, ctx.images.get(id), size);
+ Element::Image(image, size) => {
+ render_image(canvas, ts, mask, image, *size);
}
Element::Link(_, _) => {}
- Element::Pin(_) => {}
}
}
}
@@ -197,17 +196,20 @@ fn render_bitmap_glyph(
let ppem = size * ts.sy;
let font = ctx.fonts.get(text.font_id);
let raster = font.ttf().glyph_raster_image(id, ppem as u16)?;
- let img = RasterImage::parse(&raster.data).ok()?;
+ let ext = match raster.format {
+ ttf_parser::RasterImageFormat::PNG => "png",
+ };
+ let image = Image::new(raster.data.into(), ext).ok()?;
// FIXME: Vertical alignment isn't quite right for Apple Color Emoji,
// and maybe also for Noto Color Emoji. And: Is the size calculation
// correct?
let h = text.size;
- let w = (img.width() as f64 / img.height() as f64) * h;
- let dx = (raster.x as f32) / (img.width() as f32) * size;
- let dy = (raster.y as f32) / (img.height() as f32) * size;
+ let w = (image.width() as f64 / image.height() as f64) * h;
+ let dx = (raster.x as f32) / (image.width() as f32) * size;
+ let dy = (raster.y as f32) / (image.height() as f32) * size;
let ts = ts.pre_translate(dx, -size - dy);
- render_image(canvas, ts, mask, &Image::Raster(img), Size::new(w, h))
+ render_image(canvas, ts, mask, &image, Size::new(w, h))
}
/// Render an outline glyph into the canvas. This is the "normal" case.
@@ -338,33 +340,33 @@ fn render_image(
canvas: &mut sk::Pixmap,
ts: sk::Transform,
mask: Option<&sk::ClipMask>,
- img: &Image,
+ image: &Image,
size: Size,
) -> Option<()> {
let view_width = size.x.to_f32();
let view_height = size.y.to_f32();
- let aspect = (img.width() as f32) / (img.height() as f32);
+ let aspect = (image.width() as f32) / (image.height() as f32);
let scale = ts.sx.max(ts.sy);
let w = (scale * view_width.max(aspect * view_height)).ceil() as u32;
let h = ((w as f32) / aspect).ceil() as u32;
let mut pixmap = sk::Pixmap::new(w, h)?;
- match img {
- Image::Raster(img) => {
- let downscale = w < img.width();
+ match image.decode().unwrap() {
+ DecodedImage::Raster(dynamic) => {
+ let downscale = w < image.width();
let filter = if downscale {
FilterType::Lanczos3
} else {
FilterType::CatmullRom
};
- let buf = img.buf.resize(w, h, filter);
+ let buf = dynamic.resize(w, h, filter);
for ((_, _, src), dest) in buf.pixels().zip(pixmap.pixels_mut()) {
let Rgba([r, g, b, a]) = src;
*dest = sk::ColorU8::from_rgba(r, g, b, a).premultiply();
}
}
- Image::Svg(Svg(tree)) => {
+ DecodedImage::Svg(tree) => {
resvg::render(
&tree,
FitTo::Size(w, h),