def make_page(context, root_box, page_type, resume_at, page_number,
              page_state):
    """Take just enough content from the beginning to fill one page.

    Return ``(page, finished)``. ``page`` is a laid out PageBox object
    and ``resume_at`` indicates where in the document to start the next page,
    or is ``None`` if this was the last page.

    :param int page_number:
        Page number, starts at 1 for the first page.
    :param resume_at:
        As returned by ``make_page()`` for the previous page, or ``None`` for
        the first page.

    """
    style = context.style_for(page_type)

    # Propagated from the root or <body>.
    style['overflow'] = root_box.viewport_overflow
    page = boxes.PageBox(page_type, style)

    device_size = page.style['size']

    resolve_percentages(page, device_size)

    page.position_x = 0
    page.position_y = 0
    cb_width, cb_height = device_size
    page_width(page, context, cb_width)
    page_height(page, context, cb_height)

    root_box.position_x = page.content_box_x()
    root_box.position_y = page.content_box_y()
    context.page_bottom = root_box.position_y + page.height
    initial_containing_block = page

    footnote_area_style = context.style_for(page_type, '@footnote')
    footnote_area = boxes.FootnoteAreaBox(page, footnote_area_style)
    resolve_percentages(footnote_area, page)
    footnote_area.position_x = page.content_box_x()
    footnote_area.position_y = context.page_bottom

    if page_type.blank:
        previous_resume_at = resume_at
        root_box = root_box.copy_with_children([])

    # https://www.w3.org/TR/css-display-4/#root
    assert isinstance(root_box, boxes.BlockLevelBox)
    context.create_block_formatting_context()
    context.current_page = page_number
    context.current_page_footnotes = []
    context.current_footnote_area = footnote_area

    reported_footnotes = context.reported_footnotes
    context.reported_footnotes = []
    for i, reported_footnote in enumerate(reported_footnotes):
        context.footnotes.append(reported_footnote)
        overflow = context.layout_footnote(reported_footnote)
        if overflow and i != 0:
            context.report_footnote(reported_footnote)
            context.reported_footnotes = reported_footnotes[i:]
            break

    page_is_empty = True
    adjoining_margins = []
    positioned_boxes = []  # Mixed absolute and fixed
    out_of_flow_boxes = []
    broken_out_of_flow = {}
    context_out_of_flow = context.broken_out_of_flow.values()
    context.broken_out_of_flow = broken_out_of_flow
    for box, containing_block, skip_stack in context_out_of_flow:
        box.position_y = root_box.content_box_y()
        if box.is_floated():
            out_of_flow_box, out_of_flow_resume_at = float_layout(
                context, box, containing_block, positioned_boxes,
                positioned_boxes, 0, skip_stack)
        else:
            assert box.is_absolutely_positioned()
            out_of_flow_box, out_of_flow_resume_at = absolute_box_layout(
                context, box, containing_block, positioned_boxes, 0,
                skip_stack)
        out_of_flow_boxes.append(out_of_flow_box)
        if out_of_flow_resume_at:
            broken_out_of_flow[out_of_flow_box] = (
                box, containing_block, out_of_flow_resume_at)
    root_box, resume_at, next_page, _, _, _ = block_level_layout(
        context, root_box, 0, resume_at, initial_containing_block,
        page_is_empty, positioned_boxes, positioned_boxes, adjoining_margins)
    assert root_box
    root_box.children = out_of_flow_boxes + root_box.children

    footnote_area = build.create_anonymous_boxes(footnote_area.deepcopy())
    footnote_area = block_level_layout(
        context, footnote_area, -inf, None, footnote_area.page, True,
        positioned_boxes, positioned_boxes)[0]
    footnote_area.translate(dy=-footnote_area.margin_height())

    page.fixed_boxes = [
        placeholder._box for placeholder in positioned_boxes
        if placeholder._box.style['position'] == 'fixed']
    for absolute_box in positioned_boxes:
        absolute_layout(
            context, absolute_box, page, positioned_boxes, bottom_space=0,
            skip_stack=None)

    context.finish_block_formatting_context(root_box)

    page.children = [root_box, footnote_area]

    # Update page counter values
    _standardize_page_based_counters(style, None)
    build.update_counters(page_state, style)
    page_counter_values = page_state[1]
    # page_counter_values will be cached in the page_maker

    target_collector = context.target_collector
    page_maker = context.page_maker

    # remake_state tells the make_all_pages-loop in layout_document()
    # whether and what to re-make.
    remake_state = page_maker[page_number - 1][-1]

    # Evaluate and cache page values only once (for the first LineBox)
    # otherwise we suffer endless loops when the target/pseudo-element
    # spans across multiple pages
    cached_anchors = []
    cached_lookups = []
    for (_, _, _, _, x_remake_state) in page_maker[:page_number - 1]:
        cached_anchors.extend(x_remake_state.get('anchors', []))
        cached_lookups.extend(x_remake_state.get('content_lookups', []))

    for child in page.descendants(placeholders=True):
        # Cache target's page counters
        anchor = child.style['anchor']
        if anchor and anchor not in cached_anchors:
            remake_state['anchors'].append(anchor)
            cached_anchors.append(anchor)
            # Re-make of affected targeting boxes is inclusive
            target_collector.cache_target_page_counters(
                anchor, page_counter_values, page_number - 1, page_maker)

        # string-set and bookmark-labels don't create boxes, only `content`
        # requires another call to make_page. There is maximum one 'content'
        # item per box.
        if child.missing_link:
            # A CounterLookupItem exists for the css-token 'content'
            counter_lookup = target_collector.counter_lookup_items.get(
                (child.missing_link, 'content'))
        else:
            counter_lookup = None

        # Resolve missing (page based) counters
        if counter_lookup is not None:
            call_parse_again = False

            # Prevent endless loops
            counter_lookup_id = id(counter_lookup)
            refresh_missing_counters = counter_lookup_id not in cached_lookups
            if refresh_missing_counters:
                remake_state['content_lookups'].append(counter_lookup_id)
                cached_lookups.append(counter_lookup_id)
                counter_lookup.page_maker_index = page_number - 1

            # Step 1: page based back-references
            # Marked as pending by target_collector.cache_target_page_counters
            if counter_lookup.pending:
                if (page_counter_values !=
                        counter_lookup.cached_page_counter_values):
                    counter_lookup.cached_page_counter_values = copy.deepcopy(
                        page_counter_values)
                counter_lookup.pending = False
                call_parse_again = True

            # Step 2: local counters
            # If the box mixed-in page counters changed, update the content
            # and cache the new values.
            missing_counters = counter_lookup.missing_counters
            if missing_counters:
                if 'pages' in missing_counters:
                    remake_state['pages_wanted'] = True
                if refresh_missing_counters and page_counter_values != \
                        counter_lookup.cached_page_counter_values:
                    counter_lookup.cached_page_counter_values = \
                        copy.deepcopy(page_counter_values)
                    for counter_name in missing_counters:
                        counter_value = page_counter_values.get(
                            counter_name, None)
                        if counter_value is not None:
                            call_parse_again = True
                            # no need to loop them all
                            break

            # Step 3: targeted counters
            target_missing = counter_lookup.missing_target_counters
            for anchor_name, missed_counters in target_missing.items():
                if 'pages' not in missed_counters:
                    continue
                # Adjust 'pages_wanted'
                item = target_collector.target_lookup_items.get(
                    anchor_name, None)
                page_maker_index = item.page_maker_index
                if page_maker_index >= 0 and anchor_name in cached_anchors:
                    page_maker[page_maker_index][-1]['pages_wanted'] = True
                # 'content_changed' is triggered in
                # targets.cache_target_page_counters()

            if call_parse_again:
                remake_state['content_changed'] = True
                counter_lookup.parse_again(page_counter_values)

    if page_type.blank:
        resume_at = previous_resume_at
        next_page = page_maker[page_number - 1][1]

    return page, resume_at, next_page
Take just enough content from the beginning to fill one page.

Return ``(page, finished)``. ``page`` is a laid out PageBox object
and ``resume_at`` indicates where in the document to start the next page,
or is ``None`` if this was the last page.

:param int page_number:
Page number, starts at 1 for the first page.
:param resume_at:
As returned by ``make_page()`` for the previous page, or ``None`` for
the first page.
weasyprint/layout/page.py