diff options
| author | Martin Haug <mhaug@live.de> | 2022-05-11 15:19:03 +0200 |
|---|---|---|
| committer | Martin Haug <mhaug@live.de> | 2022-05-11 16:25:49 +0200 |
| commit | 84bd3454df487500d8a084190b4a10eac2a9f0f1 (patch) | |
| tree | c98b688cc02564a287de43d45abf3d5dad576338 /src/export | |
| parent | a247653cd0f324bf6985c963d958348e29ade334 (diff) | |
Write language and direction for PDFs
Diffstat (limited to 'src/export')
| -rw-r--r-- | src/export/pdf.rs | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/src/export/pdf.rs b/src/export/pdf.rs index 830e5bbb..7fda504e 100644 --- a/src/export/pdf.rs +++ b/src/export/pdf.rs @@ -7,8 +7,8 @@ use std::sync::Arc; use image::{DynamicImage, GenericImageView, ImageFormat, ImageResult, Rgba}; use pdf_writer::types::{ - ActionType, AnnotationType, CidFontType, ColorSpaceOperand, FontFlags, SystemInfo, - UnicodeCmap, + ActionType, AnnotationType, CidFontType, ColorSpaceOperand, Direction, FontFlags, + SystemInfo, UnicodeCmap, }; use pdf_writer::writers::ColorSpace; use pdf_writer::{Content, Filter, Finish, Name, PdfWriter, Rect, Ref, Str, TextStr}; @@ -18,10 +18,11 @@ use super::subset::subset; use crate::font::{find_name, FaceId, FontStore}; use crate::frame::{Element, Frame, Group, Text}; use crate::geom::{ - self, Color, Em, Geometry, Length, Numeric, Paint, Point, Shape, Size, Stroke, + self, Color, Dir, Em, Geometry, Length, Numeric, Paint, Point, Shape, Size, Stroke, Transform, }; use crate::image::{Image, ImageId, ImageStore, RasterImage}; +use crate::library::text::Lang; use crate::Context; /// Export a collection of frames into a PDF file. @@ -303,6 +304,7 @@ 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 page_id = self.alloc.bump(); let content_id = self.alloc.bump(); @@ -330,6 +332,13 @@ impl<'a> PdfExporter<'a> { annotations.finish(); page_writer.finish(); + for (lang, count) in page.languages { + languages + .entry(lang) + .and_modify(|x| *x += count) + .or_insert_with(|| count); + } + self.writer .stream(content_id, &deflate(&page.content.finish())) .filter(Filter::FlateDecode); @@ -359,9 +368,28 @@ impl<'a> PdfExporter<'a> { resources.finish(); pages.finish(); + let lang = languages + .into_iter() + .max_by(|(_, v1), (_, v2)| v1.cmp(v2)) + .map(|(k, _)| k); + + let dir = if lang.map(Lang::dir) == Some(Dir::RTL) { + Direction::R2L + } else { + Direction::L2R + }; + // Write the document information, catalog and wrap it up! self.writer.document_info(self.alloc.bump()).creator(TextStr("Typst")); - self.writer.catalog(self.alloc.bump()).pages(page_tree_ref); + let mut catalog = self.writer.catalog(self.alloc.bump()); + catalog.pages(page_tree_ref); + catalog.viewer_preferences().direction(dir); + + if let Some(lang) = lang { + catalog.lang(TextStr(lang.as_str())); + } + + catalog.finish(); self.writer.finish() } } @@ -372,6 +400,7 @@ struct PageExporter<'a> { font_map: &'a mut Remapper<FaceId>, image_map: &'a mut Remapper<ImageId>, glyphs: &'a mut HashMap<FaceId, HashSet<u16>>, + languages: HashMap<Lang, usize>, bottom: f32, content: Content, links: Vec<(String, Rect)>, @@ -384,6 +413,7 @@ struct Page { size: Size, content: Content, links: Vec<(String, Rect)>, + languages: HashMap<Lang, usize>, } /// A simulated graphics state used to deduplicate graphics state changes and @@ -403,6 +433,7 @@ impl<'a> PageExporter<'a> { font_map: &mut exporter.face_map, image_map: &mut exporter.image_map, glyphs: &mut exporter.glyph_sets, + languages: HashMap::new(), bottom: 0.0, content: Content::new(), links: vec![], @@ -422,6 +453,7 @@ impl<'a> PageExporter<'a> { size: frame.size, content: self.content, links: self.links, + languages: self.languages, } } @@ -508,6 +540,11 @@ impl<'a> PageExporter<'a> { items.show(Str(&encoded)); } + self.languages + .entry(text.lang) + .and_modify(|x| *x += text.glyphs.len()) + .or_insert_with(|| text.glyphs.len()); + items.finish(); positioned.finish(); self.content.end_text(); |
