Skip to content

Commit d579096

Browse files
Omikhleiaalerque
authored andcommitted
feat(math): Support MathML mpadded and refactor TeX-like phantoms
Nothing really complex with mpadded.. Wait some ambiguity if dimensions are in a font-relative unit (see in-code comment), but let's move forward anyway -- and on the same occasion, remove the non-standard approach previously used for (La)TeX's phantom, hphantom and vphantom.
1 parent e0559e8 commit d579096

3 files changed

Lines changed: 52 additions & 19 deletions

File tree

packages/math/base-elements.lua

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ function elements.stackbox.output (_, _, _, _) end
468468
elements.phantom = pl.class(elements.stackbox) -- inherit from stackbox
469469
elements.phantom._type = "Phantom"
470470

471-
function elements.phantom:_init (children, special)
471+
function elements.phantom:_init (children)
472472
-- MathML core 3.3.7:
473473
-- "Its layout algorithm is the same as the mrow element".
474474
-- Also not the MathML states that <mphantom> is sort of legacy, "implemented
@@ -477,22 +477,6 @@ function elements.phantom:_init (children, special)
477477
-- The thing is that we don't have CSS in SILE, so supporting <mphantom> is
478478
-- a must.
479479
elements.stackbox._init(self, "H", children)
480-
self.special = special
481-
end
482-
483-
function elements.phantom:shape ()
484-
elements.stackbox.shape(self)
485-
-- From https://latexref.xyz:
486-
-- "The \vphantom variant produces an invisible box with the same vertical size
487-
-- as subformula, the same height and depth, but having zero width.
488-
-- And \hphantom makes a box with the same width as subformula but
489-
-- with zero height and depth."
490-
if self.special == "v" then
491-
self.width = SILE.types.length()
492-
elseif self.special == "h" then
493-
self.height = SILE.types.length()
494-
self.depth = SILE.types.length()
495-
end
496480
end
497481

498482
function elements.phantom:output (_, _, _)
@@ -1454,6 +1438,50 @@ function elements.sqrt:output (x, y, line)
14541438
)
14551439
end
14561440

1441+
elements.padded = pl.class(elements.mbox)
1442+
elements.padded._type = "Padded"
1443+
1444+
function elements.padded:__tostring ()
1445+
return self._type .. "(" .. tostring(self.impadded) .. ")"
1446+
end
1447+
1448+
function elements.padded:_init (attributes, impadded)
1449+
elements.mbox._init(self)
1450+
self.impadded = impadded
1451+
self.attributes = attributes or {}
1452+
table.insert(self.children, impadded)
1453+
end
1454+
1455+
function elements.padded:styleChildren ()
1456+
self.impadded.mode = self.mode
1457+
end
1458+
1459+
function elements.padded:shape ()
1460+
-- TODO MathML allows percentages font-relative units (em, ex) for padding
1461+
-- But our units work with font.size, not math.font.size (possibly adjusted by scaleDown)
1462+
-- so the expectations might not be met.
1463+
local width = self.attributes.width and SU.cast("measurement", self.attributes.width)
1464+
local height = self.attributes.height and SU.cast("measurement", self.attributes.height)
1465+
local depth = self.attributes.depth and SU.cast("measurement", self.attributes.depth)
1466+
local lspace = self.attributes.lspace and SU.cast("measurement", self.attributes.lspace)
1467+
local voffset = self.attributes.voffset and SU.cast("measurement", self.attributes.voffset)
1468+
-- Clamping for width, height, depth, lspace
1469+
width = width and (width:tonumber() > 0 and width or SILE.types.measurement())
1470+
height = height and (height:tonumber() > 0 and height or SILE.types.measurement())
1471+
depth = depth and (depth:tonumber() > 0 and depth or SILE.types.measurement())
1472+
lspace = lspace and (lspace:tonumber() > 0 and lspace or SILE.types.measurement())
1473+
-- No clamping for voffset
1474+
voffset = voffset or SILE.types.measurement(0)
1475+
-- Compute the dimensions
1476+
self.width = width and SILE.types.length(width) or self.impadded.width
1477+
self.height = height and SILE.types.length(height) or self.impadded.height
1478+
self.depth = depth and SILE.types.length(depth) or self.impadded.depth
1479+
self.impadded.relX = lspace and SILE.types.length(lspace) or SILE.types.length()
1480+
self.impadded.relY = voffset and SILE.types.length(voffset):negate() or SILE.types.length()
1481+
end
1482+
1483+
function elements.padded.output (_, _, _, _) end
1484+
14571485
elements.mathMode = mathMode
14581486
elements.atomType = atomType
14591487
elements.symbolDefaults = symbolDefaults

packages/math/texlike.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -656,8 +656,9 @@ compileToMathML(
656656
657657
% Phantom commands from TeX/LaTeX
658658
\def{phantom}{\mphantom{#1}}
659-
\def{hphantom}{\mphantom[special=h]{#1}}
660-
\def{vphantom}{\mphantom[special=v]{#1}}
659+
\def{hphantom}{\mpadded[height=0, depth=0]{\mphantom{#1}}}
660+
\def{vphantom}{\mpadded[width=0]{\mphantom{#1}}}
661+
%\mphantom[special=v]{#1}}}
661662
]==],
662663
})
663664
)

packages/math/typesetter.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ function ConvertMathML (_, content)
177177
-- It's an mrow, but with some style attributes that we ignore.
178178
SU.warn("MathML mstyle is not fully supported yet")
179179
return b.stackbox("H", convertChildren(content))
180+
elseif content.command == "mpadded" then
181+
-- MathML Core 3.3.6.1: The <mpadded> element generates an anonymous <mrow> box
182+
-- called the "impadded inner box"
183+
return b.padded(content.options, b.stackbox("H", convertChildren(content)))
180184
else
181185
SU.error("Unknown math command " .. content.command)
182186
end

0 commit comments

Comments
 (0)