mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Move to top-left default positioning 📐
This commit is contained in:
parent
221934df4b
commit
3e9f42661e
@ -27,6 +27,8 @@ pub struct Page {
|
|||||||
/// A text layouting action.
|
/// A text layouting action.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TextAction {
|
pub enum TextAction {
|
||||||
|
/// Move to an absolute position.
|
||||||
|
MoveAbsolute(Position),
|
||||||
/// Move from the _start_ of the current line by an (x, y) offset.
|
/// Move from the _start_ of the current line by an (x, y) offset.
|
||||||
MoveNewline(Position),
|
MoveNewline(Position),
|
||||||
/// Write text starting at the current position.
|
/// Write text starting at the current position.
|
||||||
|
@ -8,9 +8,9 @@ use pdf::doc::{Catalog, PageTree, Page, Resource, Text};
|
|||||||
use pdf::font::{Type0Font, CIDFont, CIDFontType, CIDSystemInfo, FontDescriptor, FontFlags};
|
use pdf::font::{Type0Font, CIDFont, CIDFontType, CIDSystemInfo, FontDescriptor, FontFlags};
|
||||||
use pdf::font::{GlyphUnit, CMap, CMapEncoding, WidthRecord, FontStream};
|
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::font::{Font, FontError};
|
||||||
use crate::layout::Size;
|
use crate::layout::{Size, Position};
|
||||||
|
|
||||||
|
|
||||||
/// Exports documents into _PDFs_.
|
/// Exports documents into _PDFs_.
|
||||||
@ -96,8 +96,8 @@ impl<'d, W: Write> PdfEngine<'d, W> {
|
|||||||
/// Write the complete document.
|
/// Write the complete document.
|
||||||
fn write(&mut self) -> PdfResult<usize> {
|
fn write(&mut self) -> PdfResult<usize> {
|
||||||
self.writer.write_header(&Version::new(1, 7))?;
|
self.writer.write_header(&Version::new(1, 7))?;
|
||||||
|
self.write_page_tree()?;
|
||||||
self.write_pages()?;
|
self.write_pages()?;
|
||||||
self.write_contents()?;
|
|
||||||
self.write_fonts()?;
|
self.write_fonts()?;
|
||||||
self.writer.write_xref_table()?;
|
self.writer.write_xref_table()?;
|
||||||
self.writer.write_trailer(&Trailer::new(self.offsets.catalog))?;
|
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.
|
/// Write the document catalog and page tree.
|
||||||
fn write_pages(&mut self) -> PdfResult<()> {
|
fn write_page_tree(&mut self) -> PdfResult<()> {
|
||||||
// The document catalog
|
// The document catalog
|
||||||
self.writer.write_obj(self.offsets.catalog, &Catalog::new(self.offsets.page_tree))?;
|
self.writer.write_obj(self.offsets.catalog, &Catalog::new(self.offsets.page_tree))?;
|
||||||
|
|
||||||
// The font resources
|
// The font resources
|
||||||
|
let offset = self.offsets.fonts.0;
|
||||||
let fonts = (0 .. self.fonts.len())
|
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
|
// The root page tree
|
||||||
self.writer.write_obj(self.offsets.page_tree, PageTree::new()
|
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.
|
/// 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) {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a series of text actions.
|
/// Write the content of a page.
|
||||||
fn write_text_actions(&mut self, id: u32, actions: &[TextAction]) -> PdfResult<()> {
|
fn write_page(&mut self, id: u32, page: &DocPage) -> PdfResult<()> {
|
||||||
let mut font = 0;
|
let mut font = 0;
|
||||||
let mut text = Text::new();
|
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 {
|
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::WriteText(string) => { text.tj(self.fonts[font].encode(&string)); },
|
||||||
TextAction::SetFont(id, size) => {
|
TextAction::SetFont(id, size) => {
|
||||||
font = *id;
|
font = *id;
|
||||||
|
@ -22,7 +22,7 @@ impl<'a, 'p> BoxLayouter<'a, 'p> {
|
|||||||
|
|
||||||
/// Add a sublayout.
|
/// Add a sublayout.
|
||||||
pub fn add_layout_absolute(&mut self, position: Position, layout: Layout) {
|
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);
|
self.actions.extend(layout.actions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,12 @@ pub struct Position {
|
|||||||
pub y: Size,
|
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.
|
/// Size of a box in 2-dimensional space.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Default)]
|
#[derive(Debug, Copy, Clone, PartialEq, Default)]
|
||||||
pub struct Extent {
|
pub struct Extent {
|
||||||
|
@ -145,8 +145,9 @@ impl<'a, 'p> TextFinisher<'a, 'p> {
|
|||||||
let mut units = Vec::new();
|
let mut units = Vec::new();
|
||||||
mem::swap(&mut self.layouter.units, &mut units);
|
mem::swap(&mut self.layouter.units, &mut units);
|
||||||
|
|
||||||
// Move to the top-left corner of the layout space.
|
// Move from the origin one line below because the y-component of the origin is the
|
||||||
self.move_start();
|
// baseline.
|
||||||
|
self.move_newline(1.0);
|
||||||
|
|
||||||
for unit in units {
|
for unit in units {
|
||||||
match unit {
|
match unit {
|
||||||
@ -206,30 +207,19 @@ 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.
|
/// Move to the next line. A factor of 1.0 uses the default line spacing.
|
||||||
fn move_newline(&mut self, factor: f32) {
|
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)
|
let vertical = Size::from_points(self.layouter.ctx.text_style.font_size)
|
||||||
* self.layouter.ctx.text_style.line_spacing
|
* self.layouter.ctx.text_style.line_spacing
|
||||||
* factor;
|
* factor;
|
||||||
|
|
||||||
self.actions.push(TextAction::MoveNewline(Position {
|
self.actions.push(TextAction::MoveNewline(Position {
|
||||||
x: Size::zero(),
|
x: Size::zero(),
|
||||||
y: -vertical
|
y: vertical
|
||||||
}));
|
}));
|
||||||
|
|
||||||
self.current_width = Size::zero();
|
self.current_width = Size::zero();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Output a text action containing the buffered text and reset the buffer.
|
/// Output a text action containing the buffered text and reset the buffer.
|
||||||
fn write_buffered_text(&mut self) {
|
fn write_buffered_text(&mut self) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user