Don't hang quotes

This commit is contained in:
Laurenz 2022-04-13 11:24:42 +02:00
parent 072543fc59
commit 002b6c5b3e
6 changed files with 29 additions and 53 deletions

View File

@ -497,16 +497,6 @@ fn prepare<'a>(
} }
}, },
Segment::Node(node) => { Segment::Node(node) => {
// Prevent margin overhang in the inline node except if there's
// just this one.
let local;
let styles = if par.0.len() != 1 {
local = StyleMap::with(TextNode::OVERHANG, false);
local.chain(&styles)
} else {
styles
};
let size = Size::new(regions.first.x, regions.base.y); let size = Size::new(regions.first.x, regions.base.y);
let pod = Regions::one(size, regions.base, Spec::splat(false)); let pod = Regions::one(size, regions.base, Spec::splat(false));
let frame = node.layout(ctx, &pod, styles)?.remove(0); let frame = node.layout(ctx, &pod, styles)?.remove(0);
@ -994,9 +984,11 @@ fn commit(
// Handle hanging punctuation to the left. // Handle hanging punctuation to the left.
if let Some(Item::Text(text)) = reordered.first() { if let Some(Item::Text(text)) = reordered.first() {
if let Some(glyph) = text.glyphs.first() { if let Some(glyph) = text.glyphs.first() {
if text.styles.get(TextNode::OVERHANG) { if !text.dir.is_positive()
let start = text.dir.is_positive(); && text.styles.get(TextNode::OVERHANG)
let amount = overhang(glyph.c, start) * glyph.x_advance.at(text.size); && (reordered.len() > 1 || text.glyphs.len() > 1)
{
let amount = overhang(glyph.c) * glyph.x_advance.at(text.size);
offset -= amount; offset -= amount;
remaining += amount; remaining += amount;
} }
@ -1006,11 +998,11 @@ fn commit(
// Handle hanging punctuation to the right. // Handle hanging punctuation to the right.
if let Some(Item::Text(text)) = reordered.last() { if let Some(Item::Text(text)) = reordered.last() {
if let Some(glyph) = text.glyphs.last() { if let Some(glyph) = text.glyphs.last() {
if text.styles.get(TextNode::OVERHANG) if text.dir.is_positive()
&& text.styles.get(TextNode::OVERHANG)
&& (reordered.len() > 1 || text.glyphs.len() > 1) && (reordered.len() > 1 || text.glyphs.len() > 1)
{ {
let start = !text.dir.is_positive(); let amount = overhang(glyph.c) * glyph.x_advance.at(text.size);
let amount = overhang(glyph.c, start) * glyph.x_advance.at(text.size);
remaining += amount; remaining += amount;
} }
} }
@ -1110,24 +1102,19 @@ fn reorder<'a>(line: &'a Line<'a>) -> Vec<&'a Item<'a>> {
reordered reordered
} }
/// How much a character should hang into the margin. /// How much a character should hang into the end margin.
/// ///
/// For selection of overhang characters, see also: /// For more discussion, see:
/// https://recoveringphysicist.com/21/ /// https://recoveringphysicist.com/21/
fn overhang(c: char, start: bool) -> f64 { fn overhang(c: char) -> f64 {
match c { match c {
'“' | '”' | '„' | '‟' | '"' if start => 1.0, // Dashes.
'' | '' | '' | '' | '\'' if start => 1.0, '' | '—' => 0.2,
'-' => 0.55,
'“' | '”' | '„' | '‟' | '"' if !start => 0.6,
'' | '' | '' | '' | '\'' if !start => 0.6,
'' | '—' if !start => 0.2,
'-' if !start => 0.55,
// Punctuation.
'.' | ',' => 0.8, '.' | ',' => 0.8,
':' | ';' => 0.3, ':' | ';' => 0.3,
'«' | '»' => 0.2,
'' | '' => 0.4,
// Arabic and Ideographic // Arabic and Ideographic
'\u{60C}' | '\u{6D4}' => 0.4, '\u{60C}' | '\u{6D4}' => 0.4,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,34 +1,23 @@
// Test micro-typographical shenanigans. // Test micro-typographical shenanigans.
--- ---
// Test that overhang is off by default in boxes. // Test hanging punctuation.
A#box["]B #set page(width: 130pt, margins: 15pt)
#set par(justify: true, linebreaks: "simple")
#set text(lang: "en", size: 9pt)
#rect(fill: rgb(repr(teal) + "00"), width: 100%)[
This is a little bit of text that builds up to
hang-ing hyphens and dash---es and then, you know,
some punctuation in the margin.
]
--- // Test hanging punctuation with RTL.
// Test justified quotes. #set text(lang: "he")
#set par(justify: true) בנייה נכונה של משפטים ארוכים דורשת ידע בשפה. אז בואו נדבר על מזג האוויר.
“A quote that hangs a bit into the margin.” \
--- somebody
---
// Test fancy quotes in the left margin.
#set par(align: right)
»Book quotes are even smarter.« \
Book quotes are even smarter. \
---
// Test fancy quotes in the right margin.
#set par(align: left)
«Book quotes are even smarter.» \
Book quotes are even smarter. \
---
#set text(lang: "ar", "Noto Sans Arabic", "IBM Plex Sans")
"المطر هو الحياة" \
المطر هو الحياة
--- ---
// Test that lone punctuation doesn't overhang into the margin. // Test that lone punctuation doesn't overhang into the margin.
#set page(margins: 0pt) #set page(margins: 0pt)
#set par(align: right) #set par(align: end)
#set text(dir: rtl)
: :