<commit_before>from twyg.hyphenator import hyphenate_word
from twyg.geom import Rectangle


_hyphenate_word_cache = {}


def _calc_inside_rects(points):
    """
    Calculate a list of horizontal rectangles fitting into a convex
    shape.

    ``points``
        A list of intersection point-pairs of a set of equidistant
        horizontal lines intersecting the segments defining shape
        (should be calculated by ``slice_shape``).

    Rectangles are returned as a list of ``[x, y, width, height]``
    arrays.
    """
    rects = []
    for i in range(len(points) - 1):
        p11, p12 = points[i]
        p21, p22 = points[i + 1]

        x = max(p11.x, p21.x)
        y = p11.y
        w = min(p12.x, p22.x) - x
        h = p21.y - p11.y

        rects.append(Rectangle(x, y, w, h))

    return rects


def _hyphenate_word(word):
    """ Memoized hyphenate_word() function. """
    cache = _hyphenate_word_cache
    if word not in cache:
        cache[word] = hyphenate_word(word)
    return cache[word][:]


def _splittext(txt, textwidth_func):
    words = txt.split()
    wordwidths = [textwidth_func(w) for w in words]
    spacewidth = textwidth_func(' ')
    return words, wordwidths, spacewidth


def _wraptext(words, wordwidths, spacewidth, textwidth_func, rects=None,
              maxwidth=0, hyphenate=False, max_spacewidth_factor=5):
    """
    Wrap text in a list of variable-width or fixed-width lines.

    ``words`` should contain the text as a list of words, ``wordwidths``
    the width of each word from the words list and ``spacewidth`` the
    width of a single space character. The function returns a list of
    strings containing the text in each line and a list of line widths.

    TODO max_spacewidth_factor, hyphenate

    In variable-width mode, ``rects`` holds a list of Rectangle objects
    that represent the blank lines the text should be wrapped into. The
    value of ``maxwidth`` is disregarded in this case. The following
    three outcomes are possible:

        len(lines) = len(rects)   -- optimal wrap
        len(lines) > len(rects)   -- can't fit text into the available
                                     rects
        len(lines) < len(rects)   -- suboptimal wrap

    In fixed-width mode, ``rects`` is None and ``maxwidth`` holds the
    fixed line length (must be greater than zero).
    """

    if not rects and maxwidth <= 0:
        raise (ValueError,
               'maxwidth must be greater than 0 if no rects are provided')

    lines = ['']         # wrapped text per each line
    linewidths = [0]     # linewidth of each line (including spaces)

    currline = currword = linewidth = 0
    maxlinewidth = rects[currline].w if rects else maxwidth

    if hyphenate:
        words = words[:]
        wordwidths = wordwidths[:]

    while currword < len(words):
        word = words[currword]<commit_msg>Text wrapping infinite loop fix<commit_after>from twyg.hyphenator import hyphenate_word
from twyg.geom import Rectangle


_hyphenate_word_cache = {}


def _calc_inside_rects(points):
    """
    Calculate a list of horizontal rectangles fitting into a convex
    shape.

    ``points``
        A list of intersection point-pairs of a set of equidistant
        horizontal lines intersecting the segments defining shape
        (should be calculated by ``slice_shape``).

    Rectangles are returned as a list of ``[x, y, width, height]``
    arrays.
    """
    rects = []
    for i in range(len(points) - 1):
        p11, p12 = points[i]
        p21, p22 = points[i + 1]

        x = max(p11.x, p21.x)
        y = p11.y
        w = min(p12.x, p22.x) - x
        h = p21.y - p11.y

        rects.append(Rectangle(x, y, w, h))

    return rects


def _hyphenate_word(word):
    """ Memoized hyphenate_word() function. """
    cache = _hyphenate_word_cache
    if word not in cache:
        cache[word] = hyphenate_word(word)
    return cache[word][:]


def _splittext(txt, textwidth_func):
    words = txt.split()
    wordwidths = [textwidth_func(w) for w in words]
    spacewidth = textwidth_func(' ')
    return words, wordwidths, spacewidth


def _wraptext(words, wordwidths, spacewidth, textwidth_func, rects=None,
              maxwidth=0, hyphenate=False, max_spacewidth_factor=5):
    """
    Wrap text in a list of variable-width or fixed-width lines.

    ``words`` should contain the text as a list of words, ``wordwidths``
    the width of each word from the words list and ``spacewidth`` the
    width of a single space character. The function returns a list of
    strings containing the text in each line and a list of line widths.

    TODO max_spacewidth_factor, hyphenate

    In variable-width mode, ``rects`` holds a list of Rectangle objects
    that represent the blank lines the text should be wrapped into. The
    value of ``maxwidth`` is disregarded in this case. The following
    three outcomes are possible:

        len(lines) = len(rects)   -- optimal wrap
        len(lines) > len(rects)   -- can't fit text into the available
                                     rects
        len(lines) < len(rects)   -- suboptimal wrap

    In fixed-width mode, ``rects`` is None and ``maxwidth`` holds the
    fixed line length (must be greater than zero).
    """

    if not rects and maxwidth <= 0:
        raise (ValueError,
               'maxwidth must be greater than 0 if no rects are provided')

    maxwidth = max(maxwidth, max(wordwidths))

    lines = ['']         # wrapped text per each line
    linewidths = [0]     # linewidth of each line (including spaces)

    currline = currword = linewidth = 0
    maxlinewidth = rects[currline].w if rects else maxwidth

    if hyphenate:
        words = words[:]
        wordwidths = wordwidths[:]

    while currword < len(words):
        word = words[currword]
{'fraction_non_alphanumeric': 0.09020485453606472, 'fraction_numerical': 0.010328800137717335, 'mean_word_length': 2.5731857318573184, 'pattern_counts': {'":': 0, '<': 9, '<?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': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5853942', 'n_tokens_mistral': 1822, 'n_tokens_neox': 1727, 'n_words': 638}