fix: a header/footer's gap to the body is inside its band, not above it

The body margin reserved the zone's height *plus* its fo:margin-top/-bottom, so
every page with a footer lost a line — a fixture ran a page over. Probed against
soffice: moving a footer's fo:margin-top leaves the last body line exactly where
it was and only shifts the footer text down its band; style:dynamic-spacing
changes neither side. The band is the declared height, the gap sits in it.

One fixture paginates to LibreOffice's 63 pages again.
This commit is contained in:
Steffen Becker committed 2026-08-10 19:34:53 +00:00
1 parent d6c3602429
commit 71ecc17a9e
2 files changed
+9 -9

No files matched your search

+5 -6
View File
@@ -587,12 +587,11 @@ export class StyleResolver {
const height = lengthToCm(props.getAttributeNS(NS.svg, 'height'))
?? lengthToCm(props.getAttributeNS(NS.fo, 'min-height'))
?? 0;
// style:dynamic-spacing="true" makes the header↔body gap collapsible (the header
// grows into it), so the body isn't pushed down by it. Only fixed (non-dynamic)
// spacing is added to the body margin.
const dynamic = props.getAttributeNS(NS.style, 'dynamic-spacing') === 'true';
const spacing = dynamic ? 0 : (lengthToCm(props.getAttributeNS(NS.fo, spacingAttr)) ?? 0);
return height + spacing;
// The zone's gap to the body is laid out *inside* that height, not added to it
// (probed: a footer's fo:margin-top moves its text down the band and leaves the
// last body line where it was; style:dynamic-spacing changes neither side).
const spacing = lengthToCm(props.getAttributeNS(NS.fo, spacingAttr)) ?? 0;
return Math.max(height, spacing);
};
return {