mirror of
https://github.com/Kozea/WeasyPrint.git
synced 2024-10-05 00:21:15 +03:00
Handle margin-break
Some corner-cases are not handled yet, but that's much better than the current situation. Fix #115.
This commit is contained in:
parent
5fc905baa1
commit
75d8d983ae
@ -124,6 +124,7 @@ INITIAL_VALUES = {
|
||||
'break_after': 'auto',
|
||||
'break_before': 'auto',
|
||||
'break_inside': 'auto',
|
||||
'margin_break': 'auto',
|
||||
'orphans': 2,
|
||||
'widows': 2,
|
||||
|
||||
|
@ -301,6 +301,13 @@ def break_inside(keyword):
|
||||
return keyword in ('auto', 'avoid', 'avoid-page', 'avoid-column')
|
||||
|
||||
|
||||
@property()
|
||||
@single_keyword
|
||||
def margin_break(keyword):
|
||||
"""``margin-break`` property validation."""
|
||||
return keyword in ('auto', 'keep', 'discard')
|
||||
|
||||
|
||||
@property(unstable=True)
|
||||
@single_token
|
||||
def page(token):
|
||||
|
@ -204,6 +204,7 @@ class LayoutContext(object):
|
||||
self.excluded_shapes = None # Not initialized yet
|
||||
self.string_set = defaultdict(lambda: defaultdict(lambda: list()))
|
||||
self.current_page = None
|
||||
self.forced_break = False
|
||||
|
||||
# Cache
|
||||
self.strut_layouts = {}
|
||||
|
@ -41,6 +41,15 @@ def block_level_layout(context, box, max_position_y, skip_stack,
|
||||
if box.margin_bottom == 'auto':
|
||||
box.margin_bottom = 0
|
||||
|
||||
if (context.current_page > 1 and page_is_empty):
|
||||
# TODO: we should take care of cases when this box doesn't have
|
||||
# collaping borders with the first child of the page, see
|
||||
# test_margin_break_clearance.
|
||||
if box.style['margin_break'] == 'discard':
|
||||
box.margin_top = 0
|
||||
elif box.style['margin_break'] == 'auto' and context.forced_break:
|
||||
box.margin_top = 0
|
||||
|
||||
collapsed_margin = collapse_margin(
|
||||
adjoining_margins + [box.margin_top])
|
||||
box.clearance = get_clearance(context, box, collapsed_margin)
|
||||
@ -428,11 +437,6 @@ def block_container_layout(context, box, max_position_y, skip_stack,
|
||||
page_name = block_level_page_name(last_in_flow_child, child)
|
||||
if page_name or page_break in (
|
||||
'page', 'left', 'right', 'recto', 'verso'):
|
||||
if page_break == 'page':
|
||||
page_break = 'any'
|
||||
elif page_break not in ('left', 'right', 'recto', 'verso'):
|
||||
assert page_name
|
||||
page_break = 'any'
|
||||
page_name = child.page_values()[0]
|
||||
next_page = {'break': page_break, 'page': page_name}
|
||||
resume_at = (index, None)
|
||||
|
@ -545,6 +545,7 @@ def make_page(context, root_box, page_type, resume_at, page_number,
|
||||
# See http://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo
|
||||
assert isinstance(root_box, (boxes.BlockBox, boxes.FlexContainerBox))
|
||||
context.create_block_formatting_context()
|
||||
context.current_page = page_number
|
||||
page_is_empty = True
|
||||
adjoining_margins = []
|
||||
positioned_boxes = [] # Mixed absolute and fixed
|
||||
@ -722,16 +723,20 @@ def remake_page(index, context, root_box, html, cascaded_styles,
|
||||
page_state = copy.deepcopy(initial_page_state)
|
||||
next_page_name = initial_next_page['page']
|
||||
first = index == 0
|
||||
# TODO: handle recto/verso and add test
|
||||
blank = ((initial_next_page['break'] == 'left' and right_page) or
|
||||
(initial_next_page['break'] == 'right' and not right_page))
|
||||
if blank:
|
||||
next_page_name = None
|
||||
side = 'right' if right_page else 'left'
|
||||
page_type = PageType(
|
||||
side, blank, first, name=(next_page_name or None))
|
||||
page_type = PageType(side, blank, first, name=(next_page_name or None))
|
||||
set_page_type_computed_styles(
|
||||
page_type, cascaded_styles, computed_styles, html)
|
||||
|
||||
context.forced_break = (
|
||||
initial_next_page['break'] != 'any' or initial_next_page['page'])
|
||||
context.margin_clearance = False
|
||||
|
||||
# make_page wants a page_number of index + 1
|
||||
page_number = index + 1
|
||||
page, resume_at, next_page = make_page(
|
||||
|
@ -427,6 +427,75 @@ def test_page_breaks_complex_8():
|
||||
assert div_4.height == 20
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@pytest.mark.parametrize('break_after, margin_break, margin_top', (
|
||||
('page', 'auto', 0),
|
||||
('auto', 'auto', 5),
|
||||
('page', 'keep', 5),
|
||||
('auto', 'keep', 5),
|
||||
('page', 'discard', 0),
|
||||
('auto', 'discard', 0),
|
||||
))
|
||||
def test_margin_break(break_after, margin_break, margin_top):
|
||||
page_1, page_2 = render_pages('''
|
||||
<style>
|
||||
@page { size: 70px; margin: 0 }
|
||||
div { height: 63px; margin: 5px 0 8px;
|
||||
break-after: %s; margin-break: %s }
|
||||
</style>
|
||||
<section>
|
||||
<div></div>
|
||||
</section>
|
||||
<section>
|
||||
<div></div>
|
||||
</section>
|
||||
''' % (break_after, margin_break))
|
||||
html, = page_1.children
|
||||
body, = html.children
|
||||
section, = body.children
|
||||
div, = section.children
|
||||
assert div.margin_top == 5
|
||||
|
||||
html, = page_2.children
|
||||
body, = html.children
|
||||
section, = body.children
|
||||
div, = section.children
|
||||
assert div.margin_top == margin_top
|
||||
|
||||
|
||||
@pytest.mark.xfail
|
||||
@assert_no_logs
|
||||
def test_margin_break_clearance():
|
||||
page_1, page_2 = render_pages('''
|
||||
<style>
|
||||
@page { size: 70px; margin: 0 }
|
||||
div { height: 63px; margin: 5px 0 8px; break-after: page }
|
||||
</style>
|
||||
<section>
|
||||
<div></div>
|
||||
</section>
|
||||
<section>
|
||||
<div style="border-top: 1px solid black">
|
||||
<div></div>
|
||||
</div>
|
||||
</section>
|
||||
''')
|
||||
html, = page_1.children
|
||||
body, = html.children
|
||||
section, = body.children
|
||||
div, = section.children
|
||||
assert div.margin_top == 5
|
||||
|
||||
html, = page_2.children
|
||||
body, = html.children
|
||||
section, = body.children
|
||||
div_1, = section.children
|
||||
assert div_1.margin_top == 0
|
||||
div_2, = div_1.children
|
||||
assert div_2.margin_top == 5
|
||||
assert div_2.content_box_y() == 5
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_page_names_1():
|
||||
pages = render_pages('''
|
||||
|
Loading…
Reference in New Issue
Block a user