<commit_before># coding: utf8
"""
    weasyprint.layout.preferred
    ---------------------------

    Preferred and minimum preferred width, aka. the shrink-to-fit algorithm.

    :copyright: Copyright 2011-2012 <NAME> and contributors, see AUTHORS.
    :license: BSD, see LICENSE for details.

"""

from __future__ import division, unicode_literals

import cairo

from ..formatting_structure import boxes
from ..text import TextFragment


def shrink_to_fit(box, available_width):
    """Return the shrink-to-fit width of ``box``.

    http://www.w3.org/TR/CSS21/visudet.html#float-width

    """
    return min(
        max(preferred_minimum_width(box, outer=False), available_width),
        preferred_width(box, outer=False))


def preferred_minimum_width(box, outer=True):
    """Return the preferred minimum width for ``box``.

    This is the width by breaking at every line-break opportunity.

    """
    if isinstance(box, boxes.BlockContainerBox):
        if box.is_table_wrapper:
            return table_preferred_minimum_width(box, outer)
        else:
            return block_preferred_minimum_width(box, outer)
    elif isinstance(box, (boxes.InlineBox, boxes.LineBox)):
        return inline_preferred_minimum_width(box, outer)
    else:
        raise TypeError(
            'Preferred minimum width for %s not handled yet' %
            type(box).__name__)


def preferred_width(box, outer=True):
    """Return the preferred width for ``box``.

    This is the width by only breaking at forced line breaks.

    """
    if isinstance(box, boxes.BlockContainerBox):
        if box.is_table_wrapper:
            return table_preferred_width(box, outer)
        else:
            return block_preferred_width(box, outer)
    elif isinstance(box, (boxes.InlineBox, boxes.LineBox)):
        return inline_preferred_width(box, outer)
    else:
        raise TypeError(
            'Preferred width for %s not handled yet' % type(box).__name__)


def _block_preferred_width(box, function, outer):
    """Helper to create ``block_preferred_*_width.``"""
    width = box.style.width
    if width == 'auto' or width.unit == '%':
        # "percentages on the following properties are treated instead as
        #  though they were the following: width: auto"
        # http://dbaron.org/css/intrinsic/#outer-intrinsic
        if box.children:
            width = max(function(child, outer=True) for child in box.children)
        else:
            width = 0
    else:
        assert width.unit == 'px'
        width = width.value

    return adjust(box, outer, width)


def adjust(box, outer, width):
    """Add paddings, borders and margins to ``width`` when ``outer`` is set."""
    if not outer:
        return width

    min_width = box.style.min_width
    max_width = box.style.max_width
    min_width = min_width.value if min_width.unit != '%' else 0
    max_width = max_width.value if max_width.unit != '%' else float('inf')

    fixed = max(min_width, min(width, max_width))
    percentages = 0

    fixed += box.style.border_left_width + box.style.border_right_width
    for value in ('margin_left', 'margin_right',
                  'padding_left', 'padding_right'):
        style_value = box.style[value]
        if style_value != 'auto':
            if style_value.unit == 'px':
                fixed += style_value.value
            else:
                assert style_value.unit == '%'
                percentages += style_value.value

    if percentages < 1:
        return fixed / (1 - percentages / 100.)
    else:
        # Pathological case, ignore
        return 0


def block_preferred_minimum_width(box, outer=True):
    """Return the preferred minimum width for a ``BlockBox``."""
    return _block_preferred_width(box, preferred_minimum_width, outer)


def block_preferred_width(box, outer=True):
    """Return the preferred width for a ``BlockBox``."""
    return _block_preferred_width(box, preferred_width, outer)


def inline_preferred_minimum_width(box, outer=True):<commit_msg>Fix the ``adjust`` function for tables<commit_after># coding: utf8
"""
    weasyprint.layout.preferred
    ---------------------------

    Preferred and minimum preferred width, aka. the shrink-to-fit algorithm.

    :copyright: Copyright 2011-2012 <NAME> and contributors, see AUTHORS.
    :license: BSD, see LICENSE for details.

"""

