Remove Typesetter in favor of typeset function 🎯

This commit is contained in:
Laurenz 2020-10-04 18:18:55 +02:00
parent 262a8fa36a
commit 6672f8f7df
11 changed files with 74 additions and 115 deletions

View File

@ -3,10 +3,11 @@ use std::rc::Rc;
use criterion::{criterion_group, criterion_main, Criterion}; use criterion::{criterion_group, criterion_main, Criterion};
use fontdock::fs::{FsIndex, FsProvider}; use fontdock::fs::{FsIndex, FsProvider};
use futures_executor::block_on;
use typstc::font::FontLoader; use typstc::font::FontLoader;
use typstc::parse::parse; use typstc::parse::parse;
use typstc::Typesetter; use typstc::typeset;
const FONT_DIR: &str = "fonts"; const FONT_DIR: &str = "fonts";
const COMA: &str = include_str!("../tests/coma.typ"); const COMA: &str = include_str!("../tests/coma.typ");
@ -23,9 +24,11 @@ fn typesetting_benchmark(c: &mut Criterion) {
let provider = FsProvider::new(files); let provider = FsProvider::new(files);
let loader = FontLoader::new(Box::new(provider), descriptors); let loader = FontLoader::new(Box::new(provider), descriptors);
let loader = Rc::new(RefCell::new(loader)); 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| { 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))))
}); });
} }

View File

