From 9b0a672acd67c559b8280bf80f7fc97b1d13ce19 Mon Sep 17 00:00:00 2001 From: aschmitz <29508+aschmitz@users.noreply.github.com> Date: Tue, 1 Feb 2022 18:13:39 -0600 Subject: [PATCH] fix: handle float rounding when extending boxes over page breaks When a box would break over the edge of a page, its height is extended to the bottom of that page (per https://www.w3.org/TR/css-break-3/#box-splitting , primarily to allow backgrounds and borders to continue to the end of the page). When this happened, sometimes the values that would be calculated for the height of the extended element would be rounded *over* the calculated height that remained on the page, forcing the entire containing box to wrap to the next page. Rather than trying to carefully manage the order of operations to try to be safe in IEEE floats for directions, we apply a small "fudge factor": if an element fits very nearly (within a thousandth of a pixel) into the remaining space, it is still accepted. --- tests/layout/test_page.py | 34 ++++++++++++++++++++++++++++++++++ weasyprint/layout/block.py | 8 +++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/tests/layout/test_page.py b/tests/layout/test_page.py index 36e9a026f..878112869 100644 --- a/tests/layout/test_page.py +++ b/tests/layout/test_page.py @@ -141,6 +141,40 @@ def test_page_breaks(html): for page_child in page_children] == [[10, 40], [10, 40], [10]] +@assert_no_logs +def test_page_breaks_box_split(): + # If floats round the wrong way, a block that gets filled to the end of a + # page due to breaking over the page may be forced onto the next page + # because it is slightly taller than can fit on the previous page, even if + # it wouldn't have been without being filled. These numbers aren't ideal, + # but they do seem to trigger the issue. + page_1, page_2 = render_pages(''' + +