diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-08-23 13:18:20 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-08-23 13:21:44 +0200 |
| commit | 0806af4aecc9414962b13894a2a3c4befd2ca3c8 (patch) | |
| tree | 0267109894f9cf4b74fe2663a2e29cf589d75b44 /src/export | |
| parent | c0377de653ed7c0ae0e253724cbbb622125fbd3f (diff) | |
Kerned PDF output
Diffstat (limited to 'src/export')
| -rw-r--r-- | src/export/pdf.rs | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/src/export/pdf.rs b/src/export/pdf.rs index e77ad931..7ff600ff 100644 --- a/src/export/pdf.rs +++ b/src/export/pdf.rs @@ -14,8 +14,8 @@ use pdf_writer::{ use ttf_parser::{name_id, GlyphId}; use crate::color::Color; -use crate::font::{Em, FaceId, FontStore}; -use crate::geom::{self, Length, Size}; +use crate::font::{FaceId, FontStore}; +use crate::geom::{self, Em, Length, Size}; use crate::image::{Image, ImageId, ImageStore}; use crate::layout::{Element, Frame, Geometry, Paint}; use crate::Context; @@ -140,7 +140,7 @@ impl<'a> PdfExporter<'a> { // We only write font switching actions when the used face changes. To // do that, we need to remember the active face. - let mut face = None; + let mut face_id = None; let mut size = Length::zero(); let mut fill: Option<Paint> = None; @@ -159,17 +159,50 @@ impl<'a> PdfExporter<'a> { // Then, also check if we need to issue a font switching // action. - if face != Some(shaped.face_id) || shaped.size != size { - face = Some(shaped.face_id); + if face_id != Some(shaped.face_id) || shaped.size != size { + face_id = Some(shaped.face_id); size = shaped.size; let name = format!("F{}", self.font_map.map(shaped.face_id)); text.font(Name(name.as_bytes()), size.to_pt() as f32); } - // TODO: Respect individual glyph offsets. + let face = self.fonts.get(shaped.face_id); + + // Position the text. text.matrix(1.0, 0.0, 0.0, 1.0, x, y); - text.show(Str(&shaped.encode_glyphs_be())); + + let mut positioned = text.show_positioned(); + let mut adjustment = Em::zero(); + let mut encoded = vec![]; + + // Write the glyphs with kerning adjustments. + for glyph in &shaped.glyphs { + adjustment += glyph.x_offset; + + if !adjustment.is_zero() { + if !encoded.is_empty() { + positioned.show(Str(&encoded)); + encoded.clear(); + } + + positioned.adjust(-adjustment.to_pdf()); + adjustment = Em::zero(); + } + + encoded.push((glyph.id >> 8) as u8); + encoded.push((glyph.id & 0xff) as u8); + + if let Some(advance) = face.advance(glyph.id) { + adjustment += glyph.x_advance - advance; + } + + adjustment -= glyph.x_offset; + } + + if !encoded.is_empty() { + positioned.show(Str(&encoded)); + } } Element::Geometry(ref geometry, paint) => { |
