summaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-08-01 17:42:08 +0200
committerGitHub <noreply@github.com>2020-08-01 17:42:08 +0200
commit4ac3aa6ebc7c80945fd6c4a97a531d520e965879 (patch)
treebb3c75230098bf71d1ac23bbe7184e4ae7a6cef2 /src/layout
parent064954cf9edbb0201b6184e69978f86e93741008 (diff)
parent06dbac6efd98be5a015023c88ed3dbd9a35a4594 (diff)
Merge pull request #9 from typst/port-fontdock
Port font handling to fontdock and ttf-parser 🛳
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/actions.rs16
-rw-r--r--src/layout/mod.rs10
-rw-r--r--src/layout/model.rs11
-rw-r--r--src/layout/text.rs52
4 files changed, 43 insertions, 46 deletions
diff --git a/src/layout/actions.rs b/src/layout/actions.rs
index 317cff25..7806932e 100644
--- a/src/layout/actions.rs
+++ b/src/layout/actions.rs
@@ -2,7 +2,7 @@
use std::fmt::{self, Debug, Formatter};
use serde::ser::{Serialize, Serializer, SerializeTuple};
-use toddle::query::FontIndex;
+use fontdock::FaceId;
use crate::length::{Length, Size};
use super::Layout;
@@ -15,7 +15,7 @@ pub enum LayoutAction {
/// Move to an absolute position.
MoveAbsolute(Size),
/// Set the font given the index from the font loader and font size.
- SetFont(FontIndex, Length),
+ SetFont(FaceId, Length),
/// Write text at the current position.
WriteText(String),
/// Visualize a box for debugging purposes.
@@ -31,10 +31,10 @@ impl Serialize for LayoutAction {
tup.serialize_element(&pos)?;
tup.end()
}
- LayoutAction::SetFont(index, size) => {
+ LayoutAction::SetFont(id, size) => {
let mut tup = serializer.serialize_tuple(4)?;
tup.serialize_element(&1u8)?;
- tup.serialize_element(index)?;
+ tup.serialize_element(id)?;
tup.serialize_element(size)?;
tup.end()
}
@@ -59,7 +59,7 @@ impl Debug for LayoutAction {
use LayoutAction::*;
match self {
MoveAbsolute(s) => write!(f, "move {} {}", s.x, s.y),
- SetFont(i, s) => write!(f, "font {}-{} {}", i.id, i.variant, s),
+ SetFont(id, s) => write!(f, "font {}-{} {}", id.index, id.variant, s),
WriteText(s) => write!(f, "write {:?}", s),
DebugBox(s) => write!(f, "box {} {}", s.x, s.y),
}
@@ -82,9 +82,9 @@ impl Debug for LayoutAction {
pub struct LayoutActions {
origin: Size,
actions: Vec<LayoutAction>,
- active_font: (FontIndex, Length),
+ active_font: (FaceId, Length),
next_pos: Option<Size>,
- next_font: Option<(FontIndex, Length)>,
+ next_font: Option<(FaceId, Length)>,
}
impl LayoutActions {
@@ -93,7 +93,7 @@ impl LayoutActions {
LayoutActions {
actions: vec![],
origin: Size::ZERO,
- active_font: (FontIndex::MAX, Length::ZERO),
+ active_font: (FaceId::MAX, Length::ZERO),
next_pos: None,
next_font: None,
}
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 4863d554..8bcceda6 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -3,7 +3,7 @@
use std::fmt::{self, Display, Formatter};
use smallvec::SmallVec;
use serde::Serialize;
-use toddle::query::FontIndex;
+use fontdock::FaceId;
use crate::length::{Length, Size, Margins};
use self::prelude::*;
@@ -44,12 +44,12 @@ pub struct Layout {
impl Layout {
/// Returns a vector with all used font indices.
- pub fn find_used_fonts(&self) -> Vec<FontIndex> {
+ pub fn find_used_fonts(&self) -> Vec<FaceId> {
let mut fonts = Vec::new();
for action in &self.actions {
- if let LayoutAction::SetFont(index, _) = action {
- if !fonts.contains(index) {
- fonts.push(*index);
+ if let &LayoutAction::SetFont(id, _) = action {
+ if !fonts.contains(&id) {
+ fonts.push(id);
}
}
}
diff --git a/src/layout/model.rs b/src/layout/model.rs
index a15598d2..3fb594d5 100644
--- a/src/layout/model.rs
+++ b/src/layout/model.rs
@@ -5,10 +5,9 @@
use std::future::Future;
use std::pin::Pin;
use smallvec::smallvec;
-use toddle::query::FontStyle;
use crate::{Pass, Feedback};
-use crate::GlobalFontLoader;
+use crate::SharedFontLoader;
use crate::style::{LayoutStyle, PageStyle, TextStyle};
use crate::length::{Length, Size};
use crate::syntax::{Model, SyntaxModel, Node, Decoration};
@@ -31,7 +30,7 @@ pub struct ModelLayouter<'a> {
pub struct LayoutContext<'a> {
/// The font loader to retrieve fonts from when typesetting text
/// using [`layout_text`].
- pub loader: &'a GlobalFontLoader,
+ pub loader: &'a SharedFontLoader,
/// The style for pages and text.
pub style: &'a LayoutStyle,
/// The base unpadded dimensions of this container (for relative sizing).
@@ -167,7 +166,7 @@ impl<'a> ModelLayouter<'a> {
Linebreak => self.layouter.finish_line(),
Text(text) => {
- if self.style.text.variant.style == FontStyle::Italic {
+ if self.style.text.italic {
decorate(self, Decoration::Italic);
}
@@ -179,7 +178,7 @@ impl<'a> ModelLayouter<'a> {
}
ToggleItalic => {
- self.style.text.variant.style.toggle();
+ self.style.text.italic = !self.style.text.italic;
decorate(self, Decoration::Italic);
}
@@ -191,7 +190,7 @@ impl<'a> ModelLayouter<'a> {
Raw(lines) => {
// TODO: Make this more efficient.
let fallback = self.style.text.fallback.clone();
- self.style.text.fallback.list.insert(0, "monospace".to_string());
+ self.style.text.fallback.list_mut().insert(0, "monospace".to_string());
self.style.text.fallback.flatten();
// Layout the first line.
diff --git a/src/layout/text.rs b/src/layout/text.rs
index cbe40214..22616667 100644
--- a/src/layout/text.rs
+++ b/src/layout/text.rs
@@ -4,10 +4,8 @@
//! When the primary layouting axis horizontally inversed, the word is spelled
//! backwards. Vertical word layout is not yet supported.
-use toddle::query::{FontQuery, FontIndex};
-use toddle::tables::{CharMap, Header, HorizontalMetrics};
-
-use crate::GlobalFontLoader;
+use fontdock::{FaceId, FaceQuery, FontStyle};
+use crate::font::SharedFontLoader;
use crate::length::{Length, Size};
use crate::style::TextStyle;
use super::*;
@@ -19,7 +17,7 @@ struct TextLayouter<'a> {
text: &'a str,
actions: LayoutActions,
buffer: String,
- active_font: FontIndex,
+ active_font: FaceId,
width: Length,
}
@@ -28,7 +26,7 @@ struct TextLayouter<'a> {
pub struct TextContext<'a> {
/// The font loader to retrieve fonts from when typesetting text
/// using [`layout_text`].
- pub loader: &'a GlobalFontLoader,
+ pub loader: &'a SharedFontLoader,
/// The style for text: Font selection with classes, weights and variants,
/// font sizes, spacing and so on.
pub style: &'a TextStyle,
@@ -52,7 +50,7 @@ impl<'a> TextLayouter<'a> {
text,
actions: LayoutActions::new(),
buffer: String::new(),
- active_font: FontIndex::MAX,
+ active_font: FaceId::MAX,
width: Length::ZERO,
}
}
@@ -109,41 +107,41 @@ impl<'a> TextLayouter<'a> {
/// Select the best font for a character and return its index along with
/// the width of the char in the font.
- async fn select_font(&mut self, c: char) -> Option<(FontIndex, Length)> {
+ async fn select_font(&mut self, c: char) -> Option<(FaceId, Length)> {
let mut loader = self.ctx.loader.borrow_mut();
let mut variant = self.ctx.style.variant;
+
if self.ctx.style.bolder {
variant.weight.0 += 300;
}
- let query = FontQuery {
+ if self.ctx.style.italic {
+ variant.style = match variant.style {
+ FontStyle::Normal => FontStyle::Italic,
+ FontStyle::Italic => FontStyle::Normal,
+ FontStyle::Oblique => FontStyle::Normal,
+ }
+ }
+
+ let query = FaceQuery {
fallback: self.ctx.style.fallback.iter(),
variant,
c,
};
- if let Some((font, index)) = loader.get(query).await {
+ if let Some((id, face)) = loader.query(query).await {
// Determine the width of the char.
- let header = font.read_table::<Header>().ok()?;
- let font_unit_ratio = 1.0 / (header.units_per_em as f64);
- let font_unit_to_size = |x| Length::pt(font_unit_ratio * x);
-
- let glyph = font
- .read_table::<CharMap>()
- .ok()?
- .get(c)?;
-
- let glyph_width = font
- .read_table::<HorizontalMetrics>()
- .ok()?
- .get(glyph)?
- .advance_width as f64;
-
- let char_width = font_unit_to_size(glyph_width)
+ let units_per_em = face.units_per_em().unwrap_or(1000);
+ let ratio = 1.0 / (units_per_em as f64);
+ let to_length = |x| Length::pt(ratio * x as f64);
+
+ let glyph = face.glyph_index(c)?;
+ let glyph_width = face.glyph_hor_advance(glyph)?;
+ let char_width = to_length(glyph_width)
* self.ctx.style.font_size().to_pt();
- Some((index, char_width))
+ Some((id, char_width))
} else {
None
}