diff options
| author | Martin Haug <mhaug@live.de> | 2022-05-27 12:56:20 +0200 |
|---|---|---|
| committer | Martin Haug <mhaug@live.de> | 2022-05-27 12:56:20 +0200 |
| commit | 99cb655832161d4ebec73273a15453a8f6acc1b7 (patch) | |
| tree | 9eb6328dda9cef5ba4b436465cebfca5b7bec076 /src/export | |
| parent | 0170913d5413aab4c1f2bd7d56b9b7138f676012 (diff) | |
Intra-document links
Diffstat (limited to 'src/export')
| -rw-r--r-- | src/export/pdf.rs | 70 |
1 files changed, 47 insertions, 23 deletions
diff --git a/src/export/pdf.rs b/src/export/pdf.rs index 7fda504e..aeb5c47e 100644 --- a/src/export/pdf.rs +++ b/src/export/pdf.rs @@ -16,10 +16,10 @@ use ttf_parser::{name_id, GlyphId, Tag}; use super::subset::subset; use crate::font::{find_name, FaceId, FontStore}; -use crate::frame::{Element, Frame, Group, Text}; +use crate::frame::{Destination, Element, Frame, Group, Text}; use crate::geom::{ - self, Color, Dir, Em, Geometry, Length, Numeric, Paint, Point, Shape, Size, Stroke, - Transform, + self, Color, Dir, Em, Geometry, Length, Numeric, Paint, Point, Ratio, Shape, Size, + Stroke, Transform, }; use crate::image::{Image, ImageId, ImageStore, RasterImage}; use crate::library::text::Lang; @@ -304,13 +304,18 @@ impl<'a> PdfExporter<'a> { // The page objects (non-root nodes in the page tree). let mut page_refs = vec![]; - let mut languages = HashMap::new(); - for page in self.pages { + let mut page_heights = vec![]; + for page in &self.pages { let page_id = self.alloc.bump(); - let content_id = self.alloc.bump(); page_refs.push(page_id); + page_heights.push(page.size.y.to_f32()); + } + + let mut languages = HashMap::new(); + for (page, page_id) in self.pages.into_iter().zip(page_refs.iter()) { + let content_id = self.alloc.bump(); - let mut page_writer = self.writer.page(page_id); + let mut page_writer = self.writer.page(*page_id); page_writer.parent(page_tree_ref); let w = page.size.x.to_f32(); @@ -319,14 +324,25 @@ impl<'a> PdfExporter<'a> { page_writer.contents(content_id); let mut annotations = page_writer.annotations(); - for (url, rect) in page.links { - annotations - .push() - .subtype(AnnotationType::Link) - .rect(rect) - .action() - .action_type(ActionType::Uri) - .uri(Str(url.as_bytes())); + for (dest, rect) in page.links { + let mut link = annotations.push(); + link.subtype(AnnotationType::Link).rect(rect); + match dest { + Destination::Url(uri) => { + link.action() + .action_type(ActionType::Uri) + .uri(Str(uri.as_str().as_bytes())); + } + Destination::Internal(page, point) => { + let page = page - 1; + let height = page_heights[page]; + link.action() + .action_type(ActionType::GoTo) + .destination_direct() + .page(page_refs[page]) + .xyz(point.x.to_f32(), height - point.y.to_f32(), None); + } + } } annotations.finish(); @@ -403,7 +419,7 @@ struct PageExporter<'a> { languages: HashMap<Lang, usize>, bottom: f32, content: Content, - links: Vec<(String, Rect)>, + links: Vec<(Destination, Rect)>, state: State, saves: Vec<State>, } @@ -412,7 +428,7 @@ struct PageExporter<'a> { struct Page { size: Size, content: Content, - links: Vec<(String, Rect)>, + links: Vec<(Destination, Rect)>, languages: HashMap<Lang, usize>, } @@ -445,7 +461,14 @@ impl<'a> PageExporter<'a> { fn export(mut self, frame: &Frame) -> Page { // Make the coordinate system start at the top-left. self.bottom = frame.size.y.to_f32(); - self.content.transform([1.0, 0.0, 0.0, -1.0, 0.0, self.bottom]); + self.transform(Transform { + sx: Ratio::one(), + ky: Ratio::zero(), + kx: Ratio::zero(), + sy: Ratio::new(-1.0), + tx: Length::zero(), + ty: frame.size.y, + }); self.content.set_fill_color_space(ColorSpaceOperand::Named(SRGB)); self.content.set_stroke_color_space(ColorSpaceOperand::Named(SRGB)); self.write_frame(frame); @@ -466,7 +489,7 @@ impl<'a> PageExporter<'a> { Element::Text(ref text) => self.write_text(x, y, text), Element::Shape(ref shape) => self.write_shape(x, y, shape), Element::Image(id, size) => self.write_image(x, y, id, size), - Element::Link(ref url, size) => self.write_link(pos, url, size), + Element::Link(ref dest, size) => self.write_link(pos, dest, size), } } } @@ -627,7 +650,7 @@ impl<'a> PageExporter<'a> { self.content.restore_state(); } - fn write_link(&mut self, pos: Point, url: &str, size: Size) { + fn write_link(&mut self, pos: Point, dest: &Destination, size: Size) { let mut min_x = Length::inf(); let mut min_y = Length::inf(); let mut max_x = -Length::inf(); @@ -649,10 +672,11 @@ impl<'a> PageExporter<'a> { let x1 = min_x.to_f32(); let x2 = max_x.to_f32(); - let y1 = self.bottom - max_y.to_f32(); - let y2 = self.bottom - min_y.to_f32(); + let y1 = max_y.to_f32(); + let y2 = min_y.to_f32(); let rect = Rect::new(x1, y1, x2, y2); - self.links.push((url.to_string(), rect)); + + self.links.push((dest.clone(), rect)); } fn save_state(&mut self) { |
