Skip to content

Commit

Permalink
Merge pull request #2151 from Omikhleia/math-more-fixes-and-features
Browse files Browse the repository at this point in the history
Math more fixes and features
  • Loading branch information
alerque authored Nov 2, 2024
2 parents da1829c + ef249c3 commit 21bcc5c
Show file tree
Hide file tree
Showing 11 changed files with 660 additions and 398 deletions.
328 changes: 242 additions & 86 deletions packages/math/base-elements.lua

Large diffs are not rendered by default.

111 changes: 101 additions & 10 deletions packages/math/texlike.lua
Original file line number Diff line number Diff line change
Expand Up @@ -260,23 +260,40 @@ local compileToStr = function (argEnv, mathlist)
end
end

local function isBigOperator (tree)
local function isOperatorKind (tree, typeOfAtom, typeOfSymbol)
if not tree then
return false -- safeguard
end
if tree.command ~= "mo" then
return false
end
-- Case \mo[atom=big]{ops}
-- E.g. \mo[atom=big]{lim}
if tree.options and tree.options.atom == "big" then
if tree.options and tree.options.atom == typeOfAtom then
return true
end
-- Case \mo{ops} where ops is registered as big operator (unicode-symbols)
-- Case \mo{ops} where ops is registered with the resquested type
-- E.g. \mo{∑) or \sum
if tree[1] and symbolDefaults[tree[1]] and symbolDefaults[tree[1]].atom == atomType.bigOperator then
if tree[1] and symbolDefaults[tree[1]] and symbolDefaults[tree[1]].atom == typeOfSymbol then
return true
end
return false
end

local function isBigOperator (tree)
return isOperatorKind(tree, "big", atomType.bigOperator)
end
local function isCloseOperator (tree)
return isOperatorKind(tree, "close", atomType.closeSymbol)
end
local function isOpeningOperator (tree)
return isOperatorKind(tree, "open", atomType.openingSymbol)
end

local function isAccentSymbol (symbol)
return symbolDefaults[symbol] and symbolDefaults[symbol].atom == atomType.accentSymbol
end

