def layout_document(html, root_box, context, max_loops=8):
    """Lay out the whole document.

    This includes line breaks, page breaks, absolute size and position for all
    boxes. Page based counters might require multiple passes.

    :param root_box:
        Root of the box tree (formatting structure of the HTML). The page boxes
        are created from that tree, this structure is not lost during
        pagination.
    :returns:
        A list of laid out Page objects.

    """
    initialize_page_maker(context, root_box)
    pages = []
    original_footnotes = []
    actual_total_pages = 0

    for loop in range(max_loops):
        if loop > 0:
            PROGRESS_LOGGER.info(
                'Step 5 - Creating layout - Repagination #%d', loop)
            context.footnotes = original_footnotes.copy()

        initial_total_pages = actual_total_pages
        if loop == 0:
            original_footnotes = context.footnotes.copy()
        pages = list(make_all_pages(context, root_box, html, pages))
        actual_total_pages = len(pages)

        # Check whether another round is required
        reloop_content = False
        reloop_pages = False
        for page_data in context.page_maker:
            # Update pages
            _, _, _, page_state, remake_state = page_data
            page_counter_values = page_state[1]
            page_counter_values['pages'] = [actual_total_pages]
            if remake_state['content_changed']:
                reloop_content = True
            if remake_state['pages_wanted']:
                reloop_pages = initial_total_pages != actual_total_pages

        # No need for another loop, stop here
        if not reloop_content and not reloop_pages:
            break

    # Calculate string-sets and bookmark-labels containing page based counters
    # when pagination is finished. No need to do that (maybe multiple times) in
    # make_page because they dont create boxes, only appear in MarginBoxes and
    # in the final PDF.
    # Prevent repetition of bookmarks (see #1145).

    watch_elements = []
    watch_elements_before = []
    watch_elements_after = []
    for i, page in enumerate(pages):
        # We need the updated page_counter_values
        _, _, _, page_state, _ = context.page_maker[i + 1]
        page_counter_values = page_state[1]

        for child in page.descendants():
            # Only one bookmark per original box
            if child.bookmark_label:
                if child.element_tag.endswith('::before'):
                    checklist = watch_elements_before
                elif child.element_tag.endswith('::after'):
                    checklist = watch_elements_after
                else:
                    checklist = watch_elements
                if child.element in checklist:
                    child.bookmark_label = ''
                else:
                    checklist.append(child.element)

            if child.missing_link:
                for (box, css_token), item in (
                        context.target_collector.counter_lookup_items.items()):
                    if child.missing_link == box and css_token != 'content':
                        if (css_token == 'bookmark-label' and
                                not child.bookmark_label):
                            # don't refill it!
                            continue
                        item.parse_again(page_counter_values)
                        # string_set is a pointer, but the bookmark_label is
                        # just a string: copy it
                        if css_token == 'bookmark-label':
                            child.bookmark_label = box.bookmark_label
            # Collect the string_sets in the LayoutContext
            string_sets = child.string_set
            if string_sets and string_sets != 'none':
                for string_set in string_sets:
                    string_name, text = string_set
                    context.string_set[string_name][i+1].append(text)

    # Add margin boxes
    for i, page in enumerate(pages):
        root_children = []
        root, footnote_area = page.children
        root_children.extend(layout_fixed_boxes(context, pages[:i], page))
        root_children.extend(root.children)
        root_children.extend(layout_fixed_boxes(context, pages[i + 1:], page))
        root.children = root_children
        context.current_page = i + 1  # page_number starts at 1

        # page_maker's page_state is ready for the MarginBoxes
        state = context.page_maker[context.current_page][3]
        page.children = (root,)
        if footnote_area.children:
            page.children += (footnote_area,)
        page.children += tuple(make_margin_boxes(context, page, state))
        layout_backgrounds(page, context.get_image_from_uri)
        yield page
Lay out the whole document.

This includes line breaks, page breaks, absolute size and position for all
boxes. Page based counters might require multiple passes.

:param root_box:
Root of the box tree (formatting structure of the HTML). The page boxes
are created from that tree, this structure is not lost during
pagination.
:returns:
A list of laid out Page objects.
weasyprint/layout/__init__.py