summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/exec/state.rs2
-rw-r--r--src/export/pdf.rs2
-rw-r--r--src/layout/par.rs8
-rw-r--r--src/shaping.rs57
4 files changed, 42 insertions, 27 deletions
diff --git a/src/exec/state.rs b/src/exec/state.rs
index 22839c54..416b5d08 100644
--- a/src/exec/state.rs
+++ b/src/exec/state.rs
@@ -93,7 +93,7 @@ impl Default for ParState {
fn default() -> Self {
Self {
word_spacing: Relative::new(0.25).into(),
- line_spacing: Relative::new(0.2).into(),
+ line_spacing: Linear::ZERO,
par_spacing: Relative::new(0.5).into(),
}
}
diff --git a/src/export/pdf.rs b/src/export/pdf.rs
index 9f355278..c30222b2 100644
--- a/src/export/pdf.rs
+++ b/src/export/pdf.rs
@@ -195,7 +195,7 @@ impl<'a> PdfExporter<'a> {
}
let x = pos.x.to_pt() as f32;
- let y = (page.size.height - pos.y - size).to_pt() as f32;
+ let y = (page.size.height - pos.y).to_pt() as f32;
text.matrix(1.0, 0.0, 0.0, 1.0, x, y);
text.show(&shaped.encode_glyphs_be());
}
diff --git a/src/layout/par.rs b/src/layout/par.rs
index 7d876fc1..45494dec 100644
--- a/src/layout/par.rs
+++ b/src/layout/par.rs
@@ -163,13 +163,17 @@ impl<'a> ParLayouter<'a> {
output.push_frame(pos, frame);
}
+ // Add line spacing, but only between lines.
+ if !self.lines.is_empty() {
+ self.lines_size.main += self.par.line_spacing;
+ *self.areas.current.get_mut(self.main) -= self.par.line_spacing;
+ }
+
// Update metrics of the whole paragraph.
self.lines.push((self.lines_size.main, output, self.line_ruler));
self.lines_size.main += full_size.main;
- self.lines_size.main += self.par.line_spacing;
self.lines_size.cross = self.lines_size.cross.max(full_size.cross);
*self.areas.current.get_mut(self.main) -= full_size.main;
- *self.areas.current.get_mut(self.main) -= self.par.line_spacing;
// Reset metrics for the single line.
self.line_size = Gen::ZERO;
diff --git a/src/shaping.rs b/src/shaping.rs
index 722d103a..a8d2b2bf 100644
--- a/src/shaping.rs
+++ b/src/shaping.rs
@@ -70,6 +70,8 @@ pub fn shape(
let mut frame = Frame::new(Size::new(Length::ZERO, font_size));
let mut shaped = Shaped::new(FaceId::MAX, font_size);
let mut offset = Length::ZERO;
+ let mut ascender = Length::ZERO;
+ let mut descender = Length::ZERO;
// Create an iterator with conditional direction.
let mut forwards = text.chars();
@@ -84,47 +86,56 @@ pub fn shape(
let query = FaceQuery { fallback: fallback.iter(), variant, c };
if let Some(id) = loader.query(query) {
let face = loader.face(id).get();
- let (glyph, width) = match lookup_glyph(face, c, font_size) {
+ let (glyph, width) = match lookup_glyph(face, c) {
Some(v) => v,
None => continue,
};
- // Flush the buffer if we change the font face.
- if shaped.face != id && !shaped.text.is_empty() {
- let pos = Point::new(frame.size.width, Length::ZERO);
- frame.push(pos, Element::Text(shaped));
- frame.size.width += offset;
- shaped = Shaped::new(FaceId::MAX, font_size);
+ let units_per_em = f64::from(face.units_per_em().unwrap_or(1000));
+ let convert = |units| units / units_per_em * font_size;
+
+ // Flush the buffer and reset the metrics if we use a new font face.
+ if shaped.face != id {
+ place(&mut frame, shaped, offset, ascender, descender);
+
+ shaped = Shaped::new(id, font_size);
offset = Length::ZERO;
+ ascender = convert(f64::from(face.ascender()));
+ descender = convert(f64::from(face.descender()));
}
- shaped.face = id;
shaped.text.push(c);
shaped.glyphs.push(glyph);
shaped.offsets.push(offset);
- offset += width;
+ offset += convert(f64::from(width));
}
}
// Flush the last buffered parts of the word.
- if !shaped.text.is_empty() {
- let pos = Point::new(frame.size.width, Length::ZERO);
- frame.push(pos, Element::Text(shaped));
- frame.size.width += offset;
- }
+ place(&mut frame, shaped, offset, ascender, descender);
frame
}
-/// Looks up the glyph for `c` and returns its index alongside its width at the
-/// given `size`.
-fn lookup_glyph(face: &Face, c: char, size: Length) -> Option<(GlyphId, Length)> {
+/// Look up the glyph for `c` and returns its index alongside its advance width.
+fn lookup_glyph(face: &Face, c: char) -> Option<(GlyphId, u16)> {
let glyph = face.glyph_index(c)?;
-
- // Determine the width of the char.
- let units_per_em = face.units_per_em().unwrap_or(1000) as f64;
- let width_units = face.glyph_hor_advance(glyph)? as f64;
- let width = width_units / units_per_em * size;
-
+ let width = face.glyph_hor_advance(glyph)?;
Some((glyph, width))
}
+
+/// Place shaped text into a frame.
+fn place(
+ frame: &mut Frame,
+ shaped: Shaped,
+ offset: Length,
+ ascender: Length,
+ descender: Length,
+) {
+ if !shaped.text.is_empty() {
+ let pos = Point::new(frame.size.width, ascender);
+ frame.push(pos, Element::Text(shaped));
+ frame.size.width += offset;
+ frame.size.height = frame.size.height.max(ascender - descender);
+ }
+}