local function compileToMathML_aux (_, arg_env, tree)
if type(tree) == "string" then
return tree
Expand Down Expand Up @@ -323,12 +340,56 @@ local function compileToMathML_aux (_, arg_env, tree)
-- Turn mathlist into `mrow` except if it has exactly one `mtr` or `mtd`
-- child.
-- Note that `def`s have already been compiled away at this point.
if #tree == 1 and (tree[1].command == "mtr" or tree[1].command == "mtd") then
return tree[1]
if #tree == 1 then
if tree[1].command == "mtr" or tree[1].command == "mtd" then
return tree[1]
else
tree.command = "mrow"
end
else
-- Re-wrap content from opening to closing operator in an implicit mrow,
-- so stretchy operators apply to the correct span of content.
local children = {}
local stack = {}
for _, child in ipairs(tree) do
if isOpeningOperator(child) then
table.insert(stack, children)
local mrow = {
command = "mrow",
options = {},
child,
}
table.insert(children, mrow)
children = mrow
elseif isCloseOperator(child) then
table.insert(children, child)
if #stack > 0 then
children = table.remove(stack)
end
elseif
(child.command == "msubsup" or child.command == "msub" or child.command == "msup")
and isCloseOperator(child[1]) -- child[1] is the base
then
if #stack > 0 then
-- Special case for closing operator with sub/superscript:
-- (....)^i must be interpreted as {(....)}^i, not as (...{)}^i
-- Push the closing operator into the mrow
table.insert(children, child[1])
-- Move the mrow into the msubsup, replacing the closing operator
child[1] = children
-- And insert the msubsup into the parent
children = table.remove(stack)
children[#children] = child
else
table.insert(children, child)
end
else
table.insert(children, child)
end
end
tree = #stack > 0 and stack[1] or children
tree.command = "mrow"
end
tree.command = "mrow"
elseif tree.id == "atom" then
local codepoints = {}
for _, cp in luautf8.codes(tree[1]) do
Expand Down Expand Up @@ -424,7 +485,36 @@ local function compileToMathML_aux (_, arg_env, tree)
return res
elseif tree.id == "command" and symbols[tree.command] then
local atom = { id = "atom", [1] = symbols[tree.command] }
tree = compileToMathML_aux(nil, arg_env, atom)
if isAccentSymbol(symbols[tree.command]) and #tree > 0 then
-- LaTeX-style accents \vec{v} = <mover accent="true"><mi>v</mi><mo>→</mo></mover>
local accent = {
id = "command",
command = "mover",
options = {
accent = "true",
},
}
accent[1] = compileToMathML_aux(nil, arg_env, tree[1])
accent[2] = compileToMathML_aux(nil, arg_env, atom)
tree = accent
elseif #tree > 0 then
-- Play cool with LaTeX-style commands that don't take arguments:
-- Edge case for non-accent symbols so we don't loose bracketed groups
-- that might have been seen as command arguments.
-- Ex. \langle{x}\rangle (without space after \langle)
local sym = compileToMathML_aux(nil, arg_env, atom)
-- Compile all children in-place
for i, child in ipairs(tree) do
tree[i] = compileToMathML_aux(nil, arg_env, child)
end
-- Insert symbol at the beginning,
-- And add a wrapper mrow to be unwrapped in the parent.
table.insert(tree, 1, sym)
tree.command = "mrow"
tree.id = "wrapper"
else
tree = compileToMathML_aux(nil, arg_env, atom)
end
elseif tree.id == "argument" then
if arg_env[tree.index] then
return arg_env[tree.index]
Expand Down Expand Up @@ -566,8 +656,9 @@ compileToMathML(
% Phantom commands from TeX/LaTeX
\def{phantom}{\mphantom{#1}}
\def{hphantom}{\mphantom[special=h]{#1}}
\def{vphantom}{\mphantom[special=v]{#1}}
\def{hphantom}{\mpadded[height=0, depth=0]{\mphantom{#1}}}
\def{vphantom}{\mpadded[width=0]{\mphantom{#1}}}
%\mphantom[special=v]{#1}}}
]==],
})
)
Expand Down
31 changes: 29 additions & 2 deletions packages/math/typesetter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,24 @@ local function convertChildren (tree)
return mboxes
end

local function convertFirstChild (tree)
-- We need to loop until the first non-nil box is found, because
-- we may have blank lines in the tree.
for _, n in ipairs(tree) do
local box = ConvertMathML(nil, n)
if box then
return box
end
end
end

-- convert MathML into mbox
function ConvertMathML (_, content)
if content == nil or content.command == nil then
return nil
end
if content.command == "math" or content.command == "mathml" then -- toplevel
return b.stackbox("V", convertChildren(content))
return b.stackbox("H", convertChildren(content))
elseif content.command == "mrow" then
return b.stackbox("H", convertChildren(content))
elseif content.command == "mphantom" then
Expand All @@ -61,11 +72,16 @@ function ConvertMathML (_, content)
or scriptType.upright
local text = content[1]
local attributes = {}
-- Attributes from the (default) oerator table
if syms.symbolDefaults[text] then
for attribute, value in pairs(syms.symbolDefaults[text]) do
attributes[attribute] = value
end
end
-- Overwrite with attributes from the element
for attribute, value in pairs(content.options) do
attributes[attribute] = value
end
if content.options.atom then
if not atomTypeShort[content.options.atom] then
SU.error("Unknown atom type " .. content.options.atom)
Expand Down Expand Up @@ -131,7 +147,7 @@ function ConvertMathML (_, content)
if #children ~= 2 then
SU.error("Wrong number of children in mfrac: " .. #children)
end
return b.fraction(children[1], children[2])
return b.fraction(content.options, children[1], children[2])
elseif content.command == "msqrt" then
local children = convertChildren(content)
-- "The <msqrt> element generates an anonymous <mrow> box called the msqrt base
Expand Down Expand Up @@ -159,6 +175,17 @@ function ConvertMathML (_, content)
-- There's also some explanations about CSS, italic correction etc. which we ignore too.
text = text:gsub("[\n\r]", " ")
return b.text("string", {}, scriptType.upright, text:gsub("%s+", " "))
elseif content.command == "maction" then
-- MathML Core 3.6: display as mrow, ignoring all but the first child
return b.stackbox("H", { convertFirstChild(content) })
elseif content.command == "mstyle" then
-- It's an mrow, but with some style attributes that we ignore.
SU.warn("MathML mstyle is not fully supported yet")
return b.stackbox("H", convertChildren(content))
elseif content.command == "mpadded" then
-- MathML Core 3.3.6.1: The <mpadded> element generates an anonymous <mrow> box
-- called the "impadded inner box"
return b.padded(content.options, b.stackbox("H", convertChildren(content)))
else
SU.error("Unknown math command " .. content.command)
end
Expand Down
56 changes: 25 additions & 31 deletions tests/bug-1495-inline-math-layout.expected
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,11 @@ T 30 w=6.4800 (nil)
Mx 217.4262
T 68 80 84 w=13.2200 (nil)
Mx 230.6462
Mx 2.8200
T 9 a=3.5600 (nil)
T 9 w=3.5600 (nil)
Mx 234.2062
T 3421 w=5.9100 (nil)
Mx 240.1162
Mx 2.8200
T 10 a=3.5600 (nil)
T 10 w=3.5600 (nil)
Mx 247.3974
T 30 w=6.4800 (nil)
Mx 257.5986
Expand All @@ -88,53 +86,49 @@ My 52.6701
T 87 68 72 w=12.6514 (tae)
Mx 27.5333
T 17 w=2.2900 (.)
Mx 32.4913
Mx 32.7068
T 48 68 72 70 72 81 68 86 w=40.2295 (Maecenas)
Mx 75.3888
Mx 75.8198
T 89 72 81 72 81 68 87 76 86 w=39.8096 (venenatis)
Mx 117.8663
Mx 118.5129
T 88 79 87 85 76 70 72 86 w=30.9717 (ultrices)
Mx 148.8380
Mx 149.4846
T 17 w=2.2900 (.)
Mx 153.7961
Mx 154.6581
T 51 75 68 86 72 79 79 88 86 w=38.3984 (Phasellus)
Mx 194.8625
Mx 195.9401
Set font Libertinus Math;10;400;Regular;normal;;;LTR
T 2750 w=3.8100 (nil)
Mx 198.6725
Mx 199.7501
My 49.5701
Set font Libertinus Math;8;400;Regular;normal;;;LTR
T 2753 w=1.8320 (nil)
Mx 200.5045
Mx 201.5821
T 3413 w=3.5152 (nil)
Mx 207.2916
Mx 208.9129
My 52.6701
Set font Libertinus Math;10;400;Regular;normal;;;LTR
T 30 w=6.4800 (nil)
Mx 216.6135
Mx 218.7785
T 68 80 84 w=13.2200 (nil)
Mx 229.8335
Mx 3.0000
T 3798 a=4.2100 (nil)
Mx 234.0435
Mx 231.9985
T 9 w=3.5600 (nil)
Mx 235.5585
T 3413 w=4.5600 (nil)
Mx 238.6035
Mx 2.9900
T 3799 a=4.2100 (nil)
Mx 245.0614
Mx 240.1185
T 10 w=3.5600 (nil)
Mx 246.1439
T 12 w=6.4800 (nil)
Mx 253.7892
Mx 255.0892
T 2753 w=2.2900 (nil)
Mx 257.7459
Mx 259.0459
T 84 74 79 w=12.0300 (nil)
Mx 269.7759
Mx 3.0000
T 3798 a=4.2100 (nil)
Mx 273.9859
Mx 271.0759
T 9 w=3.5600 (nil)
Mx 274.6359
T 3413 w=4.5600 (nil)
Mx 278.5459
Mx 2.9900
T 3799 a=4.2100 (nil)
Mx 279.1959
T 10 w=3.5600 (nil)
Mx 14.8819
My 64.6701
Set font Gentium Plus;10;400;;normal;;;LTR
Expand Down
Loading

0 comments on commit 21bcc5c

Please sign in to comment.