Adjust attach() per TeXbook Appendix G 18a (#1129)
@ -299,6 +299,7 @@ fn compute_shifts_up_and_down(
|
||||
|
||||
let mut shift_up = Abs::zero();
|
||||
let mut shift_down = Abs::zero();
|
||||
let is_char_box = is_character_box(base);
|
||||
|
||||
for e in [tl, tr].into_iter().flatten() {
|
||||
let ascent = match &base {
|
||||
@ -308,13 +309,13 @@ fn compute_shifts_up_and_down(
|
||||
|
||||
shift_up = shift_up
|
||||
.max(sup_shift_up)
|
||||
.max(ascent - sup_drop_max)
|
||||
.max(if is_char_box { Abs::zero() } else { ascent - sup_drop_max })
|
||||
.max(sup_bottom_min + e.descent());
|
||||
}
|
||||
for e in [bl, br].into_iter().flatten() {
|
||||
shift_down = shift_down
|
||||
.max(sub_shift_down)
|
||||
.max(base.descent() + sub_drop_min)
|
||||
.max(if is_char_box { Abs::zero() } else { base.descent() + sub_drop_min })
|
||||
.max(e.ascent() - sub_top_max);
|
||||
}
|
||||
|
||||
@ -339,6 +340,27 @@ fn compute_shifts_up_and_down(
|
||||
(shift_up, shift_down)
|
||||
}
|
||||
|
||||
/// Whether the fragment consists of a single character or atomic piece of text.
|
||||
fn is_character_box(fragment: &MathFragment) -> bool {
|
||||
match fragment {
|
||||
MathFragment::Glyph(_) | MathFragment::Variant(_) => {
|
||||
fragment.class() != Some(MathClass::Large)
|
||||
}
|
||||
MathFragment::Frame(fragment) => is_atomic_text_frame(&fragment.frame),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles e.g. "sin", "log", "exp", "CustomOperator".
|
||||
fn is_atomic_text_frame(frame: &Frame) -> bool {
|
||||
// Meta information isn't visible or renderable, so we exclude it.
|
||||
let mut iter = frame
|
||||
.items()
|
||||
.map(|(_, item)| item)
|
||||
.filter(|item| !matches!(item, FrameItem::Meta(_, _)));
|
||||
matches!(iter.next(), Some(FrameItem::Text(_))) && iter.next().is_none()
|
||||
}
|
||||
|
||||
/// Unicode codepoints that should have sub- and superscripts attached as limits.
|
||||
#[rustfmt::skip]
|
||||
const LIMITS: &[char] = &[
|
||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 53 KiB |
@ -68,6 +68,16 @@ $ sqrt(a_(1/2)^zeta), sqrt(a_alpha^(1/2)), sqrt(a_(1/2)^(3/4)) \
|
||||
// Test frame base.
|
||||
$ (-1)^n + (1/2 + 3)^(-1/2) $
|
||||
|
||||
---
|
||||
#set text(size: 8pt)
|
||||
|
||||
// Test that the attachments are aligned horizontally.
|
||||
$ x_1 p_1 frak(p)_1 2_1 dot_1 lg_1 !_1 \\_1 ]_1 "ip"_1 op("iq")_1 \
|
||||
x^1 b^1 frak(b)^1 2^1 dot^1 lg^1 !^1 \\^1 ]^1 "ib"^1 op("id")^1 \
|
||||
x_1 y_1 "_"_1 x^1 l^1 "`"^1 attach(I,tl:1,bl:1,tr:1,br:1)
|
||||
scripts(sum)_1^1 integral_1^1 |1/2|_1^1 \
|
||||
x^1_1, "("b y")"^1_1 != (b y)^1_1, "[∫]"_1 [integral]_1 $
|
||||
|
||||
---
|
||||
// Test limit.
|
||||
$ lim_(n->oo \ n "grows") sum_(k=0 \ k in NN)^n k $
|
||||
|