sile-typesetter/sile

Wrong position of sub/superscripts in math on big content

Closed this issue · 3 comments

Observed
(the square root comes from #2119, but this is orthogonal to the issue)

image
image

The exponents on "big" blocks (bracketed blocs with fractions, etc.) are really off.

Note

There's some commented out code in our implementation, let's check what restoring it does:

diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua
index ea58071e..18af78cb 100644
--- a/packages/math/base-elements.lua
+++ b/packages/math/base-elements.lua
@@ -610,7 +610,7 @@ function elements.subscript:shape ()
       self.sub.relX = self.width + subShift
       self.sub.relY = SILE.types.length(math.max(
          constants.subscriptShiftDown * scaleDown,
-         --self.base.depth + constants.subscriptBaselineDropMin * scaleDown,
+         (self.base.depth + constants.subscriptBaselineDropMin * scaleDown):tonumber(),
          (self.sub.height - constants.subscriptTopMax * scaleDown):tonumber()
       ))
       if self:is_a(elements.underOver) or self:is_a(elements.stackbox) or self.base.largeop then
@@ -629,7 +629,7 @@ function elements.subscript:shape ()
       self.sup.relY = SILE.types.length(math.max(
          isCrampedMode(self.mode) and constants.superscriptShiftUpCramped * scaleDown
             or constants.superscriptShiftUp * scaleDown, -- or cramped
-         --self.base.height - constants.superscriptBaselineDropMax * scaleDown,
+         (self.base.height - constants.superscriptBaselineDropMax * scaleDown):tonumber(),
          (self.sup.depth + constants.superscriptBottomMin * scaleDown):tonumber()
       )) * -1
       if self:is_a(elements.underOver) or self:is_a(elements.stackbox) or self.base.largeop then

Result:

image
image

--> Maybe can we bisect why this code was commented out? It seems it was doing something more or less expected!

Partly relates to #1799 (although the question was more general)

Ah, maybe those lines do adverse things in inline (non-display) math:

Current:
image

With the commented-out code reverted: The exponent is slightly raised and moves the interline...
image

Yet, the commented-out lines:

  • Were correct as per MathML Core §3.4.1.2 and §3.4.1.3 (Nov. 2023 Working Draft)
  • and TeMML is consistent with the output above when the code is restored, consistent too with MathML core
  • ... but MathJax apparently knows better (see below)

Bisected to a97792c = commented out by @OlivierNicole as part of changes "largely based on Ulrik Vieth's OpenType Math Illuminated."

Referenced document by Vieth found as PDF, see p. 49

  • SuperscriptBaselineDropMax (= TeX σ18) and SubscriptBaselineDropMin (= σ19) in table 5
  • Illustration on fig. 4, and subsequent discussion = σ18 and σ19 apply "on a boxed subformula" (and other cases not at stake here).

A "boxed subformula" is not defined in that document, but on fig. 4 and its caption it seems to be opposed to "a single character". Testing with {(k^2r^2)}^{1/3} i.e. ${(k^2r^2)}^{1/3}$

  • LaTeX raises the 1/3 but both 2 on k and r are at the same position
  • TeMML shows the 2 on k higher than the 2 on r (GitHub too, at least on my browser)
  • MathJax gives the same result as LaTeX... even for (k+1)^2r^2, and has the extra raising on e.g. {(k+1)}^2r^2 -- checking the generated MathML, it's the same... but with some different custom data- attributes... They might be cheating a bit, heh :)

Digging deeper, this TeX Stack Exchange discussion gives some more pointer.

Notably this TUGboat 27 no. 1 article by Jackowski, see esp. fig. 11 and discussion p. 89: the kernel is a "symbol", vs. a "boxed formula".

This is finicky 🤣

Anyway, the case for the kernel being a symbol is easy. I'll at least push it in #2151