mirror of
https://github.com/Kozea/WeasyPrint.git
synced 2024-10-04 07:57:52 +03:00
Take care of floats when removing placeholders
Removing placeholders is something we have to do when we must discard a part of the layout that has already been done. It currently removes absolutely positioned placeholders and footnotes. The same has to be done with split floats, that’s what this commit is about. We have to change the structure of the broken_out_of_flow attribute, as we have to get a reliable way to reach the saved data using from the real element in the tree. The new structure is thus a dictionary whose keys are the boxes in the tree (placeholder for absolutes, partial elements for floats) and whose values are the original_box+parent+resume_at. Fix #1669.
This commit is contained in:
parent
74f367c2a3
commit
902bde7d9c
@ -659,3 +659,84 @@ def test_float_split_10(assert_pixels):
|
||||
<div>bbbbb bbbbb</div>
|
||||
<div class="split">aa aa</div>
|
||||
<div>bbb bbb</div>''')
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_float_split_11(assert_pixels):
|
||||
assert_pixels('''
|
||||
BBBBBBBBBBBBBBBB
|
||||
BBBBBBBBBBBBBBBB
|
||||
BBBBBBBBBBBBBBBB
|
||||
BBBBBBBBBBBBBBBB
|
||||
BBBBBBBBBBBBBBBB
|
||||
BBBBGG______BBBB
|
||||
BBBBGG______BBBB
|
||||
BBBB________BBBB
|
||||
BBBB________BBBB
|
||||
________________
|
||||
''', '''
|
||||
<style>
|
||||
@font-face {src: url(weasyprint.otf); font-family: weasyprint}
|
||||
@page {
|
||||
size: 16px 5px;
|
||||
}
|
||||
body {
|
||||
color: lime;
|
||||
font-family: weasyprint;
|
||||
font-size: 2px;
|
||||
line-height: 1;
|
||||
}
|
||||
article {
|
||||
background: blue;
|
||||
height: 5px;
|
||||
}
|
||||
div {
|
||||
background: red;
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
<article></article>
|
||||
a
|
||||
<div style="float: left"><p>aa<p>aa</div>
|
||||
<div style="float: right"><p>bb<p>bb</div>''')
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_float_split_12(assert_pixels):
|
||||
assert_pixels('''
|
||||
BBBBBBBBBBBBBBBB
|
||||
BBBBBBBBBBBBBBBB
|
||||
BBBBBBBBBBBBBBBB
|
||||
BBBBBBBBBBBBBBBB
|
||||
BBBBBBBBBBBBBBBB
|
||||
BBBBGG______BBBB
|
||||
BBBBGG______BBBB
|
||||
BBBB________BBBB
|
||||
BBBB________BBBB
|
||||
________________
|
||||
''', '''
|
||||
<style>
|
||||
@font-face {src: url(weasyprint.otf); font-family: weasyprint}
|
||||
@page {
|
||||
size: 16px 5px;
|
||||
}
|
||||
body {
|
||||
color: lime;
|
||||
font-family: weasyprint;
|
||||
font-size: 2px;
|
||||
line-height: 1;
|
||||
}
|
||||
article {
|
||||
background: blue;
|
||||
height: 5px;
|
||||
}
|
||||
div {
|
||||
background: red;
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
<article></article>
|
||||
<section>
|
||||
<div style="float: left"><p>aa<p>aa</div>
|
||||
a
|
||||
<div style="float: right"><p>bb<p>bb</div>''')
|
||||
|
@ -233,7 +233,7 @@ class LayoutContext:
|
||||
self.running_elements = defaultdict(lambda: defaultdict(lambda: []))
|
||||
self.current_page = None
|
||||
self.forced_break = False
|
||||
self.broken_out_of_flow = []
|
||||
self.broken_out_of_flow = {}
|
||||
self.in_column = False
|
||||
|
||||
# Cache
|
||||
|
@ -229,7 +229,8 @@ def absolute_layout(context, placeholder, containing_block, fixed_boxes,
|
||||
context, box, containing_block, fixed_boxes, bottom_space, skip_stack)
|
||||
placeholder.set_laid_out_box(new_box)
|
||||
if resume_at:
|
||||
context.broken_out_of_flow.append((box, containing_block, resume_at))
|
||||
context.broken_out_of_flow[placeholder] = (
|
||||
box, containing_block, resume_at)
|
||||
|
||||
|
||||
def absolute_box_layout(context, box, containing_block, fixed_boxes,
|
||||
|
@ -230,7 +230,7 @@ def _out_of_flow_layout(context, box, index, child, new_children,
|
||||
|
||||
child.position_y += collapse_margin(adjoining_margins)
|
||||
if child.is_absolutely_positioned():
|
||||
placeholder = AbsolutePlaceholder(child)
|
||||
new_child = placeholder = AbsolutePlaceholder(child)
|
||||
placeholder.index = index
|
||||
new_children.append(placeholder)
|
||||
if child.style['position'] == 'absolute':
|
||||
@ -262,7 +262,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, out_of_flow_resume_at
|
||||
return stop, resume_at, new_child, out_of_flow_resume_at
|
||||
|
||||
|
||||
def _break_line(context, box, line, new_children, lines_iterator,
|
||||
@ -629,7 +629,7 @@ def block_container_layout(context, box, bottom_space, skip_stack,
|
||||
new_children = []
|
||||
next_page = {'break': 'any', 'page': None}
|
||||
all_footnotes = []
|
||||
broken_out_of_flow = []
|
||||
broken_out_of_flow = {}
|
||||
|
||||
last_in_flow_child = None
|
||||
|
||||
@ -649,12 +649,14 @@ def block_container_layout(context, box, bottom_space, skip_stack,
|
||||
|
||||
if not child.is_in_normal_flow():
|
||||
abort = False
|
||||
stop, resume_at, out_of_flow_resume_at = _out_of_flow_layout(
|
||||
stop, resume_at, new_child, out_of_flow_resume_at = (
|
||||
_out_of_flow_layout(
|
||||
context, box, index, child, new_children, page_is_empty,
|
||||
absolute_boxes, fixed_boxes, adjoining_margins,
|
||||
bottom_space)
|
||||
bottom_space))
|
||||
if out_of_flow_resume_at:
|
||||
broken_out_of_flow.append((child, box, out_of_flow_resume_at))
|
||||
broken_out_of_flow[new_child] = (
|
||||
child, box, out_of_flow_resume_at)
|
||||
|
||||
elif isinstance(child, boxes.LineBox):
|
||||
(abort, stop, resume_at, position_y,
|
||||
@ -696,6 +698,8 @@ def block_container_layout(context, box, bottom_space, skip_stack,
|
||||
|
||||
if abort:
|
||||
page = child.page_values()[0]
|
||||
remove_placeholders(
|
||||
context, box.children[skip:], absolute_boxes, fixed_boxes)
|
||||
for footnote in new_footnotes:
|
||||
context.unlayout_footnote(footnote)
|
||||
return (
|
||||
@ -720,7 +724,8 @@ def block_container_layout(context, box, bottom_space, skip_stack,
|
||||
return (
|
||||
None, None, {'break': 'any', 'page': None}, [], False, max_lines)
|
||||
|
||||
context.broken_out_of_flow.extend(broken_out_of_flow)
|
||||
for key, value in broken_out_of_flow.items():
|
||||
context.broken_out_of_flow[key] = value
|
||||
|
||||
if collapsing_with_children:
|
||||
box.position_y += (
|
||||
@ -1005,6 +1010,8 @@ def remove_placeholders(context, box_list, absolute_boxes, fixed_boxes):
|
||||
For boxes that have been removed in find_earlier_page_break(), remove the
|
||||
matching placeholders in absolute_boxes and fixed_boxes.
|
||||
|
||||
Also takes care of removed footnotes and floats.
|
||||
|
||||
"""
|
||||
for box in box_list:
|
||||
if isinstance(box, boxes.ParentBox):
|
||||
@ -1017,6 +1024,8 @@ def remove_placeholders(context, box_list, absolute_boxes, fixed_boxes):
|
||||
fixed_boxes.remove(box)
|
||||
if box.footnote:
|
||||
context.unlayout_footnote(box.footnote)
|
||||
if box in context.broken_out_of_flow:
|
||||
context.broken_out_of_flow.pop(box)
|
||||
|
||||
|
||||
def avoid_page_break(page_break, context):
|
||||
|
@ -169,8 +169,8 @@ def get_next_linebox(context, linebox, position_y, bottom_space, skip_stack,
|
||||
fixed_boxes, bottom_space, skip_stack=None)
|
||||
float_children.append(new_waiting_float)
|
||||
if waiting_float_resume_at:
|
||||
context.broken_out_of_flow.append(
|
||||
(waiting_float, containing_block, waiting_float_resume_at))
|
||||
context.broken_out_of_flow[new_waiting_float] = (
|
||||
waiting_float, containing_block, waiting_float_resume_at)
|
||||
if float_children:
|
||||
line.children += tuple(float_children)
|
||||
|
||||
@ -559,8 +559,8 @@ def _out_of_flow_layout(context, box, containing_block, index, child,
|
||||
context, child, containing_block, absolute_boxes, fixed_boxes,
|
||||
bottom_space, skip_stack=None)
|
||||
if float_resume_at:
|
||||
context.broken_out_of_flow.append(
|
||||
(child, containing_block, float_resume_at))
|
||||
context.broken_out_of_flow[child] = (
|
||||
child, containing_block, float_resume_at)
|
||||
waiting_children.append((index, new_child, child))
|
||||
child = new_child
|
||||
|
||||
|
@ -564,8 +564,9 @@ def make_page(context, root_box, page_type, resume_at, page_number,
|
||||
adjoining_margins = []
|
||||
positioned_boxes = [] # Mixed absolute and fixed
|
||||
out_of_flow_boxes = []
|
||||
broken_out_of_flow = []
|
||||
for box, containing_block, skip_stack in context.broken_out_of_flow:
|
||||
broken_out_of_flow = {}
|
||||
context_out_of_flow = context.broken_out_of_flow.values()
|
||||
for box, containing_block, skip_stack in context_out_of_flow:
|
||||
box.position_y = 0
|
||||
if box.is_floated():
|
||||
out_of_flow_box, out_of_flow_resume_at = float_layout(
|
||||
@ -578,8 +579,8 @@ def make_page(context, root_box, page_type, resume_at, page_number,
|
||||
skip_stack)
|
||||
out_of_flow_boxes.append(out_of_flow_box)
|
||||
if out_of_flow_resume_at:
|
||||
broken_out_of_flow.append(
|
||||
(box, containing_block, out_of_flow_resume_at))
|
||||
broken_out_of_flow[out_of_flow_box] = (
|
||||
box, containing_block, out_of_flow_resume_at)
|
||||
context.broken_out_of_flow = broken_out_of_flow
|
||||
root_box, resume_at, next_page, _, _, _ = block_level_layout(
|
||||
context, root_box, 0, resume_at, initial_containing_block,
|
||||
|
Loading…
Reference in New Issue
Block a user