<commit_before>"""Page breaking and layout for block-level and block-container boxes."""

from math import inf

from ..formatting_structure import boxes
from .absolute import AbsolutePlaceholder, absolute_layout
from .column import columns_layout
from .flex import flex_layout
from .float import avoid_collisions, float_layout, get_clearance
from .inline import iter_line_boxes
from .min_max import handle_min_max_width
from .percent import resolve_percentages, resolve_position_percentages
from .replaced import block_replaced_box_layout
from .table import table_layout, table_wrapper_width


def block_level_layout(context, box, bottom_space, skip_stack,
                       containing_block, page_is_empty=True,
                       absolute_boxes=None, fixed_boxes=None,
                       adjoining_margins=None, discard=False, max_lines=None):
    """Lay out the block-level ``box``."""
    absolute_boxes = [] if absolute_boxes is None else absolute_boxes
    fixed_boxes = [] if fixed_boxes is None else fixed_boxes
    adjoining_margins = [] if adjoining_margins is None else adjoining_margins

    if not isinstance(box, boxes.TableBox):
        resolve_percentages(box, containing_block)

        if box.margin_top == 'auto':
            box.margin_top = 0
        if box.margin_bottom == 'auto':
            box.margin_bottom = 0

        if context.current_page > 1 and page_is_empty:
            # TODO: this condition is wrong, it only works for blocks whose
            # parent breaks collapsing margins. It should work for blocks whose
            # one of the ancestors breaks collapsing margins.
            # See test_margin_break_clearance.
            collapse_with_page = (
                containing_block.is_for_root_element or
                adjoining_margins)
            if collapse_with_page:
                if box.style['margin_break'] == 'discard':
                    box.margin_top = 0
                elif box.style['margin_break'] == 'auto':
                    if not context.forced_break:
                        box.margin_top = 0

        collapsed_margin = collapse_margin(
            adjoining_margins + [box.margin_top])
        box.clearance = get_clearance(context, box, collapsed_margin)
        if box.clearance is not None:
            top_border_edge = box.position_y + collapsed_margin + box.clearance
            box.position_y = top_border_edge - box.margin_top
            adjoining_margins = []

    return block_level_layout_switch(
        context, box, bottom_space, skip_stack, containing_block,
        page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins, discard,
        max_lines)


def block_level_layout_switch(context, box, bottom_space, skip_stack,
                              containing_block, page_is_empty, absolute_boxes,
                              fixed_boxes, adjoining_margins, discard,
                              max_lines):
    """Call the layout function corresponding to the ``box`` type."""
    if isinstance(box, boxes.TableBox):
        result = table_layout(
            context, box, bottom_space, skip_stack, containing_block,
            page_is_empty, absolute_boxes, fixed_boxes)
    elif isinstance(box, boxes.BlockBox):
        return block_box_layout(
            context, box, bottom_space, skip_stack, containing_block,
            page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins,
            discard, max_lines)
    elif isinstance(box, boxes.BlockReplacedBox):
        result = block_replaced_box_layout(context, box, containing_block)
    elif isinstance(box, boxes.FlexBox):
        result = flex_layout(
            context, box, bottom_space, skip_stack, containing_block,
            page_is_empty, absolute_boxes, fixed_boxes)
    else:  # pragma: no cover
        raise TypeError(f'Layout for {type(box).__name__} not handled yet')
    return result + (None,)