from __future__ import division, unicode_literals

import cairo

from ..formatting_structure import boxes
from ..text import TextFragment


def shrink_to_fit(box, available_width):
    """Return the shrink-to-fit width of ``box``.

    http://www.w3.org/TR/CSS21/visudet.html#float-width

    """
    return min(
        max(preferred_minimum_width(box, outer=False), available_width),
        preferred_width(box, outer=False))


def preferred_minimum_width(box, outer=True):
    """Return the preferred minimum width for ``box``.

    This is the width by breaking at every line-break opportunity.

    """
    if isinstance(box, boxes.BlockContainerBox):
        if box.is_table_wrapper:
            return table_preferred_minimum_width(box, outer)
        else:
            return block_preferred_minimum_width(box, outer)
    elif isinstance(box, (boxes.InlineBox, boxes.LineBox)):
        return inline_preferred_minimum_width(box, outer)
    else:
        raise TypeError(
            'Preferred minimum width for %s not handled yet' %
            type(box).__name__)


def preferred_width(box, outer=True):
    """Return the preferred width for ``box``.

    This is the width by only breaking at forced line breaks.

    """
    if isinstance(box, boxes.BlockContainerBox):
        if box.is_table_wrapper:
            return table_preferred_width(box, outer)
        else:
            return block_preferred_width(box, outer)
    elif isinstance(box, (boxes.InlineBox, boxes.LineBox)):
        return inline_preferred_width(box, outer)
    else:
        raise TypeError(
            'Preferred width for %s not handled yet' % type(box).__name__)


def _block_preferred_width(box, function, outer):
    """Helper to create ``block_preferred_*_width.``"""
    width = box.style.width
    if width == 'auto' or width.unit == '%':
        # "percentages on the following properties are treated instead as
        #  though they were the following: width: auto"
        # http://dbaron.org/css/intrinsic/#outer-intrinsic
        if box.children:
            width = max(function(child, outer=True) for child in box.children)
        else:
            width = 0
    else:
        assert width.unit == 'px'
        width = width.value

    return adjust(box, outer, width)


def adjust(box, outer, width):
    """Add paddings, borders and margins to ``width`` when ``outer`` is set."""
    if not outer:
        return width

    min_width = box.style.min_width
    max_width = box.style.max_width
    min_width = min_width.value if min_width.unit != '%' else 0
    max_width = max_width.value if max_width.unit != '%' else float('inf')

    fixed = max(min_width, min(width, max_width))
    percentages = 0

    for value in ('margin_left', 'margin_right',
                  'padding_left', 'padding_right'):
        # Padding and border are set on the table, not on the wrapper
        # http://www.w3.org/TR/CSS21/tables.html#model
        # TODO: clean this horrible hack!
        if box.is_table_wrapper and value == 'padding_left':
            box = box.get_wrapped_table()

        style_value = box.style[value]
        if style_value != 'auto':
            if style_value.unit == 'px':
                fixed += style_value.value
            else:
                assert style_value.unit == '%'
                percentages += style_value.value

    fixed += box.style.border_left_width + box.style.border_right_width

    if percentages < 1:
        return fixed / (1 - percentages / 100.)
    else:
        # Pathological case, ignore
        return 0


def block_preferred_minimum_width(box, outer=True):
    """Return the preferred minimum width for a ``BlockBox``."""
    return _block_preferred_width(box, preferred_minimum_width, outer)


def block_preferred_width(box, outer=True):
    """Return the preferred width for a ``BlockBox``."""
    return _block_preferred_width(box, preferred_width, outer)


def inline_preferred_minimum_width(box, outer=True):
{'fraction_non_alphanumeric': 0.10976342019935151, 'fraction_numerical': 0.0054041071214122735, 'mean_word_length': 2.7683257918552036, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 3, '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': '2206323', 'n_tokens_mistral': 2479, 'n_tokens_neox': 2365, 'n_words': 683}