Skip to content

Commit

Permalink
Avoid floating points errors (almost) everywhere
Browse files Browse the repository at this point in the history
Related to #1559.
  • Loading branch information
liZe committed Feb 20, 2022
1 parent b33df96 commit fe3e3b9
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 22 deletions.
5 changes: 5 additions & 0 deletions weasyprint/layout/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,11 @@ def __init__(self, style_for, get_image_from_uri, font_config,
self.tables = {}
self.dictionaries = {}

def overflows_page(self, bottom_space, position_y):
# Use a small fudge factor to avoid floating numbers errors.
# The 1e-9 value comes from PEP 485.
return position_y > (self.page_bottom - bottom_space) * (1 + 1e-9)

def create_block_formatting_context(self):
self.excluded_shapes = []
self._excluded_shapes_lists.append(self.excluded_shapes)
Expand Down
35 changes: 15 additions & 20 deletions weasyprint/layout/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,9 @@ def _out_of_flow_layout(context, box, index, child, new_children,
context, child, box, absolute_boxes, fixed_boxes, bottom_space,
skip_stack=None)
# New page if overflow
if (page_is_empty and not new_children) or not (
new_child.position_y + new_child.height >
context.page_bottom - bottom_space):
page_overflow = context.overflows_page(
bottom_space, new_child.position_y + new_child.height)
if (page_is_empty and not new_children) or not page_overflow:
new_child.index = index
new_children.append(new_child)
else:
Expand Down Expand Up @@ -315,7 +315,7 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
# page and can advance in the context.
overflow = (
(new_children or not page_is_empty) and
(new_position_y + offset_y > context.page_bottom - bottom_space))
context.overflows_page(bottom_space, new_position_y + offset_y))
if overflow:
abort, stop, resume_at = _break_line(
box, new_children, lines_iterator, page_is_empty, index,
Expand All @@ -327,8 +327,8 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
# "When an unforced page break occurs here, both the adjoining
# ‘margin-top’ and ‘margin-bottom’ are set to zero."
# See https://github.com/Kozea/WeasyPrint/issues/115
elif page_is_empty and (
new_position_y > context.page_bottom - bottom_space):
elif page_is_empty and context.overflows_page(
bottom_space, new_position_y):
# Remove the top border when a page is empty and the box is
# too high to be drawn in one page
new_position_y -= box.margin_top
Expand All @@ -343,9 +343,10 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
for footnote in footnotes:
context.layout_footnote(footnote)
new_footnotes.append(footnote)
overflow = context.reported_footnotes or (
new_position_y + offset_y >
context.page_bottom - bottom_space)
overflow = (
context.reported_footnotes or
context.overflows_page(
bottom_space, new_position_y + offset_y))
if overflow:
context.report_footnote(footnote)
if footnote.style['footnote_policy'] == 'line':
Expand Down Expand Up @@ -464,22 +465,16 @@ def _in_flow_layout(context, box, index, child, new_children, page_is_empty,
new_position_y = (
new_child.border_box_y() + new_child.border_height())

# Use a small fudge factor on this due to box splitting setting the
# height of some elements to the remaining height of the page:
# https://www.w3.org/TR/css-break-3/#box-splitting
# (Occasionally the order of this calculation would otherwise come
# out with unequal float values, forcing the box to the next page.)
# The 1e-9 value comes from PEP 485.
if (new_content_position_y >
(context.page_bottom - bottom_space) * (1 + 1e-9) and
not page_is_empty_with_no_children):
page_overflow = context.overflows_page(
bottom_space, new_content_position_y)
if page_overflow and not page_is_empty_with_no_children:
# The child content overflows the page area, display it on the
# next page.
remove_placeholders(
context, [new_child], absolute_boxes, fixed_boxes)
new_child = None
elif (new_position_y > context.page_bottom - bottom_space and
not page_is_empty_with_no_children):
elif not page_is_empty_with_no_children and context.overflows_page(
bottom_space, new_position_y):
# The child border/padding overflows the page area, do the
# layout again with a higher bottom_space value.
remove_placeholders(
Expand Down
4 changes: 2 additions & 2 deletions weasyprint/layout/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ def group_layout(group, position_y, bottom_space, page_is_empty,

# Break if this row overflows the page, unless there is no
# other content on the page.
if not page_is_empty and (
next_position_y > context.page_bottom - bottom_space):
if not page_is_empty and context.overflows_page(
bottom_space, next_position_y):
if new_group_children:
previous_row = new_group_children[-1]
page_break = block_level_page_break(previous_row, row)
Expand Down

0 comments on commit fe3e3b9

Please sign in to comment.