summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2019-04-01 12:25:31 +0200
committerLaurenz <laurmaedje@gmail.com>2019-04-01 12:25:31 +0200
commit3b4b55c59ecc85fc7446795f136baf632d0c9449 (patch)
treee2d55007d46312849ba2eaf0c5cf4ec4272379b5
parenta34d725000791215f2793269c4bc3de7374420ff (diff)
Implement bold and italics 📜
-rw-r--r--src/engine/mod.rs16
-rw-r--r--src/font.rs4
-rw-r--r--src/lib.rs23
-rw-r--r--src/parsing.rs38
4 files changed, 53 insertions, 28 deletions
diff --git a/src/engine/mod.rs b/src/engine/mod.rs
index 2e7938ed..80341dec 100644
--- a/src/engine/mod.rs
+++ b/src/engine/mod.rs
@@ -30,6 +30,8 @@ pub struct Engine<'t> {
current_text: String,
current_line_width: Size,
current_max_vertical_move: Size,
+ bold: bool,
+ italic: bool,
}
impl<'t> Engine<'t> {
@@ -44,6 +46,8 @@ impl<'t> Engine<'t> {
current_text: String::new(),
current_line_width: Size::zero(),
current_max_vertical_move: Size::zero(),
+ italic: false,
+ bold: false,
}
}
@@ -57,8 +61,12 @@ impl<'t> Engine<'t> {
match node {
Node::Word(word) => self.write_word(word)?,
Node::Space => self.write_space()?,
- Node::Newline => (),
- Node::ToggleItalics | Node::ToggleBold | Node::ToggleMath => unimplemented!(),
+ Node::Newline => {},
+
+ Node::ToggleItalics => self.italic = !self.italic,
+ Node::ToggleBold => self.bold = !self.bold,
+
+ Node::ToggleMath => unimplemented!(),
Node::Func(_) => unimplemented!(),
}
}
@@ -177,8 +185,8 @@ impl<'t> Engine<'t> {
fn get_font_for(&self, character: char) -> TypeResult<(usize, Ref<Font>)> {
self.font_loader.get(FontQuery {
families: &self.ctx.style.font_families,
- italic: false,
- bold: false,
+ italic: self.italic,
+ bold: self.bold,
character,
}).ok_or_else(|| TypesetError::MissingFont)
}
diff --git a/src/font.rs b/src/font.rs
index 53d31a41..f9039a71 100644
--- a/src/font.rs
+++ b/src/font.rs
@@ -13,7 +13,7 @@
use std::collections::HashMap;
use std::fs::File;
use std::path::PathBuf;
-use std::io::{self, Cursor, Read, Seek, SeekFrom};
+use std::io::{self, Cursor, Read, Seek, SeekFrom, BufReader};
use byteorder::{BE, ReadBytesExt, WriteBytesExt};
use opentype::{Error as OpentypeError, OpenTypeReader, Outlines, TableRecord, Tag};
use opentype::tables::{Header, Name, CharMap, MaximumProfile, HorizontalMetrics, Post, OS2};
@@ -339,7 +339,7 @@ impl FontProvider for FileSystemFontProvider {
let index = self.infos.iter().position(|i| i == info)?;
let path = &self.paths[index];
let file = File::open(self.base.join(path)).ok()?;
- Some(Box::new(file) as Box<FontData>)
+ Some(Box::new(BufReader::new(file)) as Box<FontData>)
}
#[inline]
diff --git a/src/lib.rs b/src/lib.rs
index f8c0c59b..d9d250b9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -20,7 +20,7 @@
//! use typeset::export::pdf::PdfExporter;
//!
//! // Simple example source code.
-//! let src = "Hello World from Typeset! 🌍";
+//! let src = "Hello World from __Typeset__! 🌍";
//!
//! // Create a compiler with a font provider that provides three fonts
//! // (the default sans-serif fonts and a fallback for the emoji).
@@ -38,7 +38,7 @@
//! # /*
//! let file = File::create("hello-typeset.pdf").unwrap();
//! # */
-//! # let file = File::create("../target/typeset-hello.pdf").unwrap();
+//! # let file = File::create("../target/typeset-doc-hello.pdf").unwrap();
//! let exporter = PdfExporter::new();
//! exporter.export(&document, file).unwrap();
//! ```
@@ -167,16 +167,16 @@ mod test {
let document = compiler.typeset(src).unwrap();
// Write to file
- let path = format!("../target/typeset-pdf-{}.pdf", name);
+ let path = format!("../target/typeset-unit-{}.pdf", name);
let file = BufWriter::new(File::create(path).unwrap());
let exporter = PdfExporter::new();
exporter.export(&document, file).unwrap();
}
#[test]
- fn small() {
+ fn simple() {
test("parentheses", "Text with ) and ( or (enclosed) works.");
- test("multiline","
+ test("multiline-lorem","
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
@@ -185,21 +185,22 @@ mod test {
}
#[test]
- fn unicode() {
- test("unicode", "∑mbe∂∂ed font with Unicode!");
- }
-
- #[test]
fn composite_glyph() {
test("composite-glyph", "Composite character‼");
}
#[test]
- fn mixed_emoji() {
+ fn unicode() {
+ test("unicode", "∑mbe∂∂ed font with Unicode!");
test("mixed-emoji", "Hello World 🌍!")
}
#[test]
+ fn styled() {
+ test("styled", "**Hello World**. That's __great__!");
+ }
+
+ #[test]
fn long_wikipedia() {
test("wikipedia", r#"
Typesetting is the composition of text by means of arranging physical types or the
diff --git a/src/parsing.rs b/src/parsing.rs
index 4341ed4a..085e7d1b 100644
--- a/src/parsing.rs
+++ b/src/parsing.rs
@@ -249,7 +249,12 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item=Token<'s>> {
PS::Body => match token {
// Whitespace
Token::Space => self.append(Node::Space),
- Token::Newline => self.append(Node::Newline),
+ Token::Newline => {
+ self.append(Node::Newline);
+ if self.tokens.peek() != Some(&Token::Space) {
+ self.append(Node::Space);
+ }
+ },
// Words
Token::Word(word) => self.append(Node::Word(word)),
@@ -382,6 +387,17 @@ mod token_tests {
test("\n", vec![N]);
}
+ /// This test looks if LF- and CRLF-style newlines get both identified correctly
+ #[test]
+ fn tokenize_whitespace_newlines() {
+ test(" \t", vec![S]);
+ test("First line\r\nSecond line\nThird line\n",
+ vec![W("First"), S, W("line"), N, W("Second"), S, W("line"), N,
+ W("Third"), S, W("line"), N]);
+ test("Hello \n ", vec![W("Hello"), S, N, S]);
+ test("Dense\nTimes", vec![W("Dense"), N, W("Times")]);
+ }
+
/// Tests if escaping with backslash works as it should.
#[test]
fn tokenize_escape() {
@@ -454,21 +470,12 @@ mod token_tests {
vec![L, W("document"), R, L, W("Hello"), S, W("🌍"), W("!"), R]);
test("[f]⺐.", vec![L, W("f"), R, W("⺐"), W(".")]);
}
-
- /// This test looks if LF- and CRLF-style newlines get both identified correctly.
- #[test]
- fn tokenize_whitespace_newlines() {
- test(" \t", vec![S]);
- test("First line\r\nSecond line\nThird line\n",
- vec![W("First"), S, W("line"), N, W("Second"), S, W("line"), N,
- W("Third"), S, W("line"), N]);
- }
}
#[cfg(test)]
mod parse_tests {
use super::*;
- use Node::{Space as S, Word as W, Func as F};
+ use Node::{Space as S, Word as W, Newline as N, Func as F};
/// Test if the source code parses into the syntax tree.
fn test(src: &str, tree: SyntaxTree) {
@@ -496,6 +503,15 @@ mod parse_tests {
test("Hello World!", tree! { W("Hello"), S, W("World"), W("!")});
}
+ /// Test whether newlines generate the correct whitespace.
+ #[test]
+ fn parse_newlines_whitespace() {
+ test("Hello \n World", tree! { W("Hello"), S, N, S, W("World") });
+ test("Hello\nWorld", tree! { W("Hello"), N, S, W("World") });
+ test("Hello\n World", tree! { W("Hello"), N, S, W("World") });
+ test("Hello \nWorld", tree! { W("Hello"), S, N, S, W("World") });
+ }
+
/// Parse things dealing with functions.
#[test]
fn parse_functions() {