summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/engine/mod.rs16
-rw-r--r--src/engine/size.rs5
-rw-r--r--src/export/pdf.rs2
-rw-r--r--src/font.rs57
-rw-r--r--src/lib.rs11
-rw-r--r--src/parsing.rs26
-rw-r--r--src/syntax.rs2
-rw-r--r--src/utility.rs2
8 files changed, 62 insertions, 59 deletions
diff --git a/src/engine/mod.rs b/src/engine/mod.rs
index baad9bac..daec2fbb 100644
--- a/src/engine/mod.rs
+++ b/src/engine/mod.rs
@@ -10,10 +10,10 @@ pub use size::Size;
/// The core typesetting engine, transforming an abstract syntax tree into a document.
-pub(crate) struct Engine<'a> {
+pub struct Engine<'t> {
// Immutable
- tree: &'a SyntaxTree<'a>,
- ctx: &'a Context<'a>,
+ tree: &'t SyntaxTree<'t>,
+ ctx: &'t Context<'t>,
// Mutable
fonts: Vec<Font>,
@@ -23,22 +23,22 @@ pub(crate) struct Engine<'a> {
current_width: Size,
}
-impl<'a> Engine<'a> {
+impl<'t> Engine<'t> {
/// Create a new generator from a syntax tree.
- pub fn new(tree: &'a SyntaxTree<'a>, context: &'a Context<'a>) -> Engine<'a> {
+ pub(crate) fn new(tree: &'t SyntaxTree<'t>, context: &'t Context<'t>) -> Engine<'t> {
Engine {
tree,
ctx: context,
- fonts: Vec::new(),
+ fonts: vec![],
active_font: 0,
- text_commands: Vec::new(),
+ text_commands: vec![],
current_line: String::new(),
current_width: Size::zero(),
}
}
/// Generate the abstract document.
- pub fn typeset(mut self) -> TypeResult<Document> {
+ pub(crate) fn typeset(mut self) -> TypeResult<Document> {
// Load font defined by style
let mut font = None;
let filter = FontFilter::new(&self.ctx.style.font_families);
diff --git a/src/engine/size.rs b/src/engine/size.rs
index f66641c0..bf79a3c4 100644
--- a/src/engine/size.rs
+++ b/src/engine/size.rs
@@ -5,7 +5,7 @@ use std::ops::*;
/// A general size (unit of length) type.
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, PartialEq, Default)]
pub struct Size {
/// The size in typographic points (1/72 inches).
points: f32,
@@ -62,6 +62,7 @@ impl Debug for Size {
}
impl PartialOrd for Size {
+ #[inline]
fn partial_cmp(&self, other: &Size) -> Option<Ordering> {
self.points.partial_cmp(&other.points)
}
@@ -70,12 +71,14 @@ impl PartialOrd for Size {
impl Neg for Size {
type Output = Size;
+ #[inline]
fn neg(self) -> Size {
Size { points: -self.points }
}
}
impl Sum for Size {
+ #[inline]
fn sum<I>(iter: I) -> Size where I: Iterator<Item=Size> {
iter.fold(Size::zero(), Add::add)
}
diff --git a/src/export/pdf.rs b/src/export/pdf.rs
index a2260f74..91cd9cd8 100644
--- a/src/export/pdf.rs
+++ b/src/export/pdf.rs
@@ -40,7 +40,7 @@ struct PdfEngine<'d, W: Write> {
}
/// Offsets for the various groups of ids.
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
struct Offsets {
catalog: Ref,
page_tree: Ref,
diff --git a/src/font.rs b/src/font.rs
index 298f0ffd..c88d4578 100644
--- a/src/font.rs
+++ b/src/font.rs
@@ -143,8 +143,8 @@ impl Font {
loca: None,
glyphs: Vec::with_capacity(chars.len()),
chars,
- records: Vec::new(),
- body: Vec::new(),
+ records: vec![],
+ body: vec![],
};
subsetter.subset(needed_tables, optional_tables)
@@ -152,7 +152,7 @@ impl Font {
}
/// Font metrics relevant to the typesetting engine.
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq)]
pub struct FontMetrics {
/// Whether the font is italic.
pub is_italic: bool,
@@ -275,10 +275,10 @@ macro_rules! font_info {
}
/// Criteria to filter fonts.
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, Eq, PartialEq)]
pub struct FontFilter<'a> {
- /// A fallback list of font families we accept. The first family in this list, that also
- /// satisfies the other conditions shall be returned.
+ /// A fallback list of font families to accept. The first family in this list, that also
+ /// satisfies the other conditions, shall be returned.
pub families: &'a [FontFamily],
/// If some, matches only italic/non-italic fonts, otherwise any.
pub italic: Option<bool>,
@@ -298,13 +298,6 @@ impl<'a> FontFilter<'a> {
}
}
- /// Whether this filter matches the given info.
- pub fn matches(&self, info: &FontInfo) -> bool {
- self.italic.map(|i| i == info.italic).unwrap_or(true)
- && self.bold.map(|i| i == info.bold).unwrap_or(true)
- && self.families.iter().any(|family| info.families.contains(family))
- }
-
/// Set the italic value to something.
pub fn italic(&mut self, italic: bool) -> &mut Self {
self.italic = Some(italic); self
@@ -314,6 +307,13 @@ impl<'a> FontFilter<'a> {
pub fn bold(&mut self, bold: bool) -> &mut Self {
self.bold = Some(bold); self
}
+
+ /// Whether this filter matches the given info.
+ pub fn matches(&self, info: &FontInfo) -> bool {
+ self.italic.map(|i| i == info.italic).unwrap_or(true)
+ && self.bold.map(|i| i == info.bold).unwrap_or(true)
+ && self.families.iter().any(|family| info.families.contains(family))
+ }
}
/// A family of fonts (either generic or named).
@@ -326,6 +326,7 @@ pub enum FontFamily {
}
/// A font provider serving fonts from a folder on the local file system.
+#[derive(Debug)]
pub struct FileSystemFontProvider {
base: PathBuf,
paths: Vec<PathBuf>,
@@ -346,29 +347,36 @@ impl FileSystemFontProvider {
/// ("NotoSans-Italic.ttf", font_info!(["NotoSans", SansSerif], italic)),
/// ]);
/// ```
+ #[inline]
pub fn new<B, I, P>(base: B, infos: I) -> FileSystemFontProvider
where
B: Into<PathBuf>,
I: IntoIterator<Item = (P, FontInfo)>,
P: Into<PathBuf>,
{
- let mut paths = Vec::new();
- let mut font_infos = Vec::new();
-
- for (path, info) in infos.into_iter() {
+ // Find out how long the iterator is at least, to reserve the correct
+ // capacity for the vectors.
+ let iter = infos.into_iter();
+ let min = iter.size_hint().0;
+
+ // Split the iterator into two seperated vectors.
+ let mut paths = Vec::with_capacity(min);
+ let mut infos = Vec::with_capacity(min);
+ for (path, info) in iter {
paths.push(path.into());
- font_infos.push(info);
+ infos.push(info);
}
FileSystemFontProvider {
base: base.into(),
paths,
- infos: font_infos,
+ infos,
}
}
}
impl FontProvider for FileSystemFontProvider {
+ #[inline]
fn get(&self, info: &FontInfo) -> Option<Box<dyn FontData>> {
let index = self.infos.iter().position(|i| i == info)?;
let path = &self.paths[index];
@@ -376,16 +384,17 @@ impl FontProvider for FileSystemFontProvider {
Some(Box::new(file) as Box<FontData>)
}
+ #[inline]
fn available<'a>(&'a self) -> &'a [FontInfo] {
&self.infos
}
}
#[derive(Debug)]
-struct Subsetter<'p> {
+struct Subsetter<'d> {
// Original font
- font: &'p Font,
- reader: OpenTypeReader<Cursor<&'p [u8]>>,
+ font: &'d Font,
+ reader: OpenTypeReader<Cursor<&'d [u8]>>,
outlines: Outlines,
tables: Vec<TableRecord>,
cmap: Option<CharMap>,
@@ -399,7 +408,7 @@ struct Subsetter<'p> {
body: Vec<u8>,
}
-impl<'p> Subsetter<'p> {
+impl<'d> Subsetter<'d> {
fn subset<I1, S1, I2, S2>(mut self, needed_tables: I1, optional_tables: I2)
-> FontResult<Font>
where
@@ -726,7 +735,7 @@ impl<'p> Subsetter<'p> {
}))
}
- fn get_table_data(&self, tag: Tag) -> FontResult<&'p [u8]> {
+ fn get_table_data(&self, tag: Tag) -> FontResult<&'d [u8]> {
let record = match self.tables.binary_search_by_key(&tag, |r| r.tag) {
Ok(index) => &self.tables[index],
Err(_) => return Err(FontError::MissingTable(tag.to_string())),
diff --git a/src/lib.rs b/src/lib.rs
index 44c7642e..b9992b42 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,13 +2,14 @@
//!
//! # Compilation
//! - **Parsing:** The parsing step first transforms a plain string into an
-//! [iterator of tokens](crate::parsing::Tokens). Then the parser operates on that to construct
-//! a syntax tree. The structures describing the tree can be found in the [`syntax`] module.
+//! [iterator of tokens](crate::parsing::Tokens). Then the [parser](crate::parsing::Parser)
+//! operates on that to construct a syntax tree. The structures describing the tree can be found
+//! in the [syntax] module.
//! - **Typesetting:** The next step is to transform the syntax tree into a portable representation
-//! of the typesetted document. Types for these can be found in the [`doc`] module. This
+//! of the typesetted document. Types for these can be found in the [doc] module. This
//! representation contains already the finished layout.
//! - **Exporting:** The finished document can then be exported into supported formats. Submodules
-//! for the supported formats are located in the [`export`] module. Currently the only supported
+//! for the supported formats are located in the [export] module. Currently the only supported
//! format is _PDF_.
//!
//! # Example
@@ -82,7 +83,7 @@ impl<'p> Compiler<'p> {
Compiler {
context: Context {
style: Style::default(),
- font_providers: Vec::new(),
+ font_providers: vec![],
}
}
}
diff --git a/src/parsing.rs b/src/parsing.rs
index 92eaae75..4341ed4a 100644
--- a/src/parsing.rs
+++ b/src/parsing.rs
@@ -44,7 +44,6 @@ enum TokensState<'s> {
}
impl PartialEq for TokensState<'_> {
- #[inline]
fn eq(&self, other: &TokensState) -> bool {
use TokensState as TS;
@@ -184,26 +183,22 @@ impl<'s> Tokens<'s> {
}
/// Advance the iterator by one step.
- #[inline]
fn advance(&mut self) {
self.words.next();
}
/// Switch to the given state.
- #[inline]
fn switch(&mut self, mut state: TokensState<'s>) {
swap(&mut state, &mut self.state);
self.stack.push(state);
}
/// Go back to the top-of-stack state.
- #[inline]
fn unswitch(&mut self) {
self.state = self.stack.pop().unwrap_or(TokensState::Body);
}
/// Advance and return the given token.
- #[inline]
fn consumed(&mut self, token: Token<'s>) -> Token<'s> {
self.advance();
token
@@ -211,8 +206,8 @@ impl<'s> Tokens<'s> {
}
/// Transforms token streams to syntax trees.
-#[derive(Debug, Clone)]
-pub struct Parser<'s, T> where T: Iterator<Item = Token<'s>> {
+#[derive(Debug)]
+pub struct Parser<'s, T> where T: Iterator<Item=Token<'s>> {
tokens: Peekable<T>,
state: ParserState,
stack: Vec<Function<'s>>,
@@ -220,7 +215,7 @@ pub struct Parser<'s, T> where T: Iterator<Item = Token<'s>> {
}
/// The state the parser is in.
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum ParserState {
/// The base state of the parser.
Body,
@@ -228,9 +223,9 @@ enum ParserState {
Function,
}
-impl<'s, T> Parser<'s, T> where T: Iterator<Item = Token<'s>> {
+impl<'s, T> Parser<'s, T> where T: Iterator<Item=Token<'s>> {
/// Create a new parser from a type that emits results of tokens.
- pub fn new(tokens: T) -> Parser<'s, T> {
+ pub(crate) fn new(tokens: T) -> Parser<'s, T> {
Parser {
tokens: tokens.peekable(),
state: ParserState::Body,
@@ -240,13 +235,13 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item = Token<'s>> {
}
/// Parse into an abstract syntax tree.
- pub fn parse(mut self) -> ParseResult<SyntaxTree<'s>> {
+ pub(crate) fn parse(mut self) -> ParseResult<SyntaxTree<'s>> {
use ParserState as PS;
while let Some(token) = self.tokens.next() {
// Comment
if token == Token::Hashtag {
- self.skip_while(|t| *t != Token::Newline);
+ self.skip_while(|&t| t != Token::Newline);
self.advance();
}
@@ -314,13 +309,11 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item = Token<'s>> {
}
/// Advance the iterator by one step.
- #[inline]
fn advance(&mut self) {
self.tokens.next();
}
/// Skip tokens until the condition is met.
- #[inline]
fn skip_while<F>(&mut self, f: F) where F: Fn(&Token) -> bool {
while let Some(token) = self.tokens.peek() {
if !f(token) {
@@ -331,16 +324,14 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item = Token<'s>> {
}
/// Switch the state.
- #[inline]
fn switch(&mut self, state: ParserState) {
self.state = state;
}
/// Append a node to the top-of-stack function or the main tree itself.
- #[inline]
fn append(&mut self, node: Node<'s>) {
let tree = match self.stack.last_mut() {
- Some(func) => func.body.get_or_insert_with(|| SyntaxTree::new()),
+ Some(func) => func.body.as_mut().unwrap(),
None => &mut self.tree,
};
@@ -348,7 +339,6 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item = Token<'s>> {
}
/// Gives a parsing error with a message.
- #[inline]
fn err<R, S: Into<String>>(&self, message: S) -> ParseResult<R> {
Err(ParseError { message: message.into() })
}
diff --git a/src/syntax.rs b/src/syntax.rs
index 56e11605..46b84832 100644
--- a/src/syntax.rs
+++ b/src/syntax.rs
@@ -2,7 +2,7 @@
/// A logical unit of the incoming text stream.
-#[derive(Debug, Clone, Eq, PartialEq)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Token<'s> {
/// One or more whitespace (non-newline) codepoints.
Space,
diff --git a/src/utility.rs b/src/utility.rs
index efe519c4..675016ee 100644
--- a/src/utility.rs
+++ b/src/utility.rs
@@ -49,7 +49,7 @@ pub struct Spline<'s, T> {
}
/// Represents either a splitted substring or a splinor.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Splined<'s, T> {
/// A substring.
Value(&'s str),