Move to top-left default positioning 📐

This commit is contained in:
Laurenz Mädje 2019-06-02 18:58:37 +02:00
parent 221934df4b
commit 3e9f42661e
5 changed files with 39 additions and 33 deletions

View File

@ -27,6 +27,8 @@ pub struct Page {
/// A text layouting action.
#[derive(Debug, Clone)]
pub enum TextAction {
/// Move to an absolute position.
MoveAbsolute(Position),
/// Move from the _start_ of the current line by an (x, y) offset.
MoveNewline(Position),
/// Write text starting at the current position.

View File

@ -8,9 +8,9 @@ use pdf::doc::{Catalog, PageTree, Page, Resource, Text};
use pdf::font::{Type0Font, CIDFont, CIDFontType, CIDSystemInfo, FontDescriptor, FontFlags};
use pdf::font::{GlyphUnit, CMap, CMapEncoding, WidthRecord, FontStream};
use crate::doc::{Document, TextAction};
use crate::doc::{Document, Page as DocPage, TextAction};
use crate::font::{Font, FontError};
use crate::layout::Size;
use crate::layout::{Size, Position};
/// Exports documents into _PDFs_.
@ -96,8 +96,8 @@ impl<'d, W: Write> PdfEngine<'d, W> {
/// Write the complete document.
fn write(&mut self) -> PdfResult<usize> {
self.writer.write_header(&Version::new(1, 7))?;
self.write_page_tree()?;
self.write_pages()?;
self.write_contents()?;
self.write_fonts()?;
self.writer.write_xref_table()?;
self.writer.write_trailer(&Trailer::new(self.offsets.catalog))?;
@ -105,13 +105,14 @@ impl<'d, W: Write> PdfEngine<'d, W> {
}
/// Write the document catalog and page tree.
fn write_pages(&mut self) -> PdfResult<()> {
fn write_page_tree(&mut self) -> PdfResult<()> {
// The document catalog
self.writer.write_obj(self.offsets.catalog, &Catalog::new(self.offsets.page_tree))?;
// The font resources
let offset = self.offsets.fonts.0;
let fonts = (0 .. self.fonts.len())
.map(|i| Resource::Font((i + 1) as u32, self.offsets.fonts.0 + 5 * i as u32));
.map(|i| Resource::Font((i + 1) as u32, offset + 5 * i as u32));
// The root page tree
self.writer.write_obj(self.offsets.page_tree, PageTree::new()
@ -131,21 +132,28 @@ impl<'d, W: Write> PdfEngine<'d, W> {
}
/// Write the contents of all pages.
fn write_contents(&mut self) -> PdfResult<()> {
fn write_pages(&mut self) -> PdfResult<()> {
for (id, page) in ids(self.offsets.contents).zip(&self.doc.pages) {
self.write_text_actions(id, &page.actions)?;
self.write_page(id, &page)?;
}
Ok(())
}
/// Write a series of text actions.
fn write_text_actions(&mut self, id: u32, actions: &[TextAction]) -> PdfResult<()> {
/// Write the content of a page.
fn write_page(&mut self, id: u32, page: &DocPage) -> PdfResult<()> {
let mut font = 0;
let mut text = Text::new();
for action in actions {
text.tm(1.0, 0.0, 0.0, 1.0, 0.0, page.height.to_points());
for action in &page.actions {
match action {
TextAction::MoveNewline(x, y) => { text.td(x.to_points(), y.to_points()); },
TextAction::MoveAbsolute(pos) => {
let x = pos.x.to_points();
let y = (page.height - pos.y).to_points();
text.tm(1.0, 0.0, 0.0, 1.0, x, y);
},
TextAction::MoveNewline(pos) => { text.td(pos.x.to_points(), -pos.y.to_points()); },
TextAction::WriteText(string) => { text.tj(self.fonts[font].encode(&string)); },
TextAction::SetFont(id, size) => {
font = *id;

View File

@ -22,7 +22,7 @@ impl<'a, 'p> BoxLayouter<'a, 'p> {
/// Add a sublayout.
pub fn add_layout_absolute(&mut self, position: Position, layout: Layout) {
self.actions.push(TextAction::MoveNewline(position));
self.actions.push(TextAction::MoveAbsolute(position));
self.actions.extend(layout.actions);
}
}

View File

@ -15,6 +15,12 @@ pub struct Position {
pub y: Size,
}
impl Position {
/// Create a zeroed position.
#[inline]
pub fn zero() -> Position { Position { x: Size::zero(), y: Size::zero() } }
}
/// Size of a box in 2-dimensional space.
#[derive(Debug, Copy, Clone, PartialEq, Default)]
pub struct Extent {

View File

@ -145,8 +145,9 @@ impl<'a, 'p> TextFinisher<'a, 'p> {
let mut units = Vec::new();
mem::swap(&mut self.layouter.units, &mut units);
// Move to the top-left corner of the layout space.
self.move_start();
// Move from the origin one line below because the y-component of the origin is the
// baseline.
self.move_newline(1.0);
for unit in units {
match unit {
@ -206,29 +207,18 @@ impl<'a, 'p> TextFinisher<'a, 'p> {
}
}
/// Move to the top-left corner of the layout space.
fn move_start(&mut self) {
self.actions.push(TextAction::MoveNewline(Position {
x: Size::zero(),
y: self.layouter.ctx.max_extent.height
- Size::from_points(self.layouter.ctx.text_style.font_size)
}));
}
/// Move to the next line. A factor of 1.0 uses the default line spacing.
fn move_newline(&mut self, factor: f32) {
if self.active_font != std::usize::MAX {
let vertical = Size::from_points(self.layouter.ctx.text_style.font_size)
* self.layouter.ctx.text_style.line_spacing
* factor;
let vertical = Size::from_points(self.layouter.ctx.text_style.font_size)
* self.layouter.ctx.text_style.line_spacing
* factor;
self.actions.push(TextAction::MoveNewline(Position {
x: Size::zero(),
y: -vertical
}));
self.actions.push(TextAction::MoveNewline(Position {
x: Size::zero(),
y: vertical
}));
self.current_width = Size::zero();
}
self.current_width = Size::zero();
}
/// Output a text action containing the buffered text and reset the buffer.