summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fonts/CMU-SansSerif-Bold-Italic.ttfbin462844 -> 0 bytes
-rw-r--r--fonts/CMU-SansSerif-Bold.ttfbin480476 -> 0 bytes
-rw-r--r--fonts/CMU-SansSerif-Italic.ttfbin404772 -> 0 bytes
-rw-r--r--fonts/CMU-SansSerif-Regular.ttfbin369888 -> 0 bytes
-rw-r--r--fonts/CMU-Serif-Bold-Italic.ttfbin476440 -> 0 bytes
-rw-r--r--fonts/CMU-Serif-Bold.ttfbin609796 -> 0 bytes
-rw-r--r--fonts/CMU-Serif-Italic.ttfbin486980 -> 0 bytes
-rw-r--r--fonts/CMU-Serif-Regular.ttfbin639132 -> 0 bytes
-rw-r--r--fonts/CMU-Typewriter-Bold-Italic.ttfbin458064 -> 0 bytes
-rw-r--r--fonts/CMU-Typewriter-Bold.ttfbin397792 -> 0 bytes
-rw-r--r--fonts/CMU-Typewriter-Italic.ttfbin458764 -> 0 bytes
-rw-r--r--fonts/CMU-Typewriter-Regular.ttfbin549844 -> 0 bytes
-rw-r--r--fonts/Latin-Modern-Math.otfbin733736 -> 0 bytes
-rw-r--r--fonts/License-CMU.txt103
-rw-r--r--fonts/License-Noto.txt94
-rw-r--r--fonts/NotoEmoji-Regular.ttfbin418804 -> 0 bytes
-rw-r--r--fonts/fonts.toml14
-rw-r--r--src/bin/main.rs2
-rw-r--r--src/export/pdf.rs14
-rw-r--r--src/layout/actions.rs13
-rw-r--r--src/layout/mod.rs4
-rw-r--r--src/layout/text.rs55
-rw-r--r--src/layout/tree.rs7
-rw-r--r--src/library/mod.rs80
-rw-r--r--src/style.rs71
-rw-r--r--tests/layout.rs14
-rw-r--r--tests/render.py12
27 files changed, 150 insertions, 333 deletions
diff --git a/fonts/CMU-SansSerif-Bold-Italic.ttf b/fonts/CMU-SansSerif-Bold-Italic.ttf
deleted file mode 100644
index 529277b5..00000000
--- a/fonts/CMU-SansSerif-Bold-Italic.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-SansSerif-Bold.ttf b/fonts/CMU-SansSerif-Bold.ttf
deleted file mode 100644
index d13901be..00000000
--- a/fonts/CMU-SansSerif-Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-SansSerif-Italic.ttf b/fonts/CMU-SansSerif-Italic.ttf
deleted file mode 100644
index bd30a3f9..00000000
--- a/fonts/CMU-SansSerif-Italic.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-SansSerif-Regular.ttf b/fonts/CMU-SansSerif-Regular.ttf
deleted file mode 100644
index d7513c86..00000000
--- a/fonts/CMU-SansSerif-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-Serif-Bold-Italic.ttf b/fonts/CMU-Serif-Bold-Italic.ttf
deleted file mode 100644
index 3b529ed8..00000000
--- a/fonts/CMU-Serif-Bold-Italic.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-Serif-Bold.ttf b/fonts/CMU-Serif-Bold.ttf
deleted file mode 100644
index 2c7198e5..00000000
--- a/fonts/CMU-Serif-Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-Serif-Italic.ttf b/fonts/CMU-Serif-Italic.ttf
deleted file mode 100644
index 993d5c02..00000000
--- a/fonts/CMU-Serif-Italic.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-Serif-Regular.ttf b/fonts/CMU-Serif-Regular.ttf
deleted file mode 100644
index 1c3fff0a..00000000
--- a/fonts/CMU-Serif-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-Typewriter-Bold-Italic.ttf b/fonts/CMU-Typewriter-Bold-Italic.ttf
deleted file mode 100644
index c7db8b71..00000000
--- a/fonts/CMU-Typewriter-Bold-Italic.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-Typewriter-Bold.ttf b/fonts/CMU-Typewriter-Bold.ttf
deleted file mode 100644
index f940901f..00000000
--- a/fonts/CMU-Typewriter-Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-Typewriter-Italic.ttf b/fonts/CMU-Typewriter-Italic.ttf
deleted file mode 100644
index 82c90a56..00000000
--- a/fonts/CMU-Typewriter-Italic.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/CMU-Typewriter-Regular.ttf b/fonts/CMU-Typewriter-Regular.ttf
deleted file mode 100644
index 1651877d..00000000
--- a/fonts/CMU-Typewriter-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/Latin-Modern-Math.otf b/fonts/Latin-Modern-Math.otf
deleted file mode 100644
index 0e4642e9..00000000
--- a/fonts/Latin-Modern-Math.otf
+++ /dev/null
Binary files differ
diff --git a/fonts/License-CMU.txt b/fonts/License-CMU.txt
deleted file mode 100644
index a55bb6b2..00000000
--- a/fonts/License-CMU.txt
+++ /dev/null
@@ -1,103 +0,0 @@
-Copyright (C) Authors of original metafont fonts:
-Donald Ervin Knuth (cm, concrete fonts)
-1995, 1996, 1997 J"org Knappen, 1990, 1992 Norbert Schwarz (ec fonts)
-1992-2006 A.Khodulev, O.Lapko, A.Berdnikov, V.Volovich (lh fonts)
-1997-2005 Claudio Beccari (cb greek fonts)
-2002 FUKUI Rei (tipa fonts)
-2003-2005 Han The Thanh (Vietnamese fonts)
-1996-2005 Walter Schmidt (cmbright fonts)
-
-Copyright (C) 2003-2009, Andrey V. Panov (panov@canopus.iacp.dvo.ru),
-with Reserved Font Family Name "Computer Modern Unicode fonts".
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/fonts/License-Noto.txt b/fonts/License-Noto.txt
deleted file mode 100644
index c82d72e4..00000000
--- a/fonts/License-Noto.txt
+++ /dev/null
@@ -1,94 +0,0 @@
-Copyright 2018 The Noto Project Authors (github.com/googlei18n/noto-fonts)
-
-This Font Software is licensed under the SIL Open Font License,
-Version 1.1.
-
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font
-creation efforts of academic and linguistic communities, and to
-provide a free and open framework in which fonts may be shared and
-improved in partnership with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply to
-any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software
-components as distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to,
-deleting, or substituting -- in part or in whole -- any of the
-components of the Original Version, by changing formats or by porting
-the Font Software to a new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed,
-modify, redistribute, and sell modified and unmodified copies of the
-Font Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components, in
-Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the
-corresponding Copyright Holder. This restriction only applies to the
-primary font name as presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created using
-the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/fonts/NotoEmoji-Regular.ttf b/fonts/NotoEmoji-Regular.ttf
deleted file mode 100644
index 19b7badf..00000000
--- a/fonts/NotoEmoji-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/fonts/fonts.toml b/fonts/fonts.toml
deleted file mode 100644
index b289ff5c..00000000
--- a/fonts/fonts.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-"CMU-SansSerif-Regular.ttf" = ["Computer Modern", "Regular", "SansSerif"]
-"CMU-SansSerif-Italic.ttf" = ["Computer Modern", "Italic", "SansSerif"]
-"CMU-SansSerif-Bold.ttf" = ["Computer Modern", "Bold", "SansSerif"]
-"CMU-SansSerif-Bold-Italic.ttf" = ["Computer Modern", "Bold", "Italic", "SansSerif"]
-"CMU-Serif-Regular.ttf" = ["Computer Modern", "Regular", "Serif"]
-"CMU-Serif-Italic.ttf" = ["Computer Modern", "Italic", "Serif"]
-"CMU-Serif-Bold.ttf" = ["Computer Modern", "Bold", "Serif"]
-"CMU-Serif-Bold-Italic.ttf" = ["Computer Modern", "Bold", "Italic", "Serif"]
-"CMU-Typewriter-Regular.ttf" = ["Computer Modern", "Regular", "Serif", "SansSerif", "Monospace"]
-"CMU-Typewriter-Italic.ttf" = ["Computer Modern", "Italic", "Serif", "SansSerif", "Monospace"]
-"CMU-Typewriter-Bold.ttf" = ["Computer Modern", "Bold", "Serif", "SansSerif", "Monospace"]
-"CMU-Typewriter-Bold-Italic.ttf" = ["Computer Modern", "Bold", "Italic", "Serif", "SansSerif", "Monospace"]
-"Latin-Modern-Math.otf" = ["Latin Modern", "Latin Modern Math", "Math", "Regular", "Serif"]
-"NotoEmoji-Regular.ttf" = ["Noto", "Noto Emoji", "Regular", "SansSerif", "Serif", "Monospace"]
diff --git a/src/bin/main.rs b/src/bin/main.rs
index a2b63d6d..e0bcd16d 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -36,7 +36,7 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
.map_err(|_| "failed to read from source file")?;
let mut typesetter = Typesetter::new();
- let provider = FileSystemFontProvider::from_listing("fonts/fonts.toml").unwrap();
+ let provider = FileSystemFontProvider::from_index("../fonts/index.json").unwrap();
typesetter.add_font_provider(provider);
let layouts = typesetter.typeset(&src)?;
diff --git a/src/export/pdf.rs b/src/export/pdf.rs
index 0d097a33..c5bc6ee8 100644
--- a/src/export/pdf.rs
+++ b/src/export/pdf.rs
@@ -13,7 +13,7 @@ use tide::font::{
use toddle::Error as FontError;
use toddle::font::OwnedFont;
-use toddle::query::SharedFontLoader;
+use toddle::query::{SharedFontLoader, FontIndex};
use toddle::tables::{
CharMap, Header, HorizontalMetrics, MacStyleFlags,
Name, NameEntry, Post, OS2
@@ -59,7 +59,7 @@ struct ExportProcess<'d, W: Write> {
/// go through all font usages and assign a new index for each used font.
/// This remapping is stored here because we need it when converting the
/// layout actions in `ExportProcess::write_page`.
- font_remap: HashMap<usize, usize>,
+ font_remap: HashMap<FontIndex, usize>,
/// These are the fonts sorted by their *new* ids, that is, the values of `font_remap`.
fonts: Vec<OwnedFont>,
@@ -99,13 +99,13 @@ impl<'d, W: Write> ExportProcess<'d, W> {
fn subset_fonts(
layouts: &'d MultiLayout,
font_loader: &SharedFontLoader
- ) -> PdfResult<(Vec<OwnedFont>, HashMap<usize, usize>)>
+ ) -> PdfResult<(Vec<OwnedFont>, HashMap<FontIndex, usize>)>
{
let mut fonts = Vec::new();
- let mut font_chars: HashMap<usize, HashSet<char>> = HashMap::new();
- let mut old_to_new: HashMap<usize, usize> = HashMap::new();
- let mut new_to_old: HashMap<usize, usize> = HashMap::new();
- let mut active_font = 0;
+ let mut font_chars: HashMap<FontIndex, HashSet<char>> = HashMap::new();
+ let mut old_to_new: HashMap<FontIndex, usize> = HashMap::new();
+ let mut new_to_old: HashMap<usize, FontIndex> = HashMap::new();
+ let mut active_font = FontIndex::MAX;
// We want to find out which fonts are used at all and which are chars
// are used for these. We use this information to create subsetted fonts.
diff --git a/src/layout/actions.rs b/src/layout/actions.rs
index b0d2c21d..4ab9fdb1 100644
--- a/src/layout/actions.rs
+++ b/src/layout/actions.rs
@@ -1,6 +1,7 @@
//! Drawing and cofiguration actions composing layouts.
use std::fmt::{self, Display, Formatter};
+use toddle::query::FontIndex;
use super::*;
use LayoutAction::*;
@@ -11,7 +12,7 @@ pub enum LayoutAction {
/// Move to an absolute position.
MoveAbsolute(Size2D),
/// Set the font by index and font size.
- SetFont(usize, Size),
+ SetFont(FontIndex, Size),
/// Write text starting at the current position.
WriteText(String),
/// Visualize a box for debugging purposes.
@@ -22,7 +23,7 @@ impl Serialize for LayoutAction {
fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()> {
match self {
MoveAbsolute(s) => write!(f, "m {:.4} {:.4}", s.x.to_pt(), s.y.to_pt()),
- SetFont(i, s) => write!(f, "f {} {}", i, s.to_pt()),
+ SetFont(i, s) => write!(f, "f {} {} {}", i.id, i.variant, s.to_pt()),
WriteText(s) => write!(f, "w {}", s),
DebugBox(s) => write!(f, "b {} {}", s.x.to_pt(), s.y.to_pt()),
}
@@ -34,7 +35,7 @@ impl Display for LayoutAction {
use LayoutAction::*;
match self {
MoveAbsolute(s) => write!(f, "move {} {}", s.x, s.y),
- SetFont(i, s) => write!(f, "font {} {}", i, s),
+ SetFont(i, s) => write!(f, "font {} {} {}", i.id, i.variant, s),
WriteText(s) => write!(f, "write \"{}\"", s),
DebugBox(s) => write!(f, "box {}", s),
}
@@ -58,9 +59,9 @@ debug_display!(LayoutAction);
pub struct LayoutActions {
pub origin: Size2D,
actions: Vec<LayoutAction>,
- active_font: (usize, Size),
+ active_font: (FontIndex, Size),
next_pos: Option<Size2D>,
- next_font: Option<(usize, Size)>,
+ next_font: Option<(FontIndex, Size)>,
}
impl LayoutActions {
@@ -69,7 +70,7 @@ impl LayoutActions {
LayoutActions {
actions: vec![],
origin: Size2D::ZERO,
- active_font: (std::usize::MAX, Size::ZERO),
+ active_font: (FontIndex::MAX, Size::ZERO),
next_pos: None,
next_font: None,
}
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 53c3e91e..be1ed43c 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -2,7 +2,7 @@
use std::io::{self, Write};
use smallvec::SmallVec;
-use toddle::query::SharedFontLoader;
+use toddle::query::{SharedFontLoader, FontIndex};
use crate::size::{Size, Size2D, SizeBox};
use crate::style::LayoutStyle;
@@ -58,7 +58,7 @@ pub struct Layout {
impl Layout {
/// Returns a vector with all used font indices.
- pub fn find_used_fonts(&self) -> Vec<usize> {
+ pub fn find_used_fonts(&self) -> Vec<FontIndex> {
let mut fonts = Vec::new();
for action in &self.actions {
if let LayoutAction::SetFont(index, _) = action {
diff --git a/src/layout/text.rs b/src/layout/text.rs
index e9721429..96704f60 100644
--- a/src/layout/text.rs
+++ b/src/layout/text.rs
@@ -1,4 +1,4 @@
-use toddle::query::{SharedFontLoader, FontQuery, FontClass};
+use toddle::query::{SharedFontLoader, FontQuery, FontIndex};
use toddle::tables::{CharMap, Header, HorizontalMetrics};
use crate::size::{Size, Size2D};
@@ -30,9 +30,8 @@ struct TextLayouter<'a, 'p> {
text: &'a str,
actions: LayoutActions,
buffer: String,
- active_font: usize,
+ active_font: FontIndex,
width: Size,
- classes: Vec<FontClass>,
}
impl<'a, 'p> TextLayouter<'a, 'p> {
@@ -43,9 +42,8 @@ impl<'a, 'p> TextLayouter<'a, 'p> {
text,
actions: LayoutActions::new(),
buffer: String::new(),
- active_font: std::usize::MAX,
+ active_font: FontIndex::MAX,
width: Size::ZERO,
- classes: ctx.style.classes.clone(),
}
}
@@ -95,39 +93,34 @@ impl<'a, 'p> TextLayouter<'a, 'p> {
/// Select the best font for a character and return its index along with
/// the width of the char in the font.
- fn select_font(&mut self, c: char) -> LayoutResult<(usize, Size)> {
+ fn select_font(&mut self, c: char) -> LayoutResult<(FontIndex, Size)> {
let mut loader = self.ctx.loader.borrow_mut();
- for class in &self.ctx.style.fallback {
- self.classes.push(class.clone());
+ let query = FontQuery {
+ fallback: &self.ctx.style.fallback,
+ variant: self.ctx.style.variant,
+ c,
+ };
- let query = FontQuery {
- chars: &[c],
- classes: &self.classes,
- };
+ if let Some((font, index)) = loader.get(query) {
+ let font_unit_ratio = 1.0 / (font.read_table::<Header>()?.units_per_em as f32);
+ let font_unit_to_size = |x| Size::pt(font_unit_ratio * x);
- if let Some((font, index)) = loader.get(query) {
- let font_unit_ratio = 1.0 / (font.read_table::<Header>()?.units_per_em as f32);
- let font_unit_to_size = |x| Size::pt(font_unit_ratio * x);
+ let glyph = font
+ .read_table::<CharMap>()?
+ .get(c)
+ .expect("select_font: font should have char");
- let glyph = font
- .read_table::<CharMap>()?
- .get(c)
- .expect("select_font: font should have char");
+ let glyph_width = font
+ .read_table::<HorizontalMetrics>()?
+ .get(glyph)
+ .expect("select_font: font should have glyph")
+ .advance_width as f32;
- let glyph_width = font
- .read_table::<HorizontalMetrics>()?
- .get(glyph)
- .expect("select_font: font should have glyph")
- .advance_width as f32;
+ let char_width = font_unit_to_size(glyph_width)
+ * self.ctx.style.font_size().to_pt();
- let char_width = font_unit_to_size(glyph_width)
- * self.ctx.style.font_size().to_pt();
-
- return Ok((index, char_width));
- }
-
- self.classes.pop();
+ return Ok((index, char_width));
}
error!("no suitable font for character `{}`", c);
diff --git a/src/layout/tree.rs b/src/layout/tree.rs
index db59ca8d..e77fd528 100644
--- a/src/layout/tree.rs
+++ b/src/layout/tree.rs
@@ -1,5 +1,4 @@
use smallvec::smallvec;
-use toddle::query::FontClass;
use crate::func::Command;
use crate::syntax::{SyntaxTree, Node, FuncCall};
@@ -45,9 +44,9 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
Node::Space => self.layout_space(),
Node::Newline => self.layout_paragraph()?,
- Node::ToggleItalics => self.style.text.toggle_class(FontClass::Italic),
- Node::ToggleBold => self.style.text.toggle_class(FontClass::Bold),
- Node::ToggleMonospace => self.style.text.toggle_class(FontClass::Monospace),
+ Node::ToggleItalics => {},
+ Node::ToggleBold => {},
+ Node::ToggleMonospace => {},
Node::Func(func) => self.layout_func(func)?,
}
diff --git a/src/library/mod.rs b/src/library/mod.rs
index 7f7a0411..d4519867 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -1,6 +1,6 @@
//! The standard library.
-use toddle::query::FontClass;
+use toddle::query::{FontWeight, FontStyle};
use crate::func::prelude::*;
use crate::style::{Paper, PaperClass};
@@ -36,11 +36,10 @@ pub fn std() -> Scope {
std.add_with_metadata::<Spacing>("h", Some(Horizontal));
std.add_with_metadata::<Spacing>("v", Some(Vertical));
- std.add_with_metadata::<StyleChange>("bold", FontClass::Bold);
- std.add_with_metadata::<StyleChange>("italic", FontClass::Italic);
- std.add_with_metadata::<StyleChange>("mono", FontClass::Monospace);
-
- std.add::<FontFamily>("font.family");
+ std.add_with_metadata::<FontFamily>("font.family", None);
+ std.add_with_metadata::<FontFamily>("mono", Some("monospace".to_string()));
+ std.add::<SetFontStyle>("font.style");
+ std.add::<SetFontWeight>("font.weight");
std.add::<FontSize>("font.size");
std
@@ -218,25 +217,66 @@ function! {
}
function! {
- /// `bold`, `italic`, `mono`: Sets text with a different style.
+ /// `font.weight`, `bold`: Set text with a given weight.
#[derive(Debug, PartialEq)]
- pub struct StyleChange {
+ pub struct SetFontWeight {
body: Option<SyntaxTree>,
- class: FontClass,
+ weight: FontWeight,
}
- type Meta = FontClass;
-
parse(args, body, ctx, meta) {
- StyleChange {
+ SetFontWeight {
+ body: parse!(optional: body, ctx),
+ weight: match args.get_pos::<Expression>()? {
+ Expression::Num(weight) => FontWeight(if weight < 0.0 {
+ 0
+ } else if weight < 1000.0 {
+ weight.round() as u16
+ } else {
+ 1000
+ }),
+ Expression::Ident(Ident(s)) => {
+ match FontWeight::from_str(&s) {
+ Some(weight) => weight,
+ None => error!("invalid font weight: `{}`", s),
+ }
+ }
+ _ => error!("expected identifier or number"),
+ },
+ }
+ }
+
+ layout(self, ctx) {
+ let mut style = ctx.style.text.clone();
+ style.variant.style.toggle();
+ styled(&self.body, &ctx, style)
+ }
+}
+
+function! {
+ /// `font.style`: Set the font style (normal / italic).
+ #[derive(Debug, PartialEq)]
+ pub struct SetFontStyle {
+ body: Option<SyntaxTree>,
+ style: FontStyle,
+ }
+
+ parse(args, body, ctx) {
+ SetFontStyle {
body: parse!(optional: body, ctx),
- class: meta,
+ style: {
+ let s = args.get_pos::<String>()?;
+ match FontStyle::from_str(&s) {
+ Some(style) => style,
+ None => error!("invalid font style: `{}`", s),
+ }
+ }
}
}
layout(self, ctx) {
let mut style = ctx.style.text.clone();
- style.toggle_class(self.class.clone());
+ style.variant.style = self.style;
styled(&self.body, &ctx, style)
}
}
@@ -249,16 +289,22 @@ function! {
family: String,
}
- parse(args, body, ctx) {
+ type Meta = Option<String>;
+
+ parse(args, body, ctx, meta) {
FontFamily {
body: parse!(optional: body, ctx),
- family: args.get_pos::<String>()?,
+ family: if let Some(family) = meta {
+ family
+ } else {
+ args.get_pos::<String>()?
+ },
}
}
layout(self, ctx) {
let mut style = ctx.style.text.clone();
- style.fallback.insert(0, FontClass::Family(self.family.clone()));
+ style.fallback.list = vec![self.family.clone()];
styled(&self.body, &ctx, style)
}
}
diff --git a/src/style.rs b/src/style.rs
index df5e13d1..ffa10d51 100644
--- a/src/style.rs
+++ b/src/style.rs
@@ -1,11 +1,11 @@
//! Styles for text and pages.
-use toddle::query::FontClass;
-use FontClass::*;
+use toddle::query::{FontFallbackTree, FontVariant, FontStyle, FontWeight};
use crate::size::{Size, Size2D, SizeBox, ValueBox, PSize};
use crate::syntax::ParseResult;
+
/// Defines properties of pages and text.
#[derive(Debug, Default, Clone)]
pub struct LayoutStyle {
@@ -16,11 +16,10 @@ pub struct LayoutStyle {
/// Defines which fonts to use and how to space text.
#[derive(Debug, Clone)]
pub struct TextStyle {
- /// The classes the font has to be part of.
- pub classes: Vec<FontClass>,
- /// The fallback classes from which the font needs to match the leftmost
- /// possible one.
- pub fallback: Vec<FontClass>,
+ /// A tree of font names and generic family names.
+ pub fallback: FontFallbackTree,
+ /// The selected font variant.
+ pub variant: FontVariant,
/// The base font size.
pub base_font_size: Size,
/// The font scale to apply on the base font size.
@@ -53,48 +52,34 @@ impl TextStyle {
pub fn paragraph_spacing(&self) -> Size {
(self.paragraph_spacing_scale - 1.0) * self.font_size()
}
+}
- /// Toggle a class.
- ///
- /// If the class was one of _italic_ or _bold_, then:
- /// - If it was not present before, the _regular_ class will be removed.
- /// - If it was present before, the _regular_ class will be added in case
- /// the other style class is not present.
- pub fn toggle_class(&mut self, class: FontClass) {
- if self.classes.contains(&class) {
- // If we retain a Bold or Italic class, we will not add the Regular
- // class.
- let mut regular = true;
- self.classes.retain(|x| {
- if class == *x {
- false
- } else {
- if class == Bold || class == Italic {
- regular = false;
- }
- true
- }
- });
-
- if regular {
- self.classes.push(Regular);
- }
- } else {
- // If we add an Italic or Bold class, we remove the Regular class.
- if class == Italic || class == Bold {
- self.classes.retain(|x| x != &Regular);
- }
-
- self.classes.push(class);
- }
- }
+macro_rules! fallback {
+ (($($f:expr),*), $($c:expr => ($($cf:expr),*)),*) => ({
+ let mut fallback = FontFallbackTree::new(vec![$($f.to_string()),*]);
+ $(
+ fallback.set_class_list($c.to_string(), vec![$($cf.to_string()),*])
+ .expect("TextStyle::default: unexpected error \
+ when setting class list");
+ )*
+ fallback
+ });
}
impl Default for TextStyle {
fn default() -> TextStyle {
TextStyle {
- classes: vec![Regular],
- fallback: vec![Serif],
+ fallback: fallback! {
+ ("sans-serif"),
+ "serif" => ("source serif pro", "noto serif", "noto emoji"),
+ "sans-serif" => ("source sans pro", "noto sans", "noto emoji"),
+ "monospace" => ("source code pro", "noto sans mono", "noto emoji"),
+ "math" => ("latin modern math", "serif")
+ },
+ variant: FontVariant {
+ style: FontStyle::Normal,
+ weight: FontWeight(400),
+ },
base_font_size: Size::pt(11.0),
font_scale: 1.0,
word_spacing_scale: 0.25,
diff --git a/tests/layout.rs b/tests/layout.rs
index 8a72e84b..096bc43f 100644
--- a/tests/layout.rs
+++ b/tests/layout.rs
@@ -47,7 +47,11 @@ fn main() -> Result<()> {
println!("Running {} test{}", len, if len > 1 { "s" } else { "" });
for (name, src) in filtered {
- panic::catch_unwind(|| test(&name, &src)).ok();
+ panic::catch_unwind(|| {
+ if let Err(e) = test(&name, &src) {
+ println!("error: {}", e);
+ }
+ }).ok();
}
println!();
@@ -65,7 +69,7 @@ fn test(name: &str, src: &str) -> Result<()> {
.. PageStyle::default()
});
- let provider = FileSystemFontProvider::from_listing("fonts/fonts.toml")?;
+ let provider = FileSystemFontProvider::from_index("../fonts/index.json")?;
let font_paths = provider.paths();
typesetter.add_font_provider(provider);
@@ -80,8 +84,8 @@ fn test(name: &str, src: &str) -> Result<()> {
for layout in &layouts {
for index in layout.find_used_fonts() {
fonts.entry(index).or_insert_with(|| {
- let provider_index = loader.get_provider_and_index(index).1;
- font_paths[provider_index].to_string_lossy()
+ let p = loader.get_provider_and_index(index.id).1;
+ &font_paths[p][index.variant]
});
}
}
@@ -94,7 +98,7 @@ fn test(name: &str, src: &str) -> Result<()> {
// Write the font mapping into the serialization file.
writeln!(file, "{}", fonts.len())?;
for (index, path) in fonts.iter() {
- writeln!(file, "{} {}", index, path)?;
+ writeln!(file, "{} {} {}", index.id, index.variant, path)?;
}
layouts.serialize(&mut file)?;
diff --git a/tests/render.py b/tests/render.py
index fe7a1de4..1387ed53 100644
--- a/tests/render.py
+++ b/tests/render.py
@@ -35,10 +35,10 @@ class MultiboxRenderer:
self.fonts = {}
font_count = int(lines[0])
for i in range(font_count):
- parts = lines[i + 1].split(' ', 1)
- index = int(parts[0])
- path = parts[1]
- self.fonts[index] = os.path.join(BASE, '../fonts', path)
+ parts = lines[i + 1].split(' ', 2)
+ index = int(parts[0]), int(parts[1])
+ path = parts[2]
+ self.fonts[index] = os.path.join(BASE, '../../fonts', path)
self.content = lines[font_count + 1:]
@@ -136,8 +136,8 @@ class BoxRenderer:
self.cursor = [x, y]
elif cmd == 'f':
- index = int(parts[0])
- size = pix(float(parts[1]))
+ index = int(parts[0]), int(parts[1])
+ size = pix(float(parts[2]))
self.font = ImageFont.truetype(self.fonts[index], size)
elif cmd == 'w':