Skip to content

Commit

Permalink
Merge pull request #631 from Tontyna/pagebased-counters
Browse files Browse the repository at this point in the history
Enable counter-increment and -reset in page context
  • Loading branch information
liZe authored May 24, 2018
2 parents 488241c + e56ffb9 commit 85279f4
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 8 deletions.
18 changes: 13 additions & 5 deletions weasyprint/layout/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,29 @@ def layout_document(enable_hinting, style_for, get_image_from_uri, root_box,
target_collector)
pages = list(make_all_pages(
context, root_box, html, cascaded_styles, computed_styles))
page_counter = [1]
counter_values = {'page': page_counter, 'pages': [len(pages)]}

# although neither a variable quote_depth nor counter_scopes are needed
# in page-boxes -- reusing `formatting_structure.build.update_counters()`
# to avoid redundant code requires a full `state`
state = (
# Shared mutable objects:
[0], # quote_depth: single integer
# initialize with the fixed `pages` counter
{'pages': [len(pages)]}, # counter_values
[{'pages'}] # counter_scopes
)
for i, page in enumerate(pages):
root_children = []
root, = page.children
root_children.extend(layout_fixed_boxes(context, pages[:i]))
root_children.extend(root.children)
root_children.extend(layout_fixed_boxes(context, pages[i + 1:]))
root.children = root_children
context.current_page = page_counter[0]
context.current_page = i+1 # page_number starts at 1
page.children = (root,) + tuple(
make_margin_boxes(context, page, counter_values, target_collector))
make_margin_boxes(context, page, state, target_collector))
layout_backgrounds(page, get_image_from_uri)
yield page
page_counter[0] += 1


class LayoutContext(object):
Expand Down
46 changes: 43 additions & 3 deletions weasyprint/layout/pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"""

import copy

from ..css import (
PageType, computed_from_cascaded, matching_page_types, set_computed_styles)
from ..formatting_structure import boxes, build
Expand Down Expand Up @@ -281,7 +283,33 @@ def compute_variable_dimension(context, side_boxes, vertical, outer_sum):
box.restore_box_attributes()


def make_margin_boxes(context, page, counter_values, target_collector):
def _standardize_page_based_counters(style, pseudo_type):
"""
drop 'pages' counter from style in @page and @margin context
ensure `counter-increment: page` for @page context if not otherwise
manipulated by the style
"""
page_counter_touched = False
# XXX 'counter-set` not yet supported
for propname in ['counter_reset', 'counter_increment']:
# counter_increment could be 'auto'
if not isinstance(style[propname], tuple):
style[propname] = ()
continue
justified_values = []
for name, value in style[propname]:
if name == 'page':
page_counter_touched = True
if name != 'pages':
justified_values.append((name, value))
style[propname] = tuple(justified_values)

if pseudo_type is None and not page_counter_touched:
style['counter_increment'] = (
('page', 1),) + style['counter_increment']


def make_margin_boxes(context, page, state, target_collector):
"""Yield laid-out margin boxes for this page."""
# This is a closure only to make calls shorter
def make_box(at_keyword, containing_block):
Expand All @@ -298,8 +326,10 @@ def make_box(at_keyword, containing_block):

style = context.style_for(page.page_type, at_keyword)
if style is None:
# doesn't affect counters
style = computed_from_cascaded(
element=None, cascaded={}, parent_style=page.style)
_standardize_page_based_counters(style, at_keyword)
box = boxes.MarginBox(at_keyword, style)
# Empty boxes should not be generated, but they may be needed for
# the layout of their neighbors.
Expand All @@ -308,7 +338,12 @@ def make_box(at_keyword, containing_block):
'normal', 'inhibit', 'none')
# TODO: get actual counter values at the time of the last page break
if box.is_generated:
quote_depth = [0]
# @margins mustn't manipulate page-context counters
margin_state = copy.deepcopy(state)
quote_depth, counter_values, counter_scopes = margin_state
# not 100% shure about this
counter_scopes.append(set())
build.update_counters(margin_state, box.style)
box.children = build.content_to_boxes(
box.style, box, quote_depth, counter_values,
context.get_image_from_uri, target_collector, context, page)
Expand All @@ -323,6 +358,11 @@ def make_box(at_keyword, containing_block):
box._reset_spacing(side)
return box

style = page.style
_standardize_page_based_counters(style, None)
# apply counter-* styles
build.update_counters(state, style)

margin_top = page.margin_top
margin_bottom = page.margin_bottom
margin_left = page.margin_left
Expand Down Expand Up @@ -469,7 +509,7 @@ def page_height(box, context, containing_block_height):
page_width_or_height(VerticalBox(context, box), containing_block_height)


def make_page(context, root_box, page_type, resume_at, page_number=None):
def make_page(context, root_box, page_type, resume_at, page_number):
"""Take just enough content from the beginning to fill one page.
Return ``(page, finished)``. ``page`` is a laid out PageBox object
Expand Down

0 comments on commit 85279f4

Please sign in to comment.