From 19fd61fe8304e6627ed1b9279f62350b4f72338e Mon Sep 17 00:00:00 2001 From: Omikhleia Date: Sat, 9 Nov 2024 16:25:01 +0100 Subject: [PATCH] fix(math): Avoid page breaks before display math equations See #2160. This is a conservative workaround. Introducing the predisplay/postdisplay penalties is the right thing to do, but a more general solution to the full issue requires a more subtle handling of in-paragraph display math equations, which is not considered here. --- packages/math/init.lua | 25 +++++++++++++++++++++++++ packages/math/typesetter.lua | 16 ++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/packages/math/init.lua b/packages/math/init.lua index d3715c5f6..79edba25e 100644 --- a/packages/math/init.lua +++ b/packages/math/init.lua @@ -56,6 +56,31 @@ function package.declareSettings (_) type = "VGlue", default = SILE.types.node.vglue("2ex plus 1pt"), }) + + -- Penalties for breaking before and after a display math formula + -- See TeX's \predisplaypenalty and \postdisplaypenalty + SILE.settings:declare({ + parameter = "math.predisplaypenalty", + type = "integer", + default = 10000, -- strict no break by default as in (La)TeX + help = "Penalty for breaking before a display math formula", + }) + SILE.settings:declare({ + parameter = "math.postdisplaypenalty", + type = "integer", + -- (La)TeX's default is 0 (a normal line break penalty allowing a break + -- after a display math formula) + -- See https://github.com/sile-typesetter/sile/issues/2160 + -- And see implementation in handleMath(): we are not yet doing the right + -- things with respect to paragraphing, so setting a lower value for now + -- to ease breaking after a display math formula rather than before + -- when the formula is in the middle of a paragraph. + -- (In TeX, these penalties would apply in horizontal mode, with a display + -- math formula being a horizontal full-width box, our implementation + -- currently use them as vertical penalties). + default = -50, + help = "Penalty for breaking after a display math formula", + }) end function package:registerCommands () diff --git a/packages/math/typesetter.lua b/packages/math/typesetter.lua index bbc82f856..3fbb81d44 100644 --- a/packages/math/typesetter.lua +++ b/packages/math/typesetter.lua @@ -211,8 +211,15 @@ local function handleMath (_, mbox, options) mbox:shapeTree() if mode == "display" then - SILE.typesetter:endline() + -- See https://github.com/sile-typesetter/sile/issues/2160 + -- We are not excactly doing the right things here with respect to + -- paragraphing expectations. + -- The vertical penalty will flush the previous paragraph, if any. + SILE.call("penalty", { penalty = SILE.settings:get("math.predisplaypenalty"), vertical = true }) SILE.typesetter:pushExplicitVglue(SILE.settings:get("math.displayskip")) + -- Repeating the penalty after the skip does not hurt but should not be + -- necessary if our page builder did its stuff correctly. + SILE.call("penalty", { penalty = SILE.settings:get("math.predisplaypenalty"), vertical = true }) SILE.settings:temporarily(function () -- Center the equation in the space available up to the counter (if any), -- respecting the fixed part of the left and right skips. @@ -233,9 +240,14 @@ local function handleMath (_, mbox, options) elseif options.number then SILE.call("math:numberingstyle", options) end - SILE.typesetter:endline() + -- The vertical penalty will flush the equation. + -- It must be done in the temporary settings block, because these have + -- to apply as line boxes are being built. + SILE.call("penalty", { penalty = SILE.settings:get("math.postdisplaypenalty"), vertical = true }) end) SILE.typesetter:pushExplicitVglue(SILE.settings:get("math.displayskip")) + -- Repeating: Same remark as for the predisplay penalty above. + SILE.call("penalty", { penalty = SILE.settings:get("math.postdisplaypenalty"), vertical = true }) else SILE.typesetter:pushHorizontal(mbox) end