Implement bold and italics 📜
This commit is contained in:
parent
a34d725000
commit
3b4b55c59e
@ -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)
|
||||
}
|
||||
|
@ -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]
|
||||
|
23
src/lib.rs
23
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
|
||||
@ -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#"
|
||||
|
@ -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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user