summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-03-10 10:20:01 +0100
committerLaurenz <laurmaedje@gmail.com>2021-03-10 10:20:01 +0100
commitbbb9ed07ffe8a2a0ea0a232f6cfc52f82f7f7afe (patch)
tree2b106b63e104652b66efc74a0ffa3080a8b0a134
parentb2b8d37ce03de60582230e03c03efa356b6f31d3 (diff)
Better line spacing calculations ↕
- Only add line spacing between lines. Previously, line spacing was added below every line, making `#box[word]` higher than just `word`. - Compute box height of text as `ascender - descender` so that the full word is contained in the box.
-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
-rw-r--r--tests/ref/comment.pngbin716 -> 746 bytes
-rw-r--r--tests/ref/control/for.pngbin2762 -> 2787 bytes
-rw-r--r--tests/ref/control/if.pngbin1689 -> 1727 bytes
-rw-r--r--tests/ref/control/invalid.pngbin3700 -> 3772 bytes
-rw-r--r--tests/ref/control/let.pngbin2050 -> 2089 bytes
-rw-r--r--tests/ref/control/while.pngbin886 -> 929 bytes
-rw-r--r--tests/ref/expr/array.pngbin3448 -> 3317 bytes
-rw-r--r--tests/ref/expr/block-invalid.pngbin506 -> 522 bytes
-rw-r--r--tests/ref/expr/block.pngbin1423 -> 1453 bytes
-rw-r--r--tests/ref/expr/call-invalid.pngbin2944 -> 2789 bytes
-rw-r--r--tests/ref/expr/call.pngbin6143 -> 5863 bytes
-rw-r--r--tests/ref/expr/dict.pngbin1651 -> 1627 bytes
-rw-r--r--tests/ref/expr/ops.pngbin807 -> 827 bytes
-rw-r--r--tests/ref/full/coma.pngbin59535 -> 59486 bytes
-rw-r--r--tests/ref/library/box.pngbin2663 -> 2510 bytes
-rw-r--r--tests/ref/library/font.pngbin4484 -> 4554 bytes
-rw-r--r--tests/ref/library/hv.pngbin3898 -> 3960 bytes
-rw-r--r--tests/ref/library/image.pngbin220343 -> 219392 bytes
-rw-r--r--tests/ref/library/page.pngbin8276 -> 8417 bytes
-rw-r--r--tests/ref/library/pagebreak.pngbin814 -> 840 bytes
-rw-r--r--tests/ref/markup/emph.pngbin3060 -> 3079 bytes
-rw-r--r--tests/ref/markup/escape.pngbin4190 -> 4197 bytes
-rw-r--r--tests/ref/markup/heading.pngbin4623 -> 4656 bytes
-rw-r--r--tests/ref/markup/linebreak.pngbin3765 -> 3864 bytes
-rw-r--r--tests/ref/markup/nbsp.pngbin1745 -> 1818 bytes
-rw-r--r--tests/ref/markup/raw.pngbin7334 -> 7282 bytes
-rw-r--r--tests/ref/markup/strong.pngbin2799 -> 2847 bytes
-rw-r--r--tests/ref/repr.pngbin10420 -> 10208 bytes
-rw-r--r--tests/ref/spacing.pngbin5455 -> 5494 bytes
-rw-r--r--tests/ref/text.pngbin1853 -> 1880 bytes
-rw-r--r--tests/typ/full/coma.typ2
-rw-r--r--tests/typ/library/box.typ12
-rw-r--r--tests/typ/repr.typ3
-rw-r--r--tests/typeset.rs2
38 files changed, 51 insertions, 37 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);
+ }
+}
diff --git a/tests/ref/comment.png b/tests/ref/comment.png
index 9cee51b6..1fad97fe 100644
--- a/tests/ref/comment.png
+++ b/tests/ref/comment.png
Binary files differ
diff --git a/tests/ref/control/for.png b/tests/ref/control/for.png
index f0d4a5cd..d04ea62c 100644
--- a/tests/ref/control/for.png
+++ b/tests/ref/control/for.png
Binary files differ
diff --git a/tests/ref/control/if.png b/tests/ref/control/if.png
index 04724e1f..99bde49e 100644
--- a/tests/ref/control/if.png
+++ b/tests/ref/control/if.png
Binary files differ
diff --git a/tests/ref/control/invalid.png b/tests/ref/control/invalid.png
index c9822eeb..ff4c6987 100644
--- a/tests/ref/control/invalid.png
+++ b/tests/ref/control/invalid.png
Binary files differ
diff --git a/tests/ref/control/let.png b/tests/ref/control/let.png
index 693a8d4f..5fb1c992 100644
--- a/tests/ref/control/let.png
+++ b/tests/ref/control/let.png
Binary files differ
diff --git a/tests/ref/control/while.png b/tests/ref/control/while.png
index 55a6ed80..890131f1 100644
--- a/tests/ref/control/while.png
+++ b/tests/ref/control/while.png
Binary files differ
diff --git a/tests/ref/expr/array.png b/tests/ref/expr/array.png
index 44331d9f..784553b3 100644
--- a/tests/ref/expr/array.png
+++ b/tests/ref/expr/array.png
Binary files differ
diff --git a/tests/ref/expr/block-invalid.png b/tests/ref/expr/block-invalid.png
index 11899d86..b380defc 100644
--- a/tests/ref/expr/block-invalid.png
+++ b/tests/ref/expr/block-invalid.png
Binary files differ
diff --git a/tests/ref/expr/block.png b/tests/ref/expr/block.png
index ffa59568..d5ad52ae 100644
--- a/tests/ref/expr/block.png
+++ b/tests/ref/expr/block.png
Binary files differ
diff --git a/tests/ref/expr/call-invalid.png b/tests/ref/expr/call-invalid.png
index 0d3783a8..88f13780 100644
--- a/tests/ref/expr/call-invalid.png
+++ b/tests/ref/expr/call-invalid.png
Binary files differ
diff --git a/tests/ref/expr/call.png b/tests/ref/expr/call.png
index 39941778..7197bb90 100644
--- a/tests/ref/expr/call.png
+++ b/tests/ref/expr/call.png
Binary files differ
diff --git a/tests/ref/expr/dict.png b/tests/ref/expr/dict.png
index 351e0498..28a7cb3b 100644
--- a/tests/ref/expr/dict.png
+++ b/tests/ref/expr/dict.png
Binary files differ
diff --git a/tests/ref/expr/ops.png b/tests/ref/expr/ops.png
index fb717dd0..95a24c0e 100644
--- a/tests/ref/expr/ops.png
+++ b/tests/ref/expr/ops.png
Binary files differ
diff --git a/tests/ref/full/coma.png b/tests/ref/full/coma.png
index ed849404..f5db682d 100644
--- a/tests/ref/full/coma.png
+++ b/tests/ref/full/coma.png
Binary files differ
diff --git a/tests/ref/library/box.png b/tests/ref/library/box.png
index e8513d70..2804f8e9 100644
--- a/tests/ref/library/box.png
+++ b/tests/ref/library/box.png
Binary files differ
diff --git a/tests/ref/library/font.png b/tests/ref/library/font.png
index 92b5b7fc..8e611b16 100644
--- a/tests/ref/library/font.png
+++ b/tests/ref/library/font.png
Binary files differ
diff --git a/tests/ref/library/hv.png b/tests/ref/library/hv.png
index 13a352a4..0842d409 100644
--- a/tests/ref/library/hv.png
+++ b/tests/ref/library/hv.png
Binary files differ
diff --git a/tests/ref/library/image.png b/tests/ref/library/image.png
index 70f263e6..af497c8d 100644
--- a/tests/ref/library/image.png
+++ b/tests/ref/library/image.png
Binary files differ
diff --git a/tests/ref/library/page.png b/tests/ref/library/page.png
index 1ddeeb3d..1537fad4 100644
--- a/tests/ref/library/page.png
+++ b/tests/ref/library/page.png
Binary files differ
diff --git a/tests/ref/library/pagebreak.png b/tests/ref/library/pagebreak.png
index dfb9dcaa..b1ee0eef 100644
--- a/tests/ref/library/pagebreak.png
+++ b/tests/ref/library/pagebreak.png
Binary files differ
diff --git a/tests/ref/markup/emph.png b/tests/ref/markup/emph.png
index aec7fefb..f002610e 100644
--- a/tests/ref/markup/emph.png
+++ b/tests/ref/markup/emph.png
Binary files differ
diff --git a/tests/ref/markup/escape.png b/tests/ref/markup/escape.png
index 54e61201..3fa44c6d 100644
--- a/tests/ref/markup/escape.png
+++ b/tests/ref/markup/escape.png
Binary files differ
diff --git a/tests/ref/markup/heading.png b/tests/ref/markup/heading.png
index b4aa1bbd..9f2ce6ec 100644
--- a/tests/ref/markup/heading.png
+++ b/tests/ref/markup/heading.png
Binary files differ
diff --git a/tests/ref/markup/linebreak.png b/tests/ref/markup/linebreak.png
index dda5efa6..fec65248 100644
--- a/tests/ref/markup/linebreak.png
+++ b/tests/ref/markup/linebreak.png
Binary files differ
diff --git a/tests/ref/markup/nbsp.png b/tests/ref/markup/nbsp.png
index ad7591ac..3e1f0ee7 100644
--- a/tests/ref/markup/nbsp.png
+++ b/tests/ref/markup/nbsp.png
Binary files differ
diff --git a/tests/ref/markup/raw.png b/tests/ref/markup/raw.png
index c0bf0160..ce833428 100644
--- a/tests/ref/markup/raw.png
+++ b/tests/ref/markup/raw.png
Binary files differ
diff --git a/tests/ref/markup/strong.png b/tests/ref/markup/strong.png
index cd6d670d..ac38c436 100644
--- a/tests/ref/markup/strong.png
+++ b/tests/ref/markup/strong.png
Binary files differ
diff --git a/tests/ref/repr.png b/tests/ref/repr.png
index 54a1d240..21d7af27 100644
--- a/tests/ref/repr.png
+++ b/tests/ref/repr.png
Binary files differ
diff --git a/tests/ref/spacing.png b/tests/ref/spacing.png
index a8086177..8bdc9885 100644
--- a/tests/ref/spacing.png
+++ b/tests/ref/spacing.png
Binary files differ
diff --git a/tests/ref/text.png b/tests/ref/text.png
index 31d0b45e..38ae364d 100644
--- a/tests/ref/text.png
+++ b/tests/ref/text.png
Binary files differ
diff --git a/tests/typ/full/coma.typ b/tests/typ/full/coma.typ
index 39404a35..d324627f 100644
--- a/tests/typ/full/coma.typ
+++ b/tests/typ/full/coma.typ
@@ -1,5 +1,5 @@
// Configuration with `page` and `font` functions.
-#page(width: 450pt, height: 380pt, margins: 1cm)
+#page(width: 450pt, margins: 1cm)
// There are variables and they can take normal values like strings, ...
#let city = "Berlin"
diff --git a/tests/typ/library/box.typ b/tests/typ/library/box.typ
index 10e2c93e..7ce56859 100644
--- a/tests/typ/library/box.typ
+++ b/tests/typ/library/box.typ
@@ -1,15 +1,15 @@
// Test the box function.
---
-#page("a7", flip: true)
+#page("a8", flip: true)
// Box with fixed width, should have text height.
-#box(width: 2cm, color: #9650D6)[A]
+#box(width: 2cm, color: #9650D6)[Legal]
Sometimes there is no box.
// Box with fixed height, should span line.
-#box(height: 2cm, width: 100%, color: #734CED)[B]
+#box(height: 1cm, width: 100%, color: #734CED)[B]
// Empty box with fixed width and height.
#box(width: 6cm, height: 12pt, color: #CB4CED)
@@ -18,6 +18,6 @@ Sometimes there is no box.
#box(width: 2in, color: #ff0000)
// These are in a row!
-#box(width: 1in, height: 10pt, color: #D6CD67)
-#box(width: 1in, height: 10pt, color: #EDD466)
-#box(width: 1in, height: 10pt, color: #E3BE62)
+#box(width: 0.5in, height: 10pt, color: #D6CD67)
+#box(width: 0.5in, height: 10pt, color: #EDD466)
+#box(width: 0.5in, height: 10pt, color: #E3BE62)
diff --git a/tests/typ/repr.typ b/tests/typ/repr.typ
index 6eead75e..96eb710e 100644
--- a/tests/typ/repr.typ
+++ b/tests/typ/repr.typ
@@ -32,9 +32,8 @@
{12e1pt} \
{2.5rad} \
{45deg} \
-
// Not in monospace via repr.
-#repr(45deg)
+#repr(45deg) \
---
// Colors.
diff --git a/tests/typeset.rs b/tests/typeset.rs
index c56655f5..232dfa5c 100644
--- a/tests/typeset.rs
+++ b/tests/typeset.rs
@@ -393,7 +393,7 @@ fn draw_text(env: &Env, canvas: &mut Canvas, pos: Point, shaped: &Shaped) {
let units_per_em = face.units_per_em().unwrap_or(1000);
let x = (pos.x + offset).to_pt() as f32;
- let y = (pos.y + shaped.font_size).to_pt() as f32;
+ let y = pos.y.to_pt() as f32;
let scale = (shaped.font_size / units_per_em as f64).to_pt() as f32;
let mut builder = WrappedPathBuilder(PathBuilder::new());