From 9ce5271c2114bd3c3d562f47e6bfe1aa6df2a752 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Fri, 25 Oct 2024 21:06:31 +0200 Subject: [PATCH 01/17] fix(math): Default table row/column spacing must depend on the math font size I don't really mind us using the (non-Core) rowspacing and columnspacing attributes, but the default values must be a ratio of the current math font size, not some hard-coded value in pt. --- packages/math/base-elements.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index a2401ae01..caa309d73 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -1180,9 +1180,9 @@ function elements.table:_init (children, options) return #row.children end, self.children))) SU.debug("math", "self.ncols =", self.ncols) - self.rowspacing = self.options.rowspacing and SILE.types.length(self.options.rowspacing) or SILE.types.length("7pt") - self.columnspacing = self.options.columnspacing and SILE.types.length(self.options.columnspacing) - or SILE.types.length("6pt") + local spacing = SILE.settings:get("math.font.size") * 0.6 -- arbitrary ratio of the current math font size + self.rowspacing = self.options.rowspacing and SILE.types.length(self.options.rowspacing) or spacing + self.columnspacing = self.options.columnspacing and SILE.types.length(self.options.columnspacing) or spacing -- Pad rows that do not have enough cells by adding cells to the -- right. for i, row in ipairs(self.children) do From 0df93b1654e0da448ef70bec31bba88b4a0497b1 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Fri, 25 Oct 2024 21:14:59 +0200 Subject: [PATCH 02/17] feat(math): Support MathML maction (basic) and mstyle (partial) Legit MathML elements for which a naive implementation is better than nothing and paves the way to check other more important elements from the MathML test suite. --- packages/math/typesetter.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/math/typesetter.lua b/packages/math/typesetter.lua index 78d435fde..8f2a3d82c 100644 --- a/packages/math/typesetter.lua +++ b/packages/math/typesetter.lua @@ -34,6 +34,17 @@ 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 @@ -159,6 +170,13 @@ 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)) else SU.error("Unknown math command " .. content.command) end From 4bbeaa64209103c7014b945151c103c615276530 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sat, 26 Oct 2024 02:14:04 +0200 Subject: [PATCH 03/17] fix(math): Paired open/close atoms shall be forced in a mrow in TeX-like math So that stretching occurs on the relevant spans of content. --- packages/math/texlike.lua | 71 +++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/packages/math/texlike.lua b/packages/math/texlike.lua index 618884b97..77f241ced 100644 --- a/packages/math/texlike.lua +++ b/packages/math/texlike.lua @@ -260,23 +260,36 @@ 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 compileToMathML_aux (_, arg_env, tree) if type(tree) == "string" then return tree @@ -323,12 +336,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 From f4c513ad5f1ca37235d391085796fa98a1ffb372 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sat, 26 Oct 2024 02:47:09 +0200 Subject: [PATCH 04/17] fix(math): Handle LaTeX-like math top accent commands correctly One wants `\vec{v}`, `\hat{n}` etc. to result in proper stacking of the corresponding symbol over the argument, instead of the symbol alone and the argument being lost :) --- packages/math/texlike.lua | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/math/texlike.lua b/packages/math/texlike.lua index 77f241ced..1895092ed 100644 --- a/packages/math/texlike.lua +++ b/packages/math/texlike.lua @@ -290,6 +290,10 @@ 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 @@ -481,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} = v + 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] From 59f4bfd18a45685be456550f4696b0f6632b2b02 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sat, 26 Oct 2024 05:00:31 +0200 Subject: [PATCH 05/17] feat(core): Add px unit as 0.75pt as per CSS3 We long did without it, but MathML examples may contain lengths in px. And we'll be happy too with other uses cases such as Markdown etc. This might break some code as SILE.types.length can ignore the unknown unit and the raw number value would thus be regarded as being in pt. But that's rather a parsing bug anyway, and SILE.types.measurement spits an error, so let's not care. --- types/unit.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/types/unit.lua b/types/unit.lua index 8991360ae..169de78a9 100644 --- a/types/unit.lua +++ b/types/unit.lua @@ -76,6 +76,13 @@ unittypes["pc"] = { definition = "0.166666667in", } +-- Pixel, by convention 1px = 1/96in = 0.75pt +-- (CSS Values and Units Module Level 3, §5.2) +-- Used in MathML, etc. +unittypes["px"] = { + definition = "0.75pt", +} + local checkPaperDefined = function () if not SILE.documentState or not SILE.documentState.orgPaperSize then SU.error("A measurement tried to measure the paper size before the paper was defined", true) From e0559e89a31c48f1e8dd4a9a48909bf922a714c4 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sat, 26 Oct 2024 11:03:46 +0200 Subject: [PATCH 06/17] 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. --- packages/math/base-elements.lua | 34 ++++++++++++++++++++++----------- packages/math/typesetter.lua | 2 +- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index caa309d73..511257ac9 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -1054,10 +1054,11 @@ function elements.fraction:__tostring () return self._type .. "(" .. tostring(self.numerator) .. ", " .. tostring(self.denominator) .. ")" end -function elements.fraction:_init (numerator, denominator) +function elements.fraction:_init (attributes, numerator, denominator) elements.mbox._init(self) self.numerator = numerator self.denominator = denominator + self.attributes = attributes table.insert(self.children, numerator) table.insert(self.children, denominator) end @@ -1069,12 +1070,12 @@ end function elements.fraction:shape () -- MathML Core 3.3.2: "To avoid visual confusion between the fraction bar - -- and another adjacent items (e.g. minus sign or another fraction's bar)," - -- By convention, here we use 1px = 1/96in = 0.75pt. + -- and another adjacent items (e.g. minus sign or another fraction's bar), + -- a default 1-pixel space is added around the element." -- Note that PlainTeX would likely use \nulldelimiterspace (default 1.2pt) -- but it would depend on the surrounding context, and might be far too -- much in some cases, so we stick to MathML's suggested padding. - self.padding = SILE.types.length(0.75) + self.padding = SILE.types.length("1px"):absolute() -- Determine relative abscissas and width local widest, other @@ -1090,7 +1091,16 @@ function elements.fraction:shape () local constants = self:getMathMetrics().constants local scaleDown = self:getScaleDown() self.axisHeight = constants.axisHeight * scaleDown - self.ruleThickness = constants.fractionRuleThickness * scaleDown + self.ruleThickness = self.attributes.linethickness + and SU.cast("measurement", self.attributes.linethickness):tonumber() + or constants.fractionRuleThickness * scaleDown + + -- MathML Core 3.3.2.2 ("Fraction with zero line thickness") uses + -- stack(DisplayStyle)GapMin, stackTop(DisplayStyle)ShiftUp and stackBottom(DisplayStyle)ShiftDown. + -- TODO not implemented + -- The most common use cases for zero line thickness are: + -- - Binomial coefficients + -- - Stacked subscript/superscript on big operators such as sums. local numeratorGapMin, denominatorGapMin, numeratorShiftUp, denominatorShiftDown if isDisplayMode(self.mode) then @@ -1126,12 +1136,14 @@ function elements.fraction:shape () end function elements.fraction:output (x, y, line) - SILE.outputter:drawRule( - scaleWidth(x + self.padding, line), - y.length - self.axisHeight - self.ruleThickness / 2, - scaleWidth(self.width - 2 * self.padding, line), - self.ruleThickness - ) + if self.ruleThickness > 0 then + SILE.outputter:drawRule( + scaleWidth(x + self.padding, line), + y.length - self.axisHeight - self.ruleThickness / 2, + scaleWidth(self.width - 2 * self.padding, line), + self.ruleThickness + ) + end end local function newSubscript (spec) diff --git a/packages/math/typesetter.lua b/packages/math/typesetter.lua index 8f2a3d82c..2faab1cf4 100644 --- a/packages/math/typesetter.lua +++ b/packages/math/typesetter.lua @@ -142,7 +142,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 element generates an anonymous box called the msqrt base From d5790961765e0b693788f89445840f0fc8912220 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Tue, 29 Oct 2024 02:23:16 +0100 Subject: [PATCH 07/17] 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. --- packages/math/base-elements.lua | 62 ++++++++++++++++++++++++--------- packages/math/texlike.lua | 5 +-- packages/math/typesetter.lua | 4 +++ 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index 511257ac9..a780308dd 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -468,7 +468,7 @@ function elements.stackbox.output (_, _, _, _) end elements.phantom = pl.class(elements.stackbox) -- inherit from stackbox elements.phantom._type = "Phantom" -function elements.phantom:_init (children, special) +function elements.phantom:_init (children) -- MathML core 3.3.7: -- "Its layout algorithm is the same as the mrow element". -- Also not the MathML states that is sort of legacy, "implemented @@ -477,22 +477,6 @@ function elements.phantom:_init (children, special) -- The thing is that we don't have CSS in SILE, so supporting is -- a must. elements.stackbox._init(self, "H", children) - self.special = special -end - -function elements.phantom:shape () - elements.stackbox.shape(self) - -- From https://latexref.xyz: - -- "The \vphantom variant produces an invisible box with the same vertical size - -- as subformula, the same height and depth, but having zero width. - -- And \hphantom makes a box with the same width as subformula but - -- with zero height and depth." - if self.special == "v" then - self.width = SILE.types.length() - elseif self.special == "h" then - self.height = SILE.types.length() - self.depth = SILE.types.length() - end end function elements.phantom:output (_, _, _) @@ -1454,6 +1438,50 @@ function elements.sqrt:output (x, y, line) ) end +elements.padded = pl.class(elements.mbox) +elements.padded._type = "Padded" + +function elements.padded:__tostring () + return self._type .. "(" .. tostring(self.impadded) .. ")" +end + +function elements.padded:_init (attributes, impadded) + elements.mbox._init(self) + self.impadded = impadded + self.attributes = attributes or {} + table.insert(self.children, impadded) +end + +function elements.padded:styleChildren () + self.impadded.mode = self.mode +end + +function elements.padded:shape () + -- TODO MathML allows percentages font-relative units (em, ex) for padding + -- But our units work with font.size, not math.font.size (possibly adjusted by scaleDown) + -- so the expectations might not be met. + local width = self.attributes.width and SU.cast("measurement", self.attributes.width) + local height = self.attributes.height and SU.cast("measurement", self.attributes.height) + local depth = self.attributes.depth and SU.cast("measurement", self.attributes.depth) + local lspace = self.attributes.lspace and SU.cast("measurement", self.attributes.lspace) + local voffset = self.attributes.voffset and SU.cast("measurement", self.attributes.voffset) + -- Clamping for width, height, depth, lspace + width = width and (width:tonumber() > 0 and width or SILE.types.measurement()) + height = height and (height:tonumber() > 0 and height or SILE.types.measurement()) + depth = depth and (depth:tonumber() > 0 and depth or SILE.types.measurement()) + lspace = lspace and (lspace:tonumber() > 0 and lspace or SILE.types.measurement()) + -- No clamping for voffset + voffset = voffset or SILE.types.measurement(0) + -- Compute the dimensions + self.width = width and SILE.types.length(width) or self.impadded.width + self.height = height and SILE.types.length(height) or self.impadded.height + self.depth = depth and SILE.types.length(depth) or self.impadded.depth + self.impadded.relX = lspace and SILE.types.length(lspace) or SILE.types.length() + self.impadded.relY = voffset and SILE.types.length(voffset):negate() or SILE.types.length() +end + +function elements.padded.output (_, _, _, _) end + elements.mathMode = mathMode elements.atomType = atomType elements.symbolDefaults = symbolDefaults diff --git a/packages/math/texlike.lua b/packages/math/texlike.lua index 1895092ed..7b7430b12 100644 --- a/packages/math/texlike.lua +++ b/packages/math/texlike.lua @@ -656,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}}} ]==], }) ) diff --git a/packages/math/typesetter.lua b/packages/math/typesetter.lua index 2faab1cf4..aaf4b9e04 100644 --- a/packages/math/typesetter.lua +++ b/packages/math/typesetter.lua @@ -177,6 +177,10 @@ function ConvertMathML (_, content) -- 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 element generates an anonymous 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 From 19906b9d83408b96b9eaf2774276c59956d6f50c Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Tue, 29 Oct 2024 03:10:01 +0100 Subject: [PATCH 08/17] fix(math): Wrong condition on moveable limits (workaround) This is not a proper fix, see in-code comment, but one has to move forward and the workaround does the trick until we can do better. --- packages/math/base-elements.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index a780308dd..91b60fc2e 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -663,7 +663,16 @@ function elements.underOver:styleChildren () end function elements.underOver:shape () - if not (self.mode == mathMode.display or self.mode == mathMode.displayCramped) then + if not (self.mode == mathMode.display or self.mode == mathMode.displayCramped) and self.base.largeop then + -- FIXME + -- Added the self.base.largeop condition, but it's kind of a workaround: + -- It should rather be the "moveablelimits" propery in MathML, but we do not have that yet. + -- When the base is a moveable limit, the under/over scripts are not placed under/over the base, + -- but ather to the right of it, when display mode is not used. + -- Notable effects: + -- Mozilla MathML test 19 (on "k times" > overbrace > base) + -- Maxwell's Equations in MathML3 Test Suite "complex1" (on the vectors in fractions) + -- For now, go with the "largeop" property, but this is not correct. self.isUnderOver = true elements.subscript.shape(self) return From 7c58886aac547aab4e08c42031e4330631f7e75a Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Wed, 30 Oct 2024 23:38:20 +0100 Subject: [PATCH 09/17] refactor(math): Prepare for horizontal reshaping of stretchy symbols --- packages/math/base-elements.lua | 83 +++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 31 deletions(-) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index 91b60fc2e..ea6e84f97 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -424,7 +424,7 @@ function elements.stackbox:shape () -- Handle stretchy operators for _, elt in ipairs(self.children) do if elt.is_a(elements.text) and elt.kind == "operator" and elt.stretchy then - elt:stretchyReshape(self.depth, self.height) + elt:_vertStretchyReshape(self.depth, self.height) end end -- Set self.width @@ -966,38 +966,56 @@ function elements.text:shape () end end -function elements.text:stretchyReshape (depth, height) - -- Required depth+height of stretched glyph, in font units +function elements.text.findClosestVariant (_, variants, requiredAdvance, currentAdvance) + local closest + local closestI + local m = requiredAdvance - currentAdvance + for i, variant in ipairs(variants) do + local diff = math.abs(variant.advanceMeasurement - requiredAdvance) + SU.debug("math", "stretch: diff =", diff) + if diff < m then + closest = variant + closestI = i + m = diff + end + end + return closest, closestI +end + +function elements.text:_reshapeGlyph (glyph, closestVariant, sz) + local face = SILE.font.cache(self.font, SILE.shaper.getFace) + local dimen = hb.get_glyph_dimensions(face, sz, closestVariant.variantGlyph) + glyph.gid = closestVariant.variantGlyph + glyph.width, glyph.height, glyph.depth, glyph.glyphAdvance = + dimen.width, dimen.height, dimen.depth, dimen.glyphAdvance + return dimen +end + +function elements.text:_stretchyReshape (target, direction) + -- direction is the required direction of stretching: true for vertical, false for horizontal + -- target is the required dimension of the stretched glyph, in font units local mathMetrics = self:getMathMetrics() local upem = mathMetrics.unitsPerEm local sz = self.font.size - local requiredAdvance = (depth + height):tonumber() * upem / sz + local requiredAdvance = target:tonumber() * upem / sz SU.debug("math", "stretch: rA =", requiredAdvance) -- Choose variant of the closest size. The criterion we use is to have -- an advance measurement as close as possible as the required one. - -- The advance measurement is simply the depth+height of the glyph. + -- The advance measurement is simply the dimension of the glyph. -- Therefore, the selected glyph may be smaller or bigger than - -- required. TODO: implement assembly of stretchable glyphs form - -- their parts for cases when the biggest variant is not big enough. + -- required. + -- TODO: implement assembly of stretchable glyphs from their parts for cases + -- when the biggest variant is not big enough. -- We copy the glyph list to avoid modifying the shaper's cache. Yes. local glyphs = pl.tablex.deepcopy(self.value.items) - local constructions = self:getMathMetrics().mathVariants.vertGlyphConstructions[glyphs[1].gid] + local glyphConstructions = direction and mathMetrics.mathVariants.vertGlyphConstructions + or mathMetrics.mathVariants.horizGlyphConstructions + local constructions = glyphConstructions[glyphs[1].gid] if constructions then local variants = constructions.mathGlyphVariantRecord SU.debug("math", "stretch: variants =", variants) - local closest - local closestI - local m = requiredAdvance - (self.depth + self.height):tonumber() * upem / sz - SU.debug("math", "stretch: m =", m) - for i, v in ipairs(variants) do - local diff = math.abs(v.advanceMeasurement - requiredAdvance) - SU.debug("math", "stretch: diff =", diff) - if diff < m then - closest = v - closestI = i - m = diff - end - end + local currentAdvance = (direction and (self.depth + self.height):tonumber() or self.width:tonumber()) * upem / sz + local closest, closestI = self:findClosestVariant(variants, requiredAdvance, currentAdvance) SU.debug("math", "stretch: closestI =", closestI) if closest then -- Now we have to re-shape the glyph chain. We will assume there @@ -1005,21 +1023,24 @@ function elements.text:stretchyReshape (depth, height) -- TODO: this code is probably wrong when the vertical -- variants have a different width than the original, because -- the shaping phase is already done. Need to do better. - glyphs[1].gid = closest.variantGlyph - local face = SILE.font.cache(self.font, SILE.shaper.getFace) - local dimen = hb.get_glyph_dimensions(face, self.font.size, closest.variantGlyph) - glyphs[1].width = dimen.width - glyphs[1].height = dimen.height - glyphs[1].depth = dimen.depth - glyphs[1].glyphAdvance = dimen.glyphAdvance - self.width = SILE.types.length(dimen.glyphAdvance) - self.depth = SILE.types.length(dimen.depth) - self.height = SILE.types.length(dimen.height) + local dimen = self:_reshapeGlyph(glyphs[1], closest, sz) + self.width, self.depth, self.height = + SILE.types.length(dimen.glyphAdvance), SILE.types.length(dimen.depth), SILE.types.length(dimen.height) SILE.shaper:preAddNodes(glyphs, self.value) self.value.items = glyphs self.value.glyphString = { glyphs[1].gid } + return true end end + return false +end + +function elements.text:_vertStretchyReshape(depth, height) + return self:_stretchyReshape(depth + height, true) +end + +function elements.text:_horizStretchyReshape(width) + return self:_stretchyReshape(width, false) end function elements.text:output (x, y, line) From bde46cdfe4bb2a76e5a9476f077ad9ad76860625 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Wed, 30 Oct 2024 23:43:35 +0100 Subject: [PATCH 10/17] fix(math): Honor stretchy attribute on MathML mo elements And also override other explicit attributes from the element over those from the default operator table. --- packages/math/base-elements.lua | 20 ++++++++++---------- packages/math/typesetter.lua | 5 +++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index ea6e84f97..48808d50d 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -423,7 +423,7 @@ function elements.stackbox:shape () end -- Handle stretchy operators for _, elt in ipairs(self.children) do - if elt.is_a(elements.text) and elt.kind == "operator" and elt.stretchy then + if elt.is_a(elements.text) and elt.kind == "operator" and SU.boolean(elt.stretchy, false) then elt:_vertStretchyReshape(self.depth, self.height) end end @@ -554,7 +554,7 @@ function elements.subscript:shape () local subShift local supShift if self.sub then - if self.isUnderOver or self.base.largeop then + if self.isUnderOver or SU.boolean(self.base.largeop, false) then -- Ad hoc correction on integral limits, following LuaTeX's -- `\mathnolimitsmode=0` (see LuaTeX Reference Manual). subShift = -itCorr @@ -567,12 +567,12 @@ function elements.subscript:shape () --self.base.depth + constants.subscriptBaselineDropMin * scaleDown, (self.sub.height - constants.subscriptTopMax * scaleDown):tonumber() )) - if self:is_a(elements.underOver) or self:is_a(elements.stackbox) or self.base.largeop then + if self:is_a(elements.underOver) or self:is_a(elements.stackbox) or SU.boolean(self.base.largeop, false) then self.sub.relY = maxLength(self.sub.relY, self.base.depth + constants.subscriptBaselineDropMin * scaleDown) end end if self.sup then - if self.isUnderOver or self.base.largeop then + if self.isUnderOver or SU.boolean(self.base.largeop, false) then -- Ad hoc correction on integral limits, following LuaTeX's -- `\mathnolimitsmode=0` (see LuaTeX Reference Manual). supShift = 0 @@ -586,7 +586,7 @@ function elements.subscript:shape () --self.base.height - constants.superscriptBaselineDropMax * scaleDown, (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 + if self:is_a(elements.underOver) or self:is_a(elements.stackbox) or SU.boolean(self.base.largeop, false) then self.sup.relY = maxLength( (0 - self.sup.relY), self.base.height - constants.superscriptBaselineDropMax * scaleDown @@ -663,9 +663,9 @@ function elements.underOver:styleChildren () end function elements.underOver:shape () - if not (self.mode == mathMode.display or self.mode == mathMode.displayCramped) and self.base.largeop then + if not (self.mode == mathMode.display or self.mode == mathMode.displayCramped) and SU.boolean(self.base.largeop, false) then -- FIXME - -- Added the self.base.largeop condition, but it's kind of a workaround: + -- Added the "largeop" condition, but it's kind of a workaround: -- It should rather be the "moveablelimits" propery in MathML, but we do not have that yet. -- When the base is a moveable limit, the under/over scripts are not placed under/over the base, -- but ather to the right of it, when display mode is not used. @@ -861,8 +861,8 @@ function elements.text:__tostring () .. tostring(self.kind) .. ", script=" .. tostring(self.script) - .. (self.stretchy and ", stretchy" or "") - .. (self.largeop and ", largeop" or "") + .. (SU.boolean(self.stretchy, false) and ", stretchy" or "") + .. (SU.boolean(self.largeop, false) and ", largeop" or "") .. ', text="' .. (self.originalText or self.text) .. '")' @@ -897,7 +897,7 @@ function elements.text:shape () local mathMetrics = self:getMathMetrics() local glyphs = SILE.shaper:shapeToken(self.text, self.font) -- Use bigger variants for big operators in display style - if isDisplayMode(self.mode) and self.largeop then + if isDisplayMode(self.mode) and SU.boolean(self.largeop, false) then -- We copy the glyph list to avoid modifying the shaper's cache. Yes. glyphs = pl.tablex.deepcopy(glyphs) local constructions = mathMetrics.mathVariants.vertGlyphConstructions[glyphs[1].gid] diff --git a/packages/math/typesetter.lua b/packages/math/typesetter.lua index aaf4b9e04..322293601 100644 --- a/packages/math/typesetter.lua +++ b/packages/math/typesetter.lua @@ -72,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) From 589c05863d3be03aed8a25f886c2a664a4bee1e1 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Thu, 31 Oct 2024 12:45:30 +0100 Subject: [PATCH 11/17] fix(math): Stretchy symbols should work on large content (workaround) The current stretchy "reshaping" picks the closest symbols in the math glyph variants, but when none exist or they are still not close enough (esp. far too small), OpenTypeand MathML Core say we should rely on complex glyph assembly rules from glyph parts. We don't have that yet: Here we fallback on re-scaling the glyph. It might not look always good, but at least it's stretched as it should around the content. It's a dirty compromise until something better can be done. --- packages/math/base-elements.lua | 38 ++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index 48808d50d..8aa2f7ed0 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -1035,12 +1035,26 @@ function elements.text:_stretchyReshape (target, direction) return false end -function elements.text:_vertStretchyReshape(depth, height) - return self:_stretchyReshape(depth + height, true) +function elements.text:_vertStretchyReshape (depth, height) + local hasStretched = self:_stretchyReshape(depth + height, true) + if hasStretched then + -- HACK: see output routine + self.vertExpectedSz = height + depth + self.vertScalingRatio = (depth + height):tonumber() / (self.height:tonumber() + self.depth:tonumber()) + self.height = height + self.depth = depth + end + return hasStretched end -function elements.text:_horizStretchyReshape(width) - return self:_stretchyReshape(width, false) +function elements.text:_horizStretchyReshape (width) + local hasStretched = self:_stretchyReshape(width, false) + if hasStretched then + -- HACK: see output routine + self.horizScalingRatio = width:tonumber() / self.width:tonumber() + self.width = width + end + return hasStretched end function elements.text:output (x, y, line) @@ -1058,7 +1072,21 @@ function elements.text:output (x, y, line) -- There should be no stretch or shrink on the width of a text -- element. local width = self.width.length - SILE.outputter:drawHbox(self.value, width) + -- HACK: For stretchy operators, MathML Core and OpenType define how to build large glyphs + -- from an assembly of smaller ones. It's fairly complex and idealistic... + -- Anyhow, we do not have that yet, so we just stretch the glyph artificially. + -- There are cases where this will not look very good. + -- Call that a compromise, so that long vectors or large matrices look "decent" without assembly. + if SILE.outputter.scaleFn and (self.horizScalingRatio or self.vertScalingRatio) then + local xratio = self.horizScalingRatio or 1 + local yratio = self.vertScalingRatio or 1 + SU.debug("math", "fake glyph stretch: xratio =", xratio, "yratio =", yratio) + SILE.outputter:scaleFn(x, y, xratio, yratio, function () + SILE.outputter:drawHbox(self.value, width) + end) + else + SILE.outputter:drawHbox(self.value, width) + end end elements.fraction = pl.class(elements.mbox) From a42181f74823fb0aece8871bd414108084227bd8 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Thu, 31 Oct 2024 13:08:37 +0100 Subject: [PATCH 12/17] fix(math): Wrong vertical alignment of integral signs --- packages/math/base-elements.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index 8aa2f7ed0..fbf675bf8 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -1062,7 +1062,7 @@ function elements.text:output (x, y, line) return end local compensatedY - if isDisplayMode(self.mode) and self.atom == atomType.bigOperator and self.value.items[1].fontDepth then + if isDisplayMode(self.mode) and SU.boolean(self.largeop, false) and self.value.items[1].fontDepth then compensatedY = SILE.types.length(y.length + self.value.items[1].depth - self.value.items[1].fontDepth) else compensatedY = y From b6e054e272aa653eb350b45994c0d15d71b596c4 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Fri, 1 Nov 2024 10:57:33 +0100 Subject: [PATCH 13/17] fix(math): Support basic operator stretching along the inline axis Presumably a non-general solution here, covering the main use cases only (e.g. braces and vectors) without too much stacking. --- packages/math/base-elements.lua | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index fbf675bf8..82efb4d98 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -662,6 +662,43 @@ function elements.underOver:styleChildren () end end +function elements.underOver:_stretchyReshapeToBase (part) + -- FIXME: Big leap of faith here. + -- MathML Core only mentions stretching along the inline axis in 3.4.2.2, + -- i.e. under the section on , , . + -- So we are "somewhat" good here, but... the algorithm is totally unclear + -- to me and seems to imply a lot of recursion and reshaping. + -- The implementation below is NOT general and only works for the cases + -- I checked: + -- Mozilla MathML tests: braces in f19, f22 + -- Personal tests: vectors in d19, d22, d23 + -- Joe Javawaski's tests: braces in 8a, 8b + -- MathML3 "complex1" torture test: Maxwell's Equations (vectors in fractions) + if #part.children == 0 then + local elt = part + if elt.is_a(elements.text) and elt.kind == "operator" and SU.boolean(elt.stretchy, false) then + elt:_horizStretchyReshape(self.base.width) + end + elseif part:is_a(elements.underOver) then + -- Big assumption here: only considering one level of stacked under/over. + local hasStreched = false + for _, elt in ipairs(part.children) do + if elt.is_a(elements.text) and elt.kind == "operator" and SU.boolean(elt.stretchy, false) then + local stretched = elt:_horizStretchyReshape(self.base.width) + if stretched then + hasStreched = true + end + end + end + if hasStreched then + -- We need to re-calculate the shape so positions are re-calculated on each + -- of its own parts. + -- (Added after seeing that Mozilla test f19 was not rendering correctly.) + part:shape() + end + end +end + function elements.underOver:shape () if not (self.mode == mathMode.display or self.mode == mathMode.displayCramped) and SU.boolean(self.base.largeop, false) then -- FIXME @@ -684,6 +721,7 @@ function elements.underOver:shape () self.base.relY = SILE.types.length(0) end if self.sub then + self:_stretchyReshapeToBase(self.sub) self.sub.relY = self.base.depth + SILE.types.length( math.max( @@ -693,6 +731,7 @@ function elements.underOver:shape () ) end if self.sup then + self:_stretchyReshapeToBase(self.sup) self.sup.relY = 0 - self.base.height - SILE.types.length( From 6f67be5268414b3aaeb5fde689a67af3f92047ab Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Fri, 1 Nov 2024 11:22:13 +0100 Subject: [PATCH 14/17] fix(math): Empty mrow's in munderover should not affect the baseline --- packages/math/base-elements.lua | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index 82efb4d98..f8209d400 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -633,12 +633,22 @@ function elements.underOver:__tostring () return self._type .. "(" .. tostring(self.base) .. ", " .. tostring(self.sub) .. ", " .. tostring(self.sup) .. ")" end +local function isNotEmpty (element) + -- The MathML test suite uses with an empty as sub/sup. + -- I don't know why they didn't use a or instead... + -- But the expectation is to behave as if the empty element was not there, + -- so that height and depth are not affected by the axis height. + -- See notably: + -- MathML3 "complex1" torture test: Maxwell's Equations (vectors in fractions) + return element and (element:is_a(elements.terminal) or #element.children > 0) +end + function elements.underOver:_init (base, sub, sup) elements.mbox._init(self) self.atom = base.atom self.base = base - self.sub = sub - self.sup = sup + self.sub = isNotEmpty(sub) and sub or nil + self.sup = isNotEmpty(sup) and sup or nil if self.sup then table.insert(self.children, self.sup) end From 6827eb9536197df5fa80e09a2935a08303320a80 Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Fri, 1 Nov 2024 23:46:37 +0100 Subject: [PATCH 15/17] fix(math): Correct sub/superscript position for subformulas vs. symbols Follow MathML Core layout, except when the base is a symbol, in which case use the more finicky TeX approach. Closes #2122 --- packages/math/base-elements.lua | 41 ++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/packages/math/base-elements.lua b/packages/math/base-elements.lua index f8209d400..1ad91c2a2 100644 --- a/packages/math/base-elements.lua +++ b/packages/math/base-elements.lua @@ -551,10 +551,12 @@ function elements.subscript:shape () self.width = SILE.types.length(0) end local itCorr = self:calculateItalicsCorrection() * scaleDown + local isBaseSymbol = not self.base or self.base:is_a(elements.terminal) + local isBaseLargeOp = SU.boolean(self.base and self.base.largeop, false) local subShift local supShift if self.sub then - if self.isUnderOver or SU.boolean(self.base.largeop, false) then + if self.isUnderOver or isBaseLargeOp then -- Ad hoc correction on integral limits, following LuaTeX's -- `\mathnolimitsmode=0` (see LuaTeX Reference Manual). subShift = -itCorr @@ -562,17 +564,20 @@ function elements.subscript:shape () subShift = 0 end self.sub.relX = self.width + subShift - self.sub.relY = SILE.types.length(math.max( - constants.subscriptShiftDown * scaleDown, - --self.base.depth + constants.subscriptBaselineDropMin * scaleDown, - (self.sub.height - constants.subscriptTopMax * scaleDown):tonumber() - )) - if self:is_a(elements.underOver) or self:is_a(elements.stackbox) or SU.boolean(self.base.largeop, false) then + self.sub.relY = SILE.types.length( + math.max( + constants.subscriptShiftDown * scaleDown, + isBaseSymbol and 0 -- TeX (σ19) is more finicky than MathML Core + or (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 isBaseLargeOp then self.sub.relY = maxLength(self.sub.relY, self.base.depth + constants.subscriptBaselineDropMin * scaleDown) end end if self.sup then - if self.isUnderOver or SU.boolean(self.base.largeop, false) then + if self.isUnderOver or isBaseLargeOp then -- Ad hoc correction on integral limits, following LuaTeX's -- `\mathnolimitsmode=0` (see LuaTeX Reference Manual). supShift = 0 @@ -580,13 +585,16 @@ function elements.subscript:shape () supShift = itCorr end self.sup.relX = self.width + supShift - 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.sup.depth + constants.superscriptBottomMin * scaleDown):tonumber() - )) * -1 - if self:is_a(elements.underOver) or self:is_a(elements.stackbox) or SU.boolean(self.base.largeop, false) then + self.sup.relY = SILE.types.length( + math.max( + isCrampedMode(self.mode) and constants.superscriptShiftUpCramped * scaleDown + or constants.superscriptShiftUp * scaleDown, + isBaseSymbol and 0 -- TeX (σ18) is more finicky than MathML Core + or (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 isBaseLargeOp then self.sup.relY = maxLength( (0 - self.sup.relY), self.base.height - constants.superscriptBaselineDropMax * scaleDown @@ -710,7 +718,8 @@ function elements.underOver:_stretchyReshapeToBase (part) end function elements.underOver:shape () - if not (self.mode == mathMode.display or self.mode == mathMode.displayCramped) and SU.boolean(self.base.largeop, false) then + local isBaseLargeOp = SU.boolean(self.base and self.base.largeop, false) + if not (self.mode == mathMode.display or self.mode == mathMode.displayCramped) and isBaseLargeOp then -- FIXME -- Added the "largeop" condition, but it's kind of a workaround: -- It should rather be the "moveablelimits" propery in MathML, but we do not have that yet. From 1f1a1a0303ed1d579ec98c4d98050ad84523541b Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sat, 2 Nov 2024 01:02:29 +0100 Subject: [PATCH 16/17] fix(math): Top-level math element must behave as an (horizontally stacked) mrow Closes #1293 --- packages/math/typesetter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/math/typesetter.lua b/packages/math/typesetter.lua index 322293601..bbc82f856 100644 --- a/packages/math/typesetter.lua +++ b/packages/math/typesetter.lua @@ -51,7 +51,7 @@ function ConvertMathML (_, content) 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 From ef249c3cca2beaf0a7e615d3325a11b72a4f1fdc Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sat, 2 Nov 2024 02:42:19 +0100 Subject: [PATCH 17/17] test(math): Upgrade math test expectations --- tests/bug-1495-inline-math-layout.expected | 56 ++--- tests/feat-math-display-numbered.expected | 22 +- tests/math-bigops.expected | 27 +-- tests/math-macros.expected | 74 +++--- tests/math-tables-mathml.expected | 70 +++--- tests/math-tables-tex.expected | 70 +++--- tests/math-variants.expected | 262 ++++++++++----------- 7 files changed, 281 insertions(+), 300 deletions(-) diff --git a/tests/bug-1495-inline-math-layout.expected b/tests/bug-1495-inline-math-layout.expected index f5969e666..b4c8ae2bd 100644 --- a/tests/bug-1495-inline-math-layout.expected +++ b/tests/bug-1495-inline-math-layout.expected @@ -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 @@ -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 diff --git a/tests/feat-math-display-numbered.expected b/tests/feat-math-display-numbered.expected index 76c5e4fee..265f6825e 100644 --- a/tests/feat-math-display-numbered.expected +++ b/tests/feat-math-display-numbered.expected @@ -167,7 +167,7 @@ T 38 88 86 87 82 80 w=34.1279 (Custom) Mx 51.4559 T 70 82 88 81 87 72 85 w=35.4600 (counter) Mx 96.0755 -My 293.6298 +My 293.1298 Set font Libertinus Math;10;400;Regular;normal;;;LTR Mx 2.9400 T 4118 a=4.0500 (nil) @@ -185,14 +185,14 @@ T 30 w=6.4800 (nil) Mx 127.3283 T 2722 w=6.2100 (nil) Mx 100.1255 -My 301.1048 +My 300.1048 T 2765 w=4.9200 (nil) Mx 104.6855 -My 303.2048 +My 302.2048 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 114.8483 -My 301.1048 +My 300.1048 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 127.3283 @@ -202,7 +202,7 @@ T 151 w=5.1000 (nil) Mx 140.6728 T 2765 w=4.9200 (nil) Mx 145.2328 -My 303.2048 +My 302.2048 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 148.9656 @@ -210,7 +210,7 @@ T 2088 w=5.1840 (nil) Mx 154.1496 T 18 w=3.7200 (nil) Mx 158.2996 -My 301.1048 +My 300.1048 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) Mx 162.1662 @@ -222,7 +222,7 @@ T 2618 w=6.4800 (nil) Mx 184.8918 T 18 w=4.6500 (nil) Mx 270.7354 -My 293.6298 +My 293.1298 Set font Gentium Plus;11;400;;normal;;;LTR T 11 w=3.4858 (() Mx 274.2212 @@ -230,12 +230,12 @@ T 68 w=5.0488 (a) Mx 279.2701 T 12 w=3.4858 ()) Mx 14.8819 -My 322.6002 +My 321.6002 T 39 76 85 72 70 87 w=27.5322 (Direct) Mx 44.8592 T 81 88 80 69 72 85 76 81 74 w=50.1714 (numbering) Mx 122.8959 -My 345.7905 +My 344.7905 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 18 w=4.6500 (nil) Mx 130.3237 @@ -245,13 +245,13 @@ T 2088 w=6.4800 (nil) Mx 146.0615 T 2750 w=3.8100 (nil) Mx 149.8715 -My 342.0405 +My 341.0405 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2753 w=1.8320 (nil) Mx 151.7035 T 3421 w=4.5776 (nil) Mx 264.7251 -My 345.7905 +My 344.7905 Set font Gentium Plus;11;400;;normal;;;LTR T 11 w=3.4858 (() Mx 268.2110 diff --git a/tests/math-bigops.expected b/tests/math-bigops.expected index effbcc6cd..56b4890e1 100644 --- a/tests/math-bigops.expected +++ b/tests/math-bigops.expected @@ -816,7 +816,7 @@ T 48 68 87 75 48 47 w=34.4336 (MathML) Mx 160.0108 T 29 w=2.2900 (:) Mx 229.1344 -My 381.4105 +My 384.4305 Set font Libertinus Math;10;400;Regular;normal;;;LTR Mx 9.7200 T 4231 a=10.7600 (nil) @@ -846,7 +846,7 @@ My 390.5105 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 17 w=3.7200 (nil) Mx 284.6860 -My 381.4105 +My 384.4305 Set font Libertinus Math;10;400;Regular;normal;;;LTR Mx 12.1800 T 3983 a=13.7400 (nil) @@ -863,6 +863,7 @@ T 69 55 w=11.5800 (nil) Mx 321.1850 T 30 w=6.4800 (nil) Mx 330.4428 +My 384.4305 Mx 5.3800 T 3981 a=6.9400 (nil) Mx 334.8828 @@ -911,7 +912,7 @@ T 48 68 87 75 48 47 w=34.4336 (MathML) Mx 209.5572 T 29 w=2.2900 (:) Mx 174.9317 -My 447.5261 +My 452.9621 Set font Libertinus Math;18;400;Regular;normal;;;LTR Mx 17.4960 T 4231 a=19.3680 (nil) @@ -941,7 +942,7 @@ My 463.9061 Set font Libertinus Math;14.4;400;Regular;normal;;;LTR T 17 w=6.6960 (nil) Mx 273.7246 -My 447.5261 +My 452.9621 Set font Libertinus Math;18;400;Regular;normal;;;LTR Mx 21.9240 T 3983 a=24.7320 (nil) @@ -958,6 +959,7 @@ T 69 55 w=20.8440 (nil) Mx 339.4228 T 30 w=11.6640 (nil) Mx 356.0868 +My 452.9621 Mx 9.6840 T 3981 a=12.4920 (nil) Mx 364.0788 @@ -1056,13 +1058,11 @@ My 483.7961 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 2751 w=5.8900 (nil) Mx 245.6942 -Mx 2.8200 -T 9 a=3.5600 (nil) +T 9 w=3.5600 (nil) Mx 249.2542 T 2764 w=3.0300 (nil) Mx 252.2842 -Mx 2.8200 -T 10 a=3.5600 (nil) +T 10 w=3.5600 (nil) Mx 255.8442 T 69 w=5.0600 (nil) Mx 260.9042 @@ -1082,7 +1082,7 @@ T 55 72 59 w=16.2793 (TeX) Mx 141.8605 T 29 w=2.2900 (:) Mx 229.1344 -My 526.1599 +My 529.1799 Set font Libertinus Math;10;400;Regular;normal;;;LTR Mx 9.7200 T 4231 a=10.7600 (nil) @@ -1112,7 +1112,7 @@ My 535.2599 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 17 w=3.7200 (nil) Mx 284.6860 -My 526.1599 +My 529.1799 Set font Libertinus Math;10;400;Regular;normal;;;LTR Mx 12.1800 T 3983 a=13.7400 (nil) @@ -1129,6 +1129,7 @@ T 69 55 w=11.5800 (nil) Mx 321.1850 T 30 w=6.4800 (nil) Mx 330.4428 +My 529.1799 Mx 5.3800 T 3981 a=6.9400 (nil) Mx 334.8828 @@ -1143,13 +1144,11 @@ My 526.1599 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 2751 w=5.8900 (nil) Mx 347.9012 -Mx 2.8200 -T 9 a=3.5600 (nil) +T 9 w=3.5600 (nil) Mx 351.4612 T 2764 w=3.0300 (nil) Mx 354.4912 -Mx 2.8200 -T 10 a=3.5600 (nil) +T 10 w=3.5600 (nil) Mx 358.0512 T 69 w=5.0600 (nil) Mx 363.1112 diff --git a/tests/math-macros.expected b/tests/math-macros.expected index 74a374dac..857e88b8d 100644 --- a/tests/math-macros.expected +++ b/tests/math-macros.expected @@ -1,33 +1,31 @@ Set paper size 595.275597 841.8897729 Begin page -Mx 241.7172 -My 51.6845 +Mx 243.0172 +My 52.1045 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 84 74 79 w=12.0300 (nil) -Mx 253.7472 +Mx 255.0472 My 47.9345 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 9 w=2.8480 (nil) -Mx 256.5952 +Mx 257.8952 T 19 w=3.7200 (nil) -Mx 260.3152 +Mx 261.6152 T 2758 w=3.7328 (nil) -Mx 264.0480 +Mx 265.3480 T 12 w=5.1840 (nil) -Mx 269.2320 +Mx 270.5320 T 18 w=3.7200 (nil) -Mx 272.9520 +Mx 274.2520 T 10 w=2.8480 (nil) -Mx 276.2300 -My 51.6845 +Mx 277.5300 +My 52.1045 Set font Libertinus Math;10;400;Regular;normal;;;LTR -Mx 3.0000 -T 3798 a=4.2100 (nil) -Mx 280.4400 +T 9 w=3.5600 (nil) +Mx 281.0900 T 2768 w=5.4100 (nil) -Mx 285.8500 -Mx 2.9900 -T 3799 a=4.2100 (nil) +Mx 286.5000 +T 10 w=3.5600 (nil) Mx 292.8378 T 30 w=6.4800 (nil) Mx 302.0956 @@ -37,74 +35,72 @@ T 2088 18 w=11.1300 (nil) Mx 316.7856 T 10 w=3.5600 (nil) Mx 320.3456 -My 47.9345 +My 47.1045 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 326.5084 -My 51.6845 +My 52.1045 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 68 80 84 w=13.2200 (nil) Mx 339.7284 -Mx 3.0000 -T 3798 a=4.2100 (nil) -Mx 343.9384 +T 9 w=3.5600 (nil) +Mx 343.2884 T 2768 w=5.4100 (nil) -Mx 349.3484 -Mx 2.9900 -T 3799 a=4.2100 (nil) -Draw line 275.3007 84.0086 11.3900 0.6500 +Mx 348.6984 +T 10 w=3.5600 (nil) +Draw line 275.3007 84.4286 11.3900 0.6500 Mx 275.3007 -My 79.6886 +My 80.1086 T 69 w=5.0600 (nil) Mx 280.3607 T 2812 w=6.3300 (nil) Mx 276.9507 -My 93.9336 +My 94.3536 T 69 w=5.0600 (nil) Mx 282.0107 T 2764 w=3.0300 (nil) Mx 290.2185 -My 86.9336 +My 87.3536 T 30 w=6.4800 (nil) Mx 299.4762 -My 86.8386 +My 87.2586 Mx 10.6300 T 3985 a=12.4300 (nil) Mx 304.7752 -My 97.5426 +My 97.9626 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2753 w=1.8320 (nil) Mx 313.5729 -My 86.9336 +My 87.3536 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 2776 w=6.0300 (nil) Mx 318.4629 -My 89.0336 +My 89.4536 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2753 w=1.8320 (nil) Mx 262.2436 -My 124.0866 +My 124.5066 Set font Libertinus Math;10;400;Regular;normal;;;LTR Mx 2.8200 T 9 a=3.5600 (nil) Mx 265.8036 T 3424 w=5.6700 (nil) Mx 270.4736 -My 126.1866 +My 126.6066 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 17 w=3.7200 (nil) Mx 274.6236 -My 124.0866 +My 124.5066 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) Mx 278.4903 T 3424 w=5.6700 (nil) Mx 283.1603 -My 126.1866 +My 126.6066 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 18 w=3.7200 (nil) Mx 287.3103 -My 124.0866 +My 124.5066 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) Mx 291.1770 @@ -114,11 +110,11 @@ T 13 w=2.2000 (nil) Mx 302.5336 T 3424 w=5.6700 (nil) Mx 307.2036 -My 126.1866 +My 126.6066 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 311.3664 -My 124.0866 +My 124.5066 Set font Libertinus Math;10;400;Regular;normal;;;LTR Mx 2.8200 T 10 a=3.5600 (nil) diff --git a/tests/math-tables-mathml.expected b/tests/math-tables-mathml.expected index a9b842829..55063c30b 100644 --- a/tests/math-tables-mathml.expected +++ b/tests/math-tables-mathml.expected @@ -1,7 +1,7 @@ Set paper size 595.275597 841.8897729 Begin page Mx 49.7638 -My 61.0395 +My 60.0395 Set font Gentium Plus;10;400;;normal;;;LTR T 49 88 80 69 72 85 w=33.4766 (Number) Mx 85.9226 @@ -25,21 +25,21 @@ T 19 w=4.6500 (nil) Mx 200.8698 T 24 w=4.6500 (nil) Mx 179.5698 -My 61.4745 +My 60.4745 T 17 w=4.6500 (nil) Mx 190.2198 T 22 w=4.6500 (nil) Mx 200.8698 T 20 w=4.6500 (nil) Mx 179.5698 -My 74.6845 +My 72.6845 T 25 w=4.6500 (nil) Mx 190.2198 T 19 w=4.6500 (nil) Mx 200.8698 T 18 w=4.6500 (nil) Mx 49.7638 -My 83.3528 +My 81.3528 Set font Gentium Plus;10;400;;normal;;;LTR T 49 88 80 69 72 85 w=33.4766 (Number) Mx 85.9243 @@ -55,7 +55,7 @@ T 48 68 87 75 48 47 w=34.4336 (MathML) Mx 187.3713 T 29 w=2.2900 (:) Mx 284.6628 -My 102.0163 +My 100.0163 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 18 w=4.6500 (nil) Mx 295.3128 @@ -63,21 +63,21 @@ T 19 w=4.6500 (nil) Mx 305.9628 T 24 w=4.6500 (nil) Mx 284.6628 -My 115.2563 +My 112.2563 T 17 w=4.6500 (nil) Mx 295.3128 T 22 w=4.6500 (nil) Mx 305.9628 T 20 w=4.6500 (nil) Mx 284.6628 -My 128.4663 +My 124.4663 T 25 w=4.6500 (nil) Mx 295.3128 T 19 w=4.6500 (nil) Mx 305.9628 T 18 w=4.6500 (nil) Mx 49.7638 -My 160.8513 +My 155.8513 Set font Gentium Plus;10;400;;normal;;;LTR T 41 82 85 80 88 79 68 86 w=38.2617 (Formulas) Mx 88.0255 @@ -91,47 +91,47 @@ T 48 68 87 75 48 47 w=34.4336 (MathML) Mx 148.9251 T 29 w=2.2900 (:) Mx 153.9043 -My 144.7283 +My 140.7283 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 2765 w=4.9200 (nil) Mx 158.4643 -My 146.8283 +My 142.8283 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 17 w=3.7200 (nil) Mx 168.6143 -My 144.7283 +My 140.7283 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 181.0943 T 18 w=4.6500 (nil) Mx 153.9043 -My 159.9883 +My 154.9883 T 2765 w=4.9200 (nil) Mx 158.4643 -My 162.0883 +My 157.0883 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 18 w=3.7200 (nil) Mx 168.6143 -My 159.9883 +My 154.9883 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 181.0943 T 18 w=4.6500 (nil) Mx 153.8915 -My 175.6743 +My 169.6743 T 2765 w=4.9200 (nil) Mx 158.4515 -My 177.7743 +My 171.7743 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 168.6143 -My 175.6743 +My 169.6743 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 181.0943 T 2765 w=4.9200 (nil) Mx 185.6543 -My 177.7743 +My 171.7743 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 189.3871 @@ -139,13 +139,13 @@ T 2088 w=5.1840 (nil) Mx 194.5711 T 18 w=3.7200 (nil) Mx 200.9774 -My 175.6743 +My 169.6743 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 12 w=6.4800 (nil) Mx 209.7137 T 2765 w=4.9200 (nil) Mx 214.2737 -My 177.7743 +My 171.7743 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 218.0065 @@ -153,7 +153,7 @@ T 2088 w=5.1840 (nil) Mx 223.1905 T 19 w=3.7200 (nil) Mx 227.3405 -My 175.6743 +My 169.6743 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) Mx 231.2072 @@ -165,7 +165,7 @@ T 2618 w=6.4800 (nil) Mx 254.1031 T 19 w=4.6500 (nil) Mx 49.7638 -My 186.4227 +My 180.4227 Set font Gentium Plus;10;400;;normal;;;LTR T 41 82 85 80 88 79 68 86 w=38.2617 (Formulas) Mx 88.0255 @@ -179,47 +179,47 @@ T 48 68 87 75 48 47 w=34.4336 (MathML) Mx 161.7145 T 29 w=2.2900 (:) Mx 245.3391 -My 205.0261 +My 199.0261 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 2765 w=4.9200 (nil) Mx 249.8991 -My 207.1261 +My 201.1261 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 17 w=3.7200 (nil) Mx 260.0491 -My 205.0261 +My 199.0261 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 272.5291 T 18 w=4.6500 (nil) Mx 245.3391 -My 220.2861 +My 213.2861 T 2765 w=4.9200 (nil) Mx 249.8991 -My 222.3861 +My 215.3861 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 18 w=3.7200 (nil) Mx 260.0491 -My 220.2861 +My 213.2861 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 272.5291 T 18 w=4.6500 (nil) Mx 245.3263 -My 235.9721 +My 227.9721 T 2765 w=4.9200 (nil) Mx 249.8863 -My 238.0721 +My 230.0721 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 260.0491 -My 235.9721 +My 227.9721 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 272.5291 T 2765 w=4.9200 (nil) Mx 277.0891 -My 238.0721 +My 230.0721 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 280.8219 @@ -227,13 +227,13 @@ T 2088 w=5.1840 (nil) Mx 286.0059 T 18 w=3.7200 (nil) Mx 292.3781 -My 235.9721 +My 227.9721 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 12 w=6.4800 (nil) Mx 301.0803 T 2765 w=4.9200 (nil) Mx 305.6403 -My 238.0721 +My 230.0721 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 309.3731 @@ -241,7 +241,7 @@ T 2088 w=5.1840 (nil) Mx 314.5571 T 19 w=3.7200 (nil) Mx 318.7071 -My 235.9721 +My 227.9721 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) Mx 322.5738 diff --git a/tests/math-tables-tex.expected b/tests/math-tables-tex.expected index 9217f7766..0c7122c6d 100644 --- a/tests/math-tables-tex.expected +++ b/tests/math-tables-tex.expected @@ -1,7 +1,7 @@ Set paper size 595.275597 841.8897729 Begin page Mx 49.7638 -My 61.0395 +My 60.0395 Set font Gentium Plus;10;400;;normal;;;LTR T 49 88 80 69 72 85 w=33.4766 (Number) Mx 85.9246 @@ -25,21 +25,21 @@ T 19 w=4.6500 (nil) Mx 182.7235 T 24 w=4.6500 (nil) Mx 161.4235 -My 61.4745 +My 60.4745 T 17 w=4.6500 (nil) Mx 172.0735 T 22 w=4.6500 (nil) Mx 182.7235 T 20 w=4.6500 (nil) Mx 161.4235 -My 74.6845 +My 72.6845 T 25 w=4.6500 (nil) Mx 172.0735 T 19 w=4.6500 (nil) Mx 182.7235 T 18 w=4.6500 (nil) Mx 49.7638 -My 83.3528 +My 81.3528 Set font Gentium Plus;10;400;;normal;;;LTR T 49 88 80 69 72 85 w=33.4766 (Number) Mx 85.9263 @@ -55,7 +55,7 @@ T 55 72 59 w=16.2793 (TeX) Mx 169.2230 T 29 w=2.2900 (:) Mx 284.6628 -My 102.0163 +My 100.0163 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 18 w=4.6500 (nil) Mx 295.3128 @@ -63,21 +63,21 @@ T 19 w=4.6500 (nil) Mx 305.9628 T 24 w=4.6500 (nil) Mx 284.6628 -My 115.2563 +My 112.2563 T 17 w=4.6500 (nil) Mx 295.3128 T 22 w=4.6500 (nil) Mx 305.9628 T 20 w=4.6500 (nil) Mx 284.6628 -My 128.4663 +My 124.4663 T 25 w=4.6500 (nil) Mx 295.3128 T 19 w=4.6500 (nil) Mx 305.9628 T 18 w=4.6500 (nil) Mx 49.7638 -My 160.8513 +My 155.8513 Set font Gentium Plus;10;400;;normal;;;LTR T 41 82 85 80 88 79 68 86 w=38.2617 (Formulas) Mx 88.0255 @@ -91,47 +91,47 @@ T 55 72 59 w=16.2793 (TeX) Mx 130.7748 T 29 w=2.2900 (:) Mx 135.7560 -My 144.7283 +My 140.7283 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 2765 w=4.9200 (nil) Mx 140.3160 -My 146.8283 +My 142.8283 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 17 w=3.7200 (nil) Mx 150.4660 -My 144.7283 +My 140.7283 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 162.9460 T 18 w=4.6500 (nil) Mx 135.7560 -My 159.9883 +My 154.9883 T 2765 w=4.9200 (nil) Mx 140.3160 -My 162.0883 +My 157.0883 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 18 w=3.7200 (nil) Mx 150.4660 -My 159.9883 +My 154.9883 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 162.9460 T 18 w=4.6500 (nil) Mx 135.7432 -My 175.6743 +My 169.6743 T 2765 w=4.9200 (nil) Mx 140.3032 -My 177.7743 +My 171.7743 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 150.4660 -My 175.6743 +My 169.6743 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 162.9460 T 2765 w=4.9200 (nil) Mx 167.5060 -My 177.7743 +My 171.7743 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 171.2388 @@ -139,13 +139,13 @@ T 2088 w=5.1840 (nil) Mx 176.4228 T 18 w=3.7200 (nil) Mx 182.8311 -My 175.6743 +My 169.6743 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 12 w=6.4800 (nil) Mx 191.5694 T 2765 w=4.9200 (nil) Mx 196.1294 -My 177.7743 +My 171.7743 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 199.8622 @@ -153,7 +153,7 @@ T 2088 w=5.1840 (nil) Mx 205.0462 T 19 w=3.7200 (nil) Mx 209.1962 -My 175.6743 +My 169.6743 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) Mx 213.0629 @@ -165,7 +165,7 @@ T 2618 w=6.4800 (nil) Mx 235.9689 T 19 w=4.6500 (nil) Mx 49.7638 -My 186.4227 +My 180.4227 Set font Gentium Plus;10;400;;normal;;;LTR T 41 82 85 80 88 79 68 86 w=38.2617 (Formulas) Mx 88.0255 @@ -179,47 +179,47 @@ T 55 72 59 w=16.2793 (TeX) Mx 130.7985 T 29 w=2.2900 (:) Mx 245.3391 -My 204.0740 +My 198.0740 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 2765 w=4.9200 (nil) Mx 249.8991 -My 206.1740 +My 200.1740 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 17 w=3.7200 (nil) Mx 260.0491 -My 204.0740 +My 198.0740 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 272.5291 T 18 w=4.6500 (nil) Mx 245.3391 -My 219.3340 +My 212.3340 T 2765 w=4.9200 (nil) Mx 249.8991 -My 221.4340 +My 214.4340 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 18 w=3.7200 (nil) Mx 260.0491 -My 219.3340 +My 212.3340 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 272.5291 T 18 w=4.6500 (nil) Mx 245.3263 -My 235.0200 +My 227.0200 T 2765 w=4.9200 (nil) Mx 249.8863 -My 237.1200 +My 229.1200 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 260.0491 -My 235.0200 +My 227.0200 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 30 w=6.4800 (nil) Mx 272.5291 T 2765 w=4.9200 (nil) Mx 277.0891 -My 237.1200 +My 229.1200 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 280.8219 @@ -227,13 +227,13 @@ T 2088 w=5.1840 (nil) Mx 286.0059 T 18 w=3.7200 (nil) Mx 292.3781 -My 235.0200 +My 227.0200 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 12 w=6.4800 (nil) Mx 301.0803 T 2765 w=4.9200 (nil) Mx 305.6403 -My 237.1200 +My 229.1200 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 309.3731 @@ -241,7 +241,7 @@ T 2088 w=5.1840 (nil) Mx 314.5571 T 19 w=3.7200 (nil) Mx 318.7071 -My 235.0200 +My 227.0200 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) Mx 322.5738 diff --git a/tests/math-variants.expected b/tests/math-variants.expected index 36c4000ae..fdf17775c 100644 --- a/tests/math-variants.expected +++ b/tests/math-variants.expected @@ -1,157 +1,157 @@ Set paper size 595.275597 841.8897729 Begin page Mx 49.7638 -My 50.0745 +My 51.9745 Set font Gentium Plus;10;400;;normal;;;LTR T 48 68 87 75 w=21.6113 (Math) -Mx 74.0469 +Mx 74.0466 T 89 68 85 76 68 81 87 86 w=33.6035 (variants) -Mx 107.6504 +Mx 107.6501 T 15 w=2.2900 (,) -Mx 112.6122 +Mx 112.6116 T 87 72 91 87 w=16.5332 (text) -Mx 129.1454 +Mx 129.1448 T 15 w=2.2900 (,) -Mx 134.1072 +Mx 134.1063 T 48 68 87 75 48 47 w=34.4336 (MathML) -Mx 168.5408 +Mx 168.5399 T 29 w=2.2900 (:) -Mx 173.5026 +Mx 173.5014 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 2070 w=5.9800 (nil) -Mx 179.4826 +Mx 179.4814 T 2758 w=4.7100 (nil) -Mx 187.0439 +Mx 187.0421 T 2078 w=6.3700 (nil) -Mx 196.2653 +Mx 196.2627 T 1880 w=8.2400 (nil) -Mx 204.5053 +Mx 204.5027 T 13 w=2.2000 (nil) -Mx 208.3720 -Mx 2.8200 -T 9 a=3.5600 (nil) -Mx 211.9320 +Mx 208.3694 +Mx 3.0000 +T 3798 a=4.2100 (nil) +Mx 212.5794 T 70 w=4.4700 (nil) -Mx 216.4020 -My 46.9745 +Mx 217.0494 +My 48.8745 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) -Mx 220.5648 -My 50.0745 +Mx 221.2122 +My 51.9745 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) -Mx 224.4315 +Mx 225.0789 T 3000 2990 2995 w=14.3900 (nil) -Mx 238.8215 -Mx 2.8200 -T 9 a=3.5600 (nil) -Mx 242.3815 +Mx 239.4689 +Mx 3.0000 +T 3798 a=4.2100 (nil) +Mx 243.6789 T 2758 w=4.7100 (nil) -Mx 247.0915 -Mx 2.8200 -T 10 a=3.5600 (nil) -Mx 250.6515 -Mx 2.8200 -T 10 a=3.5600 (nil) -Mx 257.0628 +Mx 248.3889 +Mx 2.9900 +T 3799 a=4.2100 (nil) +Mx 252.5989 +Mx 2.9900 +T 3799 a=4.2100 (nil) +Mx 259.6595 T 2078 w=6.3700 (nil) -Mx 266.2842 +Mx 268.8802 Mx 2.8200 T 9 a=3.5600 (nil) -Mx 269.8442 +Mx 272.4402 T 1887 w=6.1800 (nil) -Mx 278.2759 +Mx 280.8716 T 2601 w=5.2700 (nil) -Mx 285.7976 +Mx 288.3930 T 1884 w=7.0200 (nil) -Mx 292.8176 +Mx 295.4130 Mx 2.8200 T 10 a=3.5600 (nil) -Mx 296.3776 +Mx 298.9730 My 46.9745 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 19 w=3.7200 (nil) Mx 49.7638 -My 67.5285 +My 72.8485 Set font Gentium Plus;10;400;;normal;;;LTR T 48 68 87 75 w=21.6113 (Math) -Mx 74.0300 +Mx 74.0295 T 89 68 85 76 68 81 87 86 w=33.6035 (variants) -Mx 107.6335 +Mx 107.6330 T 15 w=2.2900 (,) -Mx 112.5784 +Mx 112.5774 T 87 72 91 87 w=16.5332 (text) -Mx 131.7665 +Mx 131.7649 T 11 w=3.1689 (() -Mx 134.9354 +Mx 134.9339 T 79 68 85 74 72 w=20.7568 (large) -Mx 158.3471 +Mx 158.3451 T 73 82 81 87 w=17.0996 (font) -Mx 175.4467 +Mx 175.4447 T 12 w=3.1689 ()) -Mx 178.6157 +Mx 178.6136 T 15 w=2.2900 (,) -Mx 183.5606 +Mx 183.5580 T 48 68 87 75 48 47 w=34.4336 (MathML) -Mx 217.9942 +Mx 217.9916 T 29 w=2.2900 (:) -Mx 225.5940 +Mx 225.5904 Set font Libertinus Math;18;400;Regular;normal;;;LTR T 2070 w=10.7640 (nil) -Mx 236.3580 +Mx 236.3544 T 2758 w=8.4780 (nil) -Mx 249.8918 +Mx 249.8859 T 2078 w=11.4660 (nil) -Mx 266.4136 +Mx 266.4053 T 1880 w=14.8320 (nil) -Mx 281.2456 +Mx 281.2373 T 13 w=3.9600 (nil) -Mx 288.2056 -Mx 5.0760 -T 9 a=6.4080 (nil) -Mx 294.6136 +Mx 288.1973 +Mx 5.4000 +T 3798 a=7.5780 (nil) +Mx 295.7753 T 70 w=8.0460 (nil) -Mx 302.6596 -My 61.9485 +Mx 303.8213 +My 67.2685 Set font Libertinus Math;14.4;400;Regular;normal;;;LTR T 2758 w=6.7190 (nil) -Mx 310.1526 -My 67.5285 +Mx 311.3144 +My 72.8485 Set font Libertinus Math;18;400;Regular;normal;;;LTR T 13 w=3.9600 (nil) -Mx 317.1126 +Mx 318.2744 T 3000 2990 2995 w=25.9020 (nil) -Mx 343.0146 -Mx 5.0760 -T 9 a=6.4080 (nil) -Mx 349.4226 +Mx 344.1764 +Mx 5.4000 +T 3798 a=7.5780 (nil) +Mx 351.7544 T 2758 w=8.4780 (nil) -Mx 357.9006 -Mx 5.0760 -T 10 a=6.4080 (nil) -Mx 364.3086 -Mx 5.0760 -T 10 a=6.4080 (nil) -Mx 375.7725 +Mx 360.2324 +Mx 5.3820 +T 3799 a=7.5780 (nil) +Mx 367.8104 +Mx 5.3820 +T 3799 a=7.5780 (nil) +Mx 380.4419 T 2078 w=11.4660 (nil) -Mx 392.2943 +Mx 396.9614 Mx 5.0760 T 9 a=6.4080 (nil) -Mx 398.7023 +Mx 403.3694 T 1887 w=11.1240 (nil) -Mx 413.8486 +Mx 418.5148 T 2601 w=9.4860 (nil) -Mx 427.3569 +Mx 432.0222 T 1884 w=12.6360 (nil) -Mx 439.9929 +Mx 444.6582 Mx 5.0760 T 10 a=6.4080 (nil) -Mx 446.4009 -My 61.9485 +Mx 451.0662 +My 63.8485 Set font Libertinus Math;14.4;400;Regular;normal;;;LTR T 19 w=6.6960 (nil) Mx 49.7638 -My 79.8588 +My 85.1788 Set font Gentium Plus;10;400;;normal;;;LTR T 48 68 87 75 w=21.6113 (Math) Mx 74.0597 @@ -167,7 +167,7 @@ T 48 68 87 75 48 47 w=34.4336 (MathML) Mx 181.3479 T 29 w=2.2900 (:) Mx 233.0020 -My 101.0123 +My 107.5823 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 2070 w=5.9800 (nil) Mx 238.9820 @@ -184,11 +184,11 @@ T 3798 a=4.2100 (nil) Mx 271.9342 T 70 w=4.4700 (nil) Mx 276.4042 -My 97.2623 +My 103.8323 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 280.5670 -My 101.0123 +My 107.5823 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) Mx 284.4336 @@ -219,11 +219,11 @@ Mx 354.5636 Mx 2.8200 T 10 a=3.5600 (nil) Mx 358.1236 -My 97.2623 +My 102.5823 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 19 w=3.7200 (nil) Mx 49.7638 -My 122.0943 +My 128.6643 Set font Gentium Plus;10;400;;normal;;;LTR T 48 68 87 75 w=21.6113 (Math) Mx 74.0543 @@ -247,7 +247,7 @@ T 48 68 87 75 48 47 w=34.4336 (MathML) Mx 230.8842 T 29 w=2.2900 (:) Mx 181.2933 -My 150.1518 +My 158.9718 Set font Libertinus Math;18;400;Regular;normal;;;LTR T 2070 w=10.7640 (nil) Mx 192.0573 @@ -264,11 +264,11 @@ T 3798 a=7.5780 (nil) Mx 251.3713 T 70 w=8.0460 (nil) Mx 259.4173 -My 143.4018 +My 152.2218 Set font Libertinus Math;14.4;400;Regular;normal;;;LTR T 2758 w=6.7190 (nil) Mx 266.9103 -My 150.1518 +My 158.9718 Set font Libertinus Math;18;400;Regular;normal;;;LTR T 13 w=3.9600 (nil) Mx 273.8703 @@ -299,11 +299,11 @@ Mx 400.1043 Mx 5.0760 T 10 a=6.4080 (nil) Mx 406.5123 -My 143.4018 +My 149.9718 Set font Libertinus Math;14.4;400;Regular;normal;;;LTR T 19 w=6.6960 (nil) Mx 49.7638 -My 171.9758 +My 182.6958 Set font Gentium Plus;10;400;;normal;;;LTR T 48 68 87 75 w=21.6113 (Math) Mx 74.0491 @@ -330,31 +330,27 @@ T 1880 w=8.2400 (nil) Mx 186.3714 T 13 w=2.2000 (nil) Mx 190.2381 -Mx 2.8200 -T 9 a=3.5600 (nil) +T 9 w=3.5600 (nil) Mx 193.7981 T 70 w=4.4700 (nil) Mx 198.2681 -My 168.8758 +My 179.5958 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) Mx 202.4309 -My 171.9758 +My 182.6958 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) Mx 206.2976 T 84 74 79 w=12.0300 (nil) Mx 218.3276 -Mx 2.8200 -T 9 a=3.5600 (nil) +T 9 w=3.5600 (nil) Mx 221.8876 T 2758 w=4.7100 (nil) Mx 226.5976 -Mx 2.8200 -T 10 a=3.5600 (nil) +T 10 w=3.5600 (nil) Mx 230.1576 -Mx 2.8200 -T 10 a=3.5600 (nil) +T 10 w=3.5600 (nil) Mx 236.5746 T 2078 w=6.3700 (nil) Mx 245.8017 @@ -370,11 +366,11 @@ Mx 272.3396 Mx 2.8200 T 10 a=3.5600 (nil) Mx 275.8996 -My 168.8758 +My 177.6958 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 19 w=3.7200 (nil) Mx 49.7638 -My 183.9758 +My 194.6958 Set font Gentium Plus;10;400;;normal;;;LTR T 48 68 87 75 w=21.6113 (Math) Mx 74.0617 @@ -389,60 +385,56 @@ Mx 146.9203 T 55 72 59 w=16.2793 (TeX) Mx 163.1996 T 29 w=2.2900 (:) -Mx 234.1820 -My 205.1292 +Mx 235.4820 +My 217.0992 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 2070 w=5.9800 (nil) -Mx 240.1620 +Mx 241.4620 T 2758 w=4.7100 (nil) -Mx 247.6497 +Mx 248.9497 T 2078 w=6.3700 (nil) -Mx 256.7975 +Mx 258.0975 T 1880 w=8.2400 (nil) -Mx 265.0375 +Mx 266.3375 T 13 w=2.2000 (nil) -Mx 268.9042 -Mx 3.0000 -T 3798 a=4.2100 (nil) -Mx 273.1142 +Mx 270.2042 +T 9 w=3.5600 (nil) +Mx 273.7642 T 70 w=4.4700 (nil) -Mx 277.5842 -My 201.3792 +Mx 278.2342 +My 213.3492 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 2758 w=3.7328 (nil) -Mx 281.7470 -My 205.1292 +Mx 282.3970 +My 217.0992 Set font Libertinus Math;10;400;Regular;normal;;;LTR T 13 w=2.2000 (nil) -Mx 285.6136 +Mx 286.2636 T 84 74 79 w=12.0300 (nil) -Mx 297.6436 -Mx 3.0000 -T 3798 a=4.2100 (nil) +Mx 298.2936 +T 9 w=3.5600 (nil) Mx 301.8536 T 2758 w=4.7100 (nil) Mx 306.5636 -Mx 2.9900 -T 3799 a=4.2100 (nil) -Mx 310.7736 -Mx 2.9900 -T 3799 a=4.2100 (nil) -Mx 317.7614 +T 10 w=3.5600 (nil) +Mx 310.1236 +T 10 w=3.5600 (nil) +Mx 316.4614 T 2078 w=6.3700 (nil) -Mx 326.9092 +Mx 325.6092 Mx 2.8200 T 9 a=3.5600 (nil) -Mx 330.4692 +Mx 329.1692 T 1887 w=6.1800 (nil) -Mx 338.8714 +Mx 337.5714 T 2601 w=5.2700 (nil) -Mx 346.3636 +Mx 345.0636 T 1884 w=7.0200 (nil) -Mx 353.3836 +Mx 352.0836 Mx 2.8200 T 10 a=3.5600 (nil) -Mx 356.9436 -My 201.3792 +Mx 355.6436 +My 212.0992 Set font Libertinus Math;8;400;Regular;normal;;;LTR T 19 w=3.7200 (nil) Mx 295.2916