@ -10,7 +10,7 @@ use futures_executor::block_on;
use typstc::export::pdf; use typstc::export::pdf;
use typstc::font::FontLoader; use typstc::font::FontLoader;
use typstc::parse::LineMap; use typstc::parse::LineMap;
use typstc::{Feedback, Pass, Typesetter}; use typstc::{typeset, Feedback, Pass};
fn main() { fn main() {
let args: Vec<_> = std::env::args().collect(); let args: Vec<_> = std::env::args().collect();
@ -41,11 +41,12 @@ fn main() {
let loader = FontLoader::new(Box::new(provider), descriptors); let loader = FontLoader::new(Box::new(provider), descriptors);
let loader = Rc::new(RefCell::new(loader)); let loader = Rc::new(RefCell::new(loader));
let typesetter = Typesetter::new(loader.clone()); let style = Default::default();
let scope = typstc::library::_std();
let Pass { let Pass {
output: layouts, output: layouts,
feedback: Feedback { mut diagnostics, .. }, feedback: Feedback { mut diagnostics, .. },
} = block_on(typesetter.typeset(&src)); } = block_on(typeset(&src, &style, &scope, Rc::clone(&loader)));
if !diagnostics.is_empty() { if !diagnostics.is_empty() {
diagnostics.sort(); diagnostics.sort();

View File

@ -14,8 +14,7 @@ use tide::{PdfWriter, Rect, Ref, Trailer, Version};
use ttf_parser::{name_id, GlyphId}; use ttf_parser::{name_id, GlyphId};
use crate::font::FontLoader; use crate::font::FontLoader;
use crate::layout::elements::LayoutElement; use crate::layout::{BoxLayout, LayoutElement};
use crate::layout::BoxLayout;
use crate::length::Length; use crate::length::Length;
/// Export a list of layouts into a _PDF_ document. /// Export a list of layouts into a _PDF_ document.

View File

@ -8,7 +8,6 @@
//! Internally, the line layouter uses a stack layouter to stack the finished //! Internally, the line layouter uses a stack layouter to stack the finished
//! lines on top of each. //! lines on top of each.
use super::stack::{StackContext, StackLayouter};
use super::*; use super::*;
/// Performs the line layouting. /// Performs the line layouting.

View File

@ -1,13 +1,17 @@
//! Layouting of syntax trees into box layouts. //! Layouting of syntax trees into box layouts.
pub mod elements;
pub mod line;
pub mod primitive; pub mod primitive;
pub mod stack;
mod elements;
mod line;
mod stack;
mod tree; mod tree;
pub use elements::*;
pub use line::*;
pub use primitive::*; 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}; use crate::geom::{Insets, Point, Rect, RectExt, Sides, Size, SizeExt};
@ -15,8 +19,33 @@ use crate::eval::Scope;
use crate::font::SharedFontLoader; use crate::font::SharedFontLoader;
use crate::style::{LayoutStyle, PageStyle, TextStyle}; use crate::style::{LayoutStyle, PageStyle, TextStyle};
use crate::syntax::SynTree; 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<MultiLayout> {
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. /// A collection of layouts.
pub type MultiLayout = Vec<BoxLayout>; pub type MultiLayout = Vec<BoxLayout>;
@ -36,7 +65,7 @@ pub struct BoxLayout {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LayoutContext<'a> { pub struct LayoutContext<'a> {
/// The font loader to query fonts from when typesetting text. /// The font loader to query fonts from when typesetting text.
pub loader: &'a SharedFontLoader, pub loader: SharedFontLoader,
/// The function scope. /// The function scope.
pub scope: &'a Scope, pub scope: &'a Scope,
/// The style for pages and text. /// The style for pages and text.

View File

@ -1,6 +1,7 @@
//! Layouting of syntax trees. //! Layouting of syntax trees.
use super::line::{LineContext, LineLayouter}; use std::rc::Rc;
use super::*; use super::*;
use crate::shaping; use crate::shaping;
use crate::style::LayoutStyle; use crate::style::LayoutStyle;
@ -9,7 +10,7 @@ use crate::syntax::{
}; };
use crate::{DynFuture, Feedback, Pass}; 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<MultiLayout> { pub async fn layout_tree(tree: &SynTree, ctx: LayoutContext<'_>) -> Pass<MultiLayout> {
let mut layouter = TreeLayouter::new(ctx); let mut layouter = TreeLayouter::new(ctx);
layouter.layout_tree(tree).await; layouter.layout_tree(tree).await;
@ -159,6 +160,7 @@ impl<'a> TreeLayouter<'a> {
style: &self.style, style: &self.style,
spaces: self.layouter.remaining(), spaces: self.layouter.remaining(),
root: false, root: false,
loader: Rc::clone(&self.ctx.loader),
..self.ctx ..self.ctx
}; };

View File

@ -46,79 +46,22 @@ use std::pin::Pin;
use crate::diagnostic::Diagnostic; use crate::diagnostic::Diagnostic;
use crate::eval::{Scope, Value}; use crate::eval::{Scope, Value};
use crate::font::SharedFontLoader; use crate::font::SharedFontLoader;
use crate::layout::{ use crate::layout::{Commands, MultiLayout};
layout, Commands, Dir, GenAlign, LayoutAlign, LayoutContext, LayoutExpansion, use crate::style::LayoutStyle;
LayoutSpace, LayoutSystem, MultiLayout, use crate::syntax::{Decoration, Offset, Pos, SpanVec};
};
use crate::style::{LayoutStyle, PageStyle, TextStyle};
use crate::syntax::{Decoration, Offset, Pos, SpanVec, SynTree};
/// 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.
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<SynTree> {
parse::parse(src)
}
/// Layout a syntax tree and return the produced layout.
pub async fn layout(&self, tree: &SynTree) -> Pass<MultiLayout> {
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. /// Process source code directly into a collection of layouts.
pub async fn typeset(&self, src: &str) -> Pass<MultiLayout> { pub async fn typeset(
let parsed = self.parse(src); src: &str,
let layouted = self.layout(&parsed.output).await; style: &LayoutStyle,
scope: &Scope,
loader: SharedFontLoader,
) -> Pass<MultiLayout> {
let parsed = parse::parse(src);
let layouted = layout::layout(&parsed.output, style, scope, loader).await;
let feedback = Feedback::merge(parsed.feedback, layouted.feedback); let feedback = Feedback::merge(parsed.feedback, layouted.feedback);
Pass::new(layouted.output, feedback) Pass::new(layouted.output, feedback)
} }
}
/// A dynamic future type which allows recursive invocation of async functions /// A dynamic future type which allows recursive invocation of async functions
/// when used as the return type. /// when used as the return type.

View File

@ -33,7 +33,7 @@ pub async fn boxed(
ctx.spaces[0].expansion.vertical = true; 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(); let layout = layouted.output.into_iter().next().unwrap();
f.extend(layouted.feedback); f.extend(layouted.feedback);

View File

@ -4,7 +4,7 @@
pub use crate::eval::{Dict, DictValue, Value}; pub use crate::eval::{Dict, DictValue, Value};
pub use crate::layout::primitive::*; pub use crate::layout::primitive::*;
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::layout::{layout, Command, Commands, LayoutContext}; pub use crate::layout::{layout_tree, Command, Commands, LayoutContext};
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::syntax::{Span, Spanned, SynTree}; pub use crate::syntax::{Span, Spanned, SynTree};
pub use crate::{Feedback, Pass}; pub use crate::{Feedback, Pass};

View File

@ -9,8 +9,7 @@ use ttf_parser::GlyphId;
use crate::font::FontLoader; use crate::font::FontLoader;
use crate::geom::{Point, Size}; use crate::geom::{Point, Size};
use crate::layout::elements::{LayoutElement, LayoutElements, Shaped}; use crate::layout::{BoxLayout, Dir, LayoutAlign, LayoutElement, LayoutElements, Shaped};
use crate::layout::{BoxLayout, Dir, LayoutAlign};
use crate::style::TextStyle; use crate::style::TextStyle;
/// Shape text into a box. /// Shape text into a box.

View File

@ -13,14 +13,10 @@ use ttf_parser::OutlineBuilder;
use typstc::export::pdf; use typstc::export::pdf;
use typstc::font::{FontLoader, SharedFontLoader}; use typstc::font::{FontLoader, SharedFontLoader};
use typstc::geom::{Point, Sides, Size, Vec2}; use typstc::geom::{Point, Vec2};
use typstc::layout::elements::{LayoutElement, Shaped}; use typstc::layout::{LayoutElement, MultiLayout, Shaped};
use typstc::layout::MultiLayout;
use typstc::length::Length;
use typstc::paper::PaperClass;
use typstc::parse::LineMap; use typstc::parse::LineMap;
use typstc::style::PageStyle; use typstc::{typeset, Feedback, Pass};
use typstc::{Feedback, Pass, Typesetter};
const TEST_DIR: &str = "tests"; const TEST_DIR: &str = "tests";
const OUT_DIR: &str = "tests/out"; const OUT_DIR: &str = "tests/out";
@ -65,32 +61,20 @@ fn main() {
let loader = FontLoader::new(Box::new(provider), descriptors); let loader = FontLoader::new(Box::new(provider), descriptors);
let loader = Rc::new(RefCell::new(loader)); 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 { for (name, path, src) in filtered {
test(&name, &src, &path, &mut typesetter, &loader) test(&name, &src, &path, &loader)
} }
} }
fn test( fn test(name: &str, src: &str, src_path: &Path, loader: &SharedFontLoader) {
name: &str,
src: &str,
src_path: &Path,
typesetter: &mut Typesetter,
loader: &SharedFontLoader,
) {
println!("Testing {}.", name); println!("Testing {}.", name);
let style = Default::default();
let scope = typstc::library::_std();
let Pass { let Pass {
output: layouts, output: layouts,
feedback: Feedback { mut diagnostics, .. }, feedback: Feedback { mut diagnostics, .. },
} = block_on(typesetter.typeset(&src)); } = block_on(typeset(&src, &style, &scope, Rc::clone(loader)));
if !diagnostics.is_empty() { if !diagnostics.is_empty() {
diagnostics.sort(); diagnostics.sort();