Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions tests/layout/test_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -840,3 +840,46 @@ def test_first_letter_float():
assert first_letter.position_x == 0
# TODO: fix problem described in #1859.
# assert text.position_x == 20


@assert_no_logs
def test_float_break_after_page():
# https://github.com/Kozea/WeasyPrint/issues/2277
# break-after: page on a floated element should force a page break.
pages = render_pages('''
<style>
@page { size: 100px; margin: 10px }
</style>
<div style="break-after: page; float: left">float</div>
<div>end</div>
''')
assert len(pages) == 2
html1, = pages[0].children
body1, = html1.children
float_div, = body1.children
assert float_div.position_y == 10
html2, = pages[1].children
body2, = html2.children
end_div, = body2.children
assert end_div.position_y == 10


@assert_no_logs
def test_float_break_before_page():
# break-before: page on a floated element should force a page break.
pages = render_pages('''
<style>
@page { size: 100px; margin: 10px }
</style>
<div>start</div>
<div style="break-before: page; float: left">float</div>
''')
assert len(pages) == 2
html1, = pages[0].children
body1, = html1.children
start_div, = body1.children
assert start_div.position_y == 10
html2, = pages[1].children
body2, = html2.children
float_div, = body2.children
assert float_div.position_y == 10
35 changes: 31 additions & 4 deletions weasyprint/layout/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def relative_positioning(box, containing_block):

def _out_of_flow_layout(context, box, index, child, new_children,
page_is_empty, absolute_boxes, fixed_boxes,
adjoining_margins, bottom_space):
adjoining_margins, bottom_space, next_page):
stop = False # whether we should stop parent rendering after this layout
resume_at = None # where to resume in-flow rendering
new_child = None # child rendered by this layout
Expand All @@ -260,10 +260,36 @@ def _out_of_flow_layout(context, box, index, child, new_children,

# Float child layout.
elif child.is_floated():
# Check for forced break-before on the float.
# https://drafts.csswg.org/css-break/#break-between
last_in_flow_child = find_last_in_flow_child(new_children)
if last_in_flow_child is not None:
page_break = block_level_page_break(last_in_flow_child, child)
if force_page_break(page_break, context):
page_name = child.page_values()[0]
next_page = {'break': page_break, 'page': page_name}
resume_at = {index: None}
stop = True
return (
stop, resume_at, new_child, out_of_flow_resume_at,
next_page)

new_child, out_of_flow_resume_at = float_layout(
context, child, box, absolute_boxes, fixed_boxes, bottom_space,
skip_stack=None)

# Check for forced break-after on the float.
page_break = child.style['break_after']
if force_page_break(page_break, context):
new_child.index = index
new_children.append(new_child)
page_name = child.page_values()[1]
next_page = {'break': page_break, 'page': page_name}
resume_at = {index + 1: None}
stop = True
return (
stop, resume_at, new_child, out_of_flow_resume_at, next_page)

# Check that child doesn’t overflow page.
page_overflow = context.overflows_page(
bottom_space, new_child.position_y + new_child.height)
Expand Down Expand Up @@ -298,7 +324,7 @@ def _out_of_flow_layout(context, box, index, child, new_children,
page = context.current_page
context.running_elements[running_name][page].append(child)

return stop, resume_at, new_child, out_of_flow_resume_at
return stop, resume_at, new_child, out_of_flow_resume_at, next_page


def _break_line(context, box, line, new_children, needed, page_is_empty, index,
Expand Down Expand Up @@ -734,10 +760,11 @@ def block_container_layout(context, box, bottom_space, skip_stack, page_is_empty
if not child.is_in_normal_flow():
# Layout out-of-flow child.
abort = False
stop, resume_at, new_child, out_of_flow_resume_at = (
stop, resume_at, new_child, out_of_flow_resume_at, next_page = (
_out_of_flow_layout(
context, box, index, child, new_children, page_is_empty,
absolute_boxes, fixed_boxes, adjoining_margins, bottom_space))
absolute_boxes, fixed_boxes, adjoining_margins,
bottom_space, next_page))
if out_of_flow_resume_at:
context.add_broken_out_of_flow(
new_child, child, box, out_of_flow_resume_at)
Expand Down