Implement bold and italics 📜

This commit is contained in:
Laurenz 2019-04-01 12:25:31 +02:00
parent a34d725000
commit 3b4b55c59e
4 changed files with 53 additions and 28 deletions

View File

@ -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)
}

View File

@ -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]

View File

@ -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
@ -184,21 +184,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#"

View File

@ -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() {