Skip to content

Commit

Permalink
Merge pull request #2165 from Omikhleia/feat-bevelled-fractions
Browse files Browse the repository at this point in the history
feat(math): Support MathML bevelled fractions
  • Loading branch information
alerque authored Nov 13, 2024
2 parents 7e682e2 + 567ac54 commit 69cae1e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
59 changes: 58 additions & 1 deletion packages/math/base-elements.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1519,7 +1519,7 @@ function elements.sqrt:output (x, y, line)
local symbol = {
_r(self.radicalRuleThickness),
"w", -- line width
2,
1,
"j", -- round line joins
_r(sw + s0),
_r(self.extraAscender),
Expand Down Expand Up @@ -1594,6 +1594,63 @@ end

function elements.padded.output (_, _, _, _) end

-- Bevelled fractions are not part of MathML Core, and MathML4 does not
-- exactly specify how to compute the layout.
elements.bevelledFraction = pl.class(elements.fraction) -- Inherit from fraction
elements.fraction._type = "BevelledFraction"

function elements.bevelledFraction:shape ()
local constants = self:getMathMetrics().constants
local scaleDown = self:getScaleDown()
local hSkew = constants.skewedFractionHorizontalGap * scaleDown
-- OpenType has properties which are not totally explicit.
-- The definition of skewedFractionVerticalGap (and its value in fonts
-- such as Libertinus Math) seems to imply that it is measured from the
-- bottom of the numerator to the top of the denominator.
-- This does not seem to be a nice general layout.
-- So we will use superscriptShiftUp(Cramped) for the numerator:
local vSkewUp = isCrampedMode(self.mode) and constants.superscriptShiftUpCramped * scaleDown
or constants.superscriptShiftUp * scaleDown
-- And all good books say that the denominator should not be shifted down:
local vSkewDown = 0

self.ruleThickness = self.attributes.linethickness
and SU.cast("measurement", self.attributes.linethickness):tonumber()
or constants.fractionRuleThickness * scaleDown
self.numerator.relX = SILE.types.length(0)
self.numerator.relY = SILE.types.length(-vSkewUp)
self.denominator.relX = self.numerator.width + hSkew
self.denominator.relY = SILE.types.length(vSkewDown)
self.width = self.numerator.width + self.denominator.width + hSkew
self.height = maxLength(self.numerator.height + vSkewUp, self.denominator.height - vSkewDown)
self.depth = maxLength(self.numerator.depth - vSkewUp, self.denominator.depth + vSkewDown)
self.barWidth = SILE.types.length(hSkew)
self.barX = self.numerator.relX + self.numerator.width
end

function elements.bevelledFraction:output (x, y, line)
local h = self.height:tonumber()
local d = self.depth:tonumber()
local barwidth = scaleWidth(self.barWidth, line):tonumber()
local xscaled = scaleWidth(x + self.barX, line)
local rd = self.ruleThickness / 2
local symbol = {
_r(self.ruleThickness),
"w", -- line width
1,
"J", -- round line caps
_r(0),
_r(d + h - rd),
"m",
_r(barwidth),
_r(rd),
"l",
"S",
}
local svg = table.concat(symbol, " ")
SILE.outputter:drawSVG(svg, xscaled, y, barwidth, h, 1)
end

elements.mathMode = mathMode
elements.atomType = atomType
elements.symbolDefaults = symbolDefaults
Expand Down
4 changes: 3 additions & 1 deletion packages/math/typesetter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ function ConvertMathML (_, content)
if #children ~= 2 then
SU.error("Wrong number of children in mfrac: " .. #children)
end
return b.fraction(content.options, children[1], children[2])
return SU.boolean(content.options.bevelled, false)
and b.bevelledFraction(content.options, children[1], children[2])
or 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

0 comments on commit 69cae1e

Please sign in to comment.