Skip to content

Commit e0559e8

Browse files
Omikhleiaalerque
authored andcommitted
fix(math): Support linethickness attribute on MathML mfrac
In particular, in most MathML examples, tests, or results from other converters, a zero line thickness is used for binomial coefficients and stacked subscript/superscript on big operators such as sums, etc.
1 parent 59f4bfd commit e0559e8

2 files changed

Lines changed: 24 additions & 12 deletions

File tree

packages/math/base-elements.lua

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,10 +1054,11 @@ function elements.fraction:__tostring ()
10541054
return self._type .. "(" .. tostring(self.numerator) .. ", " .. tostring(self.denominator) .. ")"
10551055
end
10561056

1057-
function elements.fraction:_init (numerator, denominator)
1057+
function elements.fraction:_init (attributes, numerator, denominator)
10581058
elements.mbox._init(self)
10591059
self.numerator = numerator
10601060
self.denominator = denominator
1061+
self.attributes = attributes
10611062
table.insert(self.children, numerator)
10621063
table.insert(self.children, denominator)
10631064
end
@@ -1069,12 +1070,12 @@ end
10691070

10701071
function elements.fraction:shape ()
10711072
-- MathML Core 3.3.2: "To avoid visual confusion between the fraction bar
1072-
-- and another adjacent items (e.g. minus sign or another fraction's bar),"
1073-
-- By convention, here we use 1px = 1/96in = 0.75pt.
1073+
-- and another adjacent items (e.g. minus sign or another fraction's bar),
1074+
-- a default 1-pixel space is added around the element."
10741075
-- Note that PlainTeX would likely use \nulldelimiterspace (default 1.2pt)
10751076
-- but it would depend on the surrounding context, and might be far too
10761077
-- much in some cases, so we stick to MathML's suggested padding.
1077-
self.padding = SILE.types.length(0.75)
1078+
self.padding = SILE.types.length("1px"):absolute()
10781079

10791080
-- Determine relative abscissas and width
10801081
local widest, other
@@ -1090,7 +1091,16 @@ function elements.fraction:shape ()
10901091
local constants = self:getMathMetrics().constants
10911092
local scaleDown = self:getScaleDown()
10921093
self.axisHeight = constants.axisHeight * scaleDown
1093-
self.ruleThickness = constants.fractionRuleThickness * scaleDown
1094+
self.ruleThickness = self.attributes.linethickness
1095+
and SU.cast("measurement", self.attributes.linethickness):tonumber()
1096+
or constants.fractionRuleThickness * scaleDown
1097+
1098+
-- MathML Core 3.3.2.2 ("Fraction with zero line thickness") uses
1099+
-- stack(DisplayStyle)GapMin, stackTop(DisplayStyle)ShiftUp and stackBottom(DisplayStyle)ShiftDown.
1100+
-- TODO not implemented
1101+
-- The most common use cases for zero line thickness are:
1102+
-- - Binomial coefficients
1103+
-- - Stacked subscript/superscript on big operators such as sums.
10941104

10951105
local numeratorGapMin, denominatorGapMin, numeratorShiftUp, denominatorShiftDown
10961106
if isDisplayMode(self.mode) then
@@ -1126,12 +1136,14 @@ function elements.fraction:shape ()
11261136
end
11271137

11281138
function elements.fraction:output (x, y, line)
1129-
SILE.outputter:drawRule(
1130-
scaleWidth(x + self.padding, line),
1131-
y.length - self.axisHeight - self.ruleThickness / 2,
1132-
scaleWidth(self.width - 2 * self.padding, line),
1133-
self.ruleThickness
1134-
)
1139+
if self.ruleThickness > 0 then
1140+
SILE.outputter:drawRule(
1141+
scaleWidth(x + self.padding, line),
1142+
y.length - self.axisHeight - self.ruleThickness / 2,
1143+
scaleWidth(self.width - 2 * self.padding, line),
1144+
self.ruleThickness
1145+
)
1146+
end
11351147
end
11361148

11371149
local function newSubscript (spec)

packages/math/typesetter.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ function ConvertMathML (_, content)
142142
if #children ~= 2 then
143143
SU.error("Wrong number of children in mfrac: " .. #children)
144144
end
145-
return b.fraction(children[1], children[2])
145+
return b.fraction(content.options, children[1], children[2])
146146
elseif content.command == "msqrt" then
147147
local children = convertChildren(content)
148148
-- "The <msqrt> element generates an anonymous <mrow> box called the msqrt base

0 commit comments

Comments
 (0)