From 6672f8f7dfcb38bbda3ec92bdf95341c05e9a782 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sun, 4 Oct 2020 18:18:55 +0200 Subject: [PATCH] =?UTF-8?q?Remove=20Typesetter=20in=20favor=20of=20typeset?= =?UTF-8?q?=20function=20=F0=9F=8E=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- benches/benchmarks.rs | 9 +++-- main/src/main.rs | 7 ++-- src/export/pdf.rs | 3 +- src/layout/line.rs | 1 - src/layout/mod.rs | 41 +++++++++++++++++---- src/layout/tree.rs | 6 ++-- src/lib.rs | 83 +++++++------------------------------------ src/library/boxed.rs | 2 +- src/prelude.rs | 2 +- src/shaping.rs | 3 +- tests/test_typeset.rs | 32 +++++------------ 11 files changed, 74 insertions(+), 115 deletions(-) diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs index a63640558..62f729a00 100644 --- a/benches/benchmarks.rs +++ b/benches/benchmarks.rs @@ -3,10 +3,11 @@ use std::rc::Rc; use criterion::{criterion_group, criterion_main, Criterion}; use fontdock::fs::{FsIndex, FsProvider}; +use futures_executor::block_on; use typstc::font::FontLoader; use typstc::parse::parse; -use typstc::Typesetter; +use typstc::typeset; const FONT_DIR: &str = "fonts"; const COMA: &str = include_str!("../tests/coma.typ"); @@ -23,9 +24,11 @@ fn typesetting_benchmark(c: &mut Criterion) { let provider = FsProvider::new(files); let loader = FontLoader::new(Box::new(provider), descriptors); let loader = Rc::new(RefCell::new(loader)); - let typesetter = Typesetter::new(loader.clone()); + + let style = Default::default(); + let scope = typstc::library::_std(); c.bench_function("typeset-coma", |b| { - b.iter(|| futures_executor::block_on(typesetter.typeset(COMA))) + b.iter(|| block_on(typeset(COMA, &style, &scope, Rc::clone(&loader)))) }); } diff --git a/main/src/main.rs b/main/src/main.rs index 2a09c77c4..7abef0349 100644 --- a/main/src/main.rs +++ b/main/src/main.rs @@ -10,7 +10,7 @@ use futures_executor::block_on; use typstc::export::pdf; use typstc::font::FontLoader; use typstc::parse::LineMap; -use typstc::{Feedback, Pass, Typesetter}; +use typstc::{typeset, Feedback, Pass}; fn main() { let args: Vec<_> = std::env::args().collect(); @@ -41,11 +41,12 @@ fn main() { let loader = FontLoader::new(Box::new(provider), descriptors); let loader = Rc::new(RefCell::new(loader)); - let typesetter = Typesetter::new(loader.clone()); + let style = Default::default(); + let scope = typstc::library::_std(); let Pass { output: layouts, feedback: Feedback { mut diagnostics, .. }, - } = block_on(typesetter.typeset(&src)); + } = block_on(typeset(&src, &style, &scope, Rc::clone(&loader))); if !diagnostics.is_empty() { diagnostics.sort(); diff --git a/src/export/pdf.rs b/src/export/pdf.rs index 1bed21881..d4d1adf21 100644 --- a/src/export/pdf.rs +++ b/src/export/pdf.rs @@ -14,8 +14,7 @@ use tide::{PdfWriter, Rect, Ref, Trailer, Version}; use ttf_parser::{name_id, GlyphId}; use crate::font::FontLoader; -use crate::layout::elements::LayoutElement; -use crate::layout::BoxLayout; +use crate::layout::{BoxLayout, LayoutElement}; use crate::length::Length; /// Export a list of layouts into a _PDF_ document. diff --git a/src/layout/line.rs b/src/layout/line.rs index 86531f30d..c190c152d 100644 --- a/src/layout/line.rs +++ b/src/layout/line.rs @@ -8,7 +8,6 @@ //! Internally, the line layouter uses a stack layouter to stack the finished //! lines on top of each. -use super::stack::{StackContext, StackLayouter}; use super::*; /// Performs the line layouting. diff --git a/src/layout/mod.rs b/src/layout/mod.rs index c9abb1654..8156f596e 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1,13 +1,17 @@ //! Layouting of syntax trees into box layouts. -pub mod elements; -pub mod line; pub mod primitive; -pub mod stack; + +mod elements; +mod line; +mod stack; mod tree; +pub use elements::*; +pub use line::*; pub use primitive::*; -pub use tree::layout_tree as layout; +pub use stack::*; +pub use tree::*; use crate::geom::{Insets, Point, Rect, RectExt, Sides, Size, SizeExt}; @@ -15,8 +19,33 @@ use crate::eval::Scope; use crate::font::SharedFontLoader; use crate::style::{LayoutStyle, PageStyle, TextStyle}; use crate::syntax::SynTree; +use crate::Pass; -use elements::LayoutElements; +/// Layout a syntax tree and return the produced layout. +pub async fn layout( + tree: &SynTree, + style: &LayoutStyle, + scope: &Scope, + loader: SharedFontLoader, +) -> Pass { + let space = LayoutSpace { + size: style.page.size, + insets: style.page.insets(), + expansion: LayoutExpansion::new(true, true), + }; + tree::layout_tree(&tree, LayoutContext { + loader, + scope, + style, + base: space.usable(), + spaces: vec![space], + repeat: true, + sys: LayoutSystem::new(Dir::LTR, Dir::TTB), + align: LayoutAlign::new(GenAlign::Start, GenAlign::Start), + root: true, + }) + .await +} /// A collection of layouts. pub type MultiLayout = Vec; @@ -36,7 +65,7 @@ pub struct BoxLayout { #[derive(Debug, Clone)] pub struct LayoutContext<'a> { /// The font loader to query fonts from when typesetting text. - pub loader: &'a SharedFontLoader, + pub loader: SharedFontLoader, /// The function scope. pub scope: &'a Scope, /// The style for pages and text. diff --git a/src/layout/tree.rs b/src/layout/tree.rs index dfc1c464b..df1745441 100644 --- a/src/layout/tree.rs +++ b/src/layout/tree.rs @@ -1,6 +1,7 @@ //! Layouting of syntax trees. -use super::line::{LineContext, LineLayouter}; +use std::rc::Rc; + use super::*; use crate::shaping; use crate::style::LayoutStyle; @@ -9,7 +10,7 @@ use crate::syntax::{ }; use crate::{DynFuture, Feedback, Pass}; -/// Layout a syntax tree into a collection of boxes. +/// Layout a syntax tree in a given context. pub async fn layout_tree(tree: &SynTree, ctx: LayoutContext<'_>) -> Pass { let mut layouter = TreeLayouter::new(ctx); layouter.layout_tree(tree).await; @@ -159,6 +160,7 @@ impl<'a> TreeLayouter<'a> { style: &self.style, spaces: self.layouter.remaining(), root: false, + loader: Rc::clone(&self.ctx.loader), ..self.ctx }; diff --git a/src/lib.rs b/src/lib.rs index 43868cd4b..c4a14c2ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,78 +46,21 @@ use std::pin::Pin; use crate::diagnostic::Diagnostic; use crate::eval::{Scope, Value}; use crate::font::SharedFontLoader; -use crate::layout::{ - layout, Commands, Dir, GenAlign, LayoutAlign, LayoutContext, LayoutExpansion, - LayoutSpace, LayoutSystem, MultiLayout, -}; -use crate::style::{LayoutStyle, PageStyle, TextStyle}; -use crate::syntax::{Decoration, Offset, Pos, SpanVec, SynTree}; +use crate::layout::{Commands, MultiLayout}; +use crate::style::LayoutStyle; +use crate::syntax::{Decoration, Offset, Pos, SpanVec}; -/// Transforms source code into typesetted layouts. -/// -/// A typesetter can be configured through various methods. -pub struct Typesetter { - /// The font loader shared by all typesetting processes. +/// Process source code directly into a collection of layouts. +pub async fn typeset( + src: &str, + style: &LayoutStyle, + scope: &Scope, loader: SharedFontLoader, - /// A scope that contains the standard library function definitions. - std: Scope, - /// The base layouting style. - style: LayoutStyle, -} - -impl Typesetter { - /// Create a new typesetter. - pub fn new(loader: SharedFontLoader) -> Self { - Self { - loader, - std: crate::library::_std(), - style: LayoutStyle::default(), - } - } - - /// Set the base text style. - pub fn set_text_style(&mut self, style: TextStyle) { - self.style.text = style; - } - - /// Set the base page style. - pub fn set_page_style(&mut self, style: PageStyle) { - self.style.page = style; - } - - /// Parse source code into a syntax tree. - pub fn parse(&self, src: &str) -> Pass { - parse::parse(src) - } - - /// Layout a syntax tree and return the produced layout. - pub async fn layout(&self, tree: &SynTree) -> Pass { - let space = LayoutSpace { - size: self.style.page.size, - insets: self.style.page.insets(), - expansion: LayoutExpansion::new(true, true), - }; - layout(&tree, LayoutContext { - loader: &self.loader, - scope: &self.std, - style: &self.style, - base: space.usable(), - spaces: vec![space], - repeat: true, - sys: LayoutSystem::new(Dir::LTR, Dir::TTB), - align: LayoutAlign::new(GenAlign::Start, GenAlign::Start), - root: true, - }) - .await - } - - /// Process source code directly into a collection of layouts. - pub async fn typeset(&self, src: &str) -> Pass { - let parsed = self.parse(src); - let layouted = self.layout(&parsed.output).await; - let feedback = Feedback::merge(parsed.feedback, layouted.feedback); - Pass::new(layouted.output, feedback) - } +) -> Pass { + let parsed = parse::parse(src); + let layouted = layout::layout(&parsed.output, style, scope, loader).await; + let feedback = Feedback::merge(parsed.feedback, layouted.feedback); + Pass::new(layouted.output, feedback) } /// A dynamic future type which allows recursive invocation of async functions diff --git a/src/library/boxed.rs b/src/library/boxed.rs index b36a151b9..fe0272bfb 100644 --- a/src/library/boxed.rs +++ b/src/library/boxed.rs @@ -33,7 +33,7 @@ pub async fn boxed( ctx.spaces[0].expansion.vertical = true; } - let layouted = layout(&content, ctx).await; + let layouted = layout_tree(&content, ctx).await; let layout = layouted.output.into_iter().next().unwrap(); f.extend(layouted.feedback); diff --git a/src/prelude.rs b/src/prelude.rs index 899ced7da..84c5859bd 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -4,7 +4,7 @@ pub use crate::eval::{Dict, DictValue, Value}; pub use crate::layout::primitive::*; #[doc(no_inline)] -pub use crate::layout::{layout, Command, Commands, LayoutContext}; +pub use crate::layout::{layout_tree, Command, Commands, LayoutContext}; #[doc(no_inline)] pub use crate::syntax::{Span, Spanned, SynTree}; pub use crate::{Feedback, Pass}; diff --git a/src/shaping.rs b/src/shaping.rs index 01739db39..d9e6e9fdb 100644 --- a/src/shaping.rs +++ b/src/shaping.rs @@ -9,8 +9,7 @@ use ttf_parser::GlyphId; use crate::font::FontLoader; use crate::geom::{Point, Size}; -use crate::layout::elements::{LayoutElement, LayoutElements, Shaped}; -use crate::layout::{BoxLayout, Dir, LayoutAlign}; +use crate::layout::{BoxLayout, Dir, LayoutAlign, LayoutElement, LayoutElements, Shaped}; use crate::style::TextStyle; /// Shape text into a box. diff --git a/tests/test_typeset.rs b/tests/test_typeset.rs index eb1b8ad09..4ed82032f 100644 --- a/tests/test_typeset.rs +++ b/tests/test_typeset.rs @@ -13,14 +13,10 @@ use ttf_parser::OutlineBuilder; use typstc::export::pdf; use typstc::font::{FontLoader, SharedFontLoader}; -use typstc::geom::{Point, Sides, Size, Vec2}; -use typstc::layout::elements::{LayoutElement, Shaped}; -use typstc::layout::MultiLayout; -use typstc::length::Length; -use typstc::paper::PaperClass; +use typstc::geom::{Point, Vec2}; +use typstc::layout::{LayoutElement, MultiLayout, Shaped}; use typstc::parse::LineMap; -use typstc::style::PageStyle; -use typstc::{Feedback, Pass, Typesetter}; +use typstc::{typeset, Feedback, Pass}; const TEST_DIR: &str = "tests"; const OUT_DIR: &str = "tests/out"; @@ -65,32 +61,20 @@ fn main() { let loader = FontLoader::new(Box::new(provider), descriptors); let loader = Rc::new(RefCell::new(loader)); - let mut typesetter = Typesetter::new(loader.clone()); - let edge = Length::pt(250.0).as_raw(); - typesetter.set_page_style(PageStyle { - class: PaperClass::Custom, - size: Size::new(edge, edge), - margins: Sides::uniform(None), - }); - for (name, path, src) in filtered { - test(&name, &src, &path, &mut typesetter, &loader) + test(&name, &src, &path, &loader) } } -fn test( - name: &str, - src: &str, - src_path: &Path, - typesetter: &mut Typesetter, - loader: &SharedFontLoader, -) { +fn test(name: &str, src: &str, src_path: &Path, loader: &SharedFontLoader) { println!("Testing {}.", name); + let style = Default::default(); + let scope = typstc::library::_std(); let Pass { output: layouts, feedback: Feedback { mut diagnostics, .. }, - } = block_on(typesetter.typeset(&src)); + } = block_on(typeset(&src, &style, &scope, Rc::clone(loader))); if !diagnostics.is_empty() { diagnostics.sort();