def layout_backgrounds(page, get_image_from_uri):
    """Layout backgrounds on the page box and on its children.

    This function takes care of the canvas background, taken from the root
    elememt or a <body> child of the root element.

    See https://www.w3.org/TR/CSS21/colors.html#background

    """
    layout_box_backgrounds(page, page, get_image_from_uri)
    assert not isinstance(page.children[0], boxes.MarginBox)
    root_box = page.children[0]
    chosen_box = root_box
    if root_box.element_tag.lower() == 'html' and root_box.background is None:
        for child in root_box.children:
            if child.element_tag.lower() == 'body':
                chosen_box = child
                break

    if chosen_box.background:
        painting_area = box_rectangle(page, 'border-box')
        original_background = page.background
        layout_box_backgrounds(
            page, page, get_image_from_uri, layout_children=False,
            style=chosen_box.style)
        page.canvas_background = page.background._replace(
            # TODO: background-clip should be updated
            layers=[
                layer._replace(painting_area=painting_area)
                for layer in page.background.layers])
        page.background = original_background
        chosen_box.background = None
    else:
        page.canvas_background = None
Layout backgrounds on the page box and on its children.

This function takes care of the canvas background, taken from the root
elememt or a <body> child of the root element.

See https://www.w3.org/TR/CSS21/colors.html#background
weasyprint/layout/background.py