def block_box_layout(context, box, bottom_space, skip_stack,
                     containing_block, page_is_empty, absolute_boxes,
                     fixed_boxes, adjoining_margins, discard, max_lines):
    """Lay out the block ``box``."""
    if (box.style['column_width'] != 'auto' or
            box.style['column_count'] != 'auto'):
        result = columns_layout(
            context, box, bottom_space, skip_stack, containing_block,
            page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins)
        resume_at = result[1]
        # TODO: this condition and the whole relayout are probably wrong
        if resume_at is None:
            new_box = result[0]
            columns_bottom_space = (
                new_box.margin_bottom + new_box.padding_bottom +
                new_box.border_bottom_width)
            if columns_bottom_space:
                bottom_space += columns_bottom_space
                result = columns_layout(
                    context, box, bottom_space, skip_stack,
                    containing_block, page_is_empty, absolute_boxes,
                    fixed_boxes, adjoining_margins)
        return result + (None,)
    elif box.is_table_wrapper:
        table_wrapper_width(<commit_msg>Remove placeholders when re-rendering columns<commit_after>"""Page breaking and layout for block-level and block-container boxes."""

from math import inf

from ..formatting_structure import boxes
from .absolute import AbsolutePlaceholder, absolute_layout
from .column import columns_layout
from .flex import flex_layout
from .float import avoid_collisions, float_layout, get_clearance
from .inline import iter_line_boxes
from .min_max import handle_min_max_width
from .percent import resolve_percentages, resolve_position_percentages
from .replaced import block_replaced_box_layout
from .table import table_layout, table_wrapper_width


def block_level_layout(context, box, bottom_space, skip_stack,
                       containing_block, page_is_empty=True,
                       absolute_boxes=None, fixed_boxes=None,
                       adjoining_margins=None, discard=False, max_lines=None):
    """Lay out the block-level ``box``."""
    absolute_boxes = [] if absolute_boxes is None else absolute_boxes
    fixed_boxes = [] if fixed_boxes is None else fixed_boxes
    adjoining_margins = [] if adjoining_margins is None else adjoining_margins

    if not isinstance(box, boxes.TableBox):
        resolve_percentages(box, containing_block)

        if box.margin_top == 'auto':
            box.margin_top = 0
        if box.margin_bottom == 'auto':
            box.margin_bottom = 0

        if context.current_page > 1 and page_is_empty:
            # TODO: this condition is wrong, it only works for blocks whose
            # parent breaks collapsing margins. It should work for blocks whose
            # one of the ancestors breaks collapsing margins.
            # See test_margin_break_clearance.
            collapse_with_page = (
                containing_block.is_for_root_element or
                adjoining_margins)
            if collapse_with_page:
                if box.style['margin_break'] == 'discard':
                    box.margin_top = 0
                elif box.style['margin_break'] == 'auto':
                    if not context.forced_break:
                        box.margin_top = 0

        collapsed_margin = collapse_margin(
            adjoining_margins + [box.margin_top])
        box.clearance = get_clearance(context, box, collapsed_margin)
        if box.clearance is not None:
            top_border_edge = box.position_y + collapsed_margin + box.clearance
            box.position_y = top_border_edge - box.margin_top
            adjoining_margins = []

    return block_level_layout_switch(
        context, box, bottom_space, skip_stack, containing_block,
        page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins, discard,
        max_lines)


def block_level_layout_switch(context, box, bottom_space, skip_stack,
                              containing_block, page_is_empty, absolute_boxes,
                              fixed_boxes, adjoining_margins, discard,
                              max_lines):
    """Call the layout function corresponding to the ``box`` type."""
    if isinstance(box, boxes.TableBox):
        result = table_layout(
            context, box, bottom_space, skip_stack, containing_block,
            page_is_empty, absolute_boxes, fixed_boxes)
    elif isinstance(box, boxes.BlockBox):
        return block_box_layout(
            context, box, bottom_space, skip_stack, containing_block,
            page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins,
            discard, max_lines)
    elif isinstance(box, boxes.BlockReplacedBox):
        result = block_replaced_box_layout(context, box, containing_block)
    elif isinstance(box, boxes.FlexBox):
        result = flex_layout(
            context, box, bottom_space, skip_stack, containing_block,
            page_is_empty, absolute_boxes, fixed_boxes)
    else:  # pragma: no cover
        raise TypeError(f'Layout for {type(box).__name__} not handled yet')
    return result + (None,)


def block_box_layout(context, box, bottom_space, skip_stack,
                     containing_block, page_is_empty, absolute_boxes,
                     fixed_boxes, adjoining_margins, discard, max_lines):
    """Lay out the block ``box``."""
    if (box.style['column_width'] != 'auto' or
            box.style['column_count'] != 'auto'):
        result = columns_layout(
            context, box, bottom_space, skip_stack, containing_block,
            page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins)
        resume_at = result[1]
        # TODO: this condition and the whole relayout are probably wrong
        if resume_at is None:
            new_box = result[0]
            columns_bottom_space = (
                new_box.margin_bottom + new_box.padding_bottom +
                new_box.border_bottom_width)
            if columns_bottom_space:
                remove_placeholders(
                    context, [new_box], absolute_boxes, fixed_boxes)
                bottom_space += columns_bottom_space
                result = columns_layout(
                    context, box, bottom_space, skip_stack,
                    containing_block, page_is_empty, absolute_boxes,
                    fixed_boxes, adjoining_margins)
        return result + (None,)
    elif box.is_table_wrapper:
        table_wrapper_width(
{'fraction_non_alphanumeric': 0.07070319984671393, 'fraction_numerical': 0.0013412531136232995, 'mean_word_length': 2.5183687226154365, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2854685', 'n_tokens_mistral': 2895, 'n_tokens_neox': 2763, 'n_words': 730}