Пример #1
0
def test_real_hyphen_acts_differently_from_soft_hyphen():
    words = ["a", "b", "c", "d"]
    alphabet = {
        "normal": {
            "\u002d": 500
        },
    }
    words_separated_by_soft_hyphen = "\u00ad".join(words)
    words_separated_by_hard_hyphen = "\u002d".join(words)
    for char in words_separated_by_soft_hyphen:
        alphabet["normal"][char] = 500
    soft_hyphen_line_break = MultiLineBreak(
        [
            Fragment.from_string(words_separated_by_soft_hyphen, "normal",
                                 False)
        ],
        lambda a, b: alphabet[b][a],
    )
    hard_hyphen_line_break = MultiLineBreak(
        [
            Fragment.from_string(words_separated_by_hard_hyphen, "normal",
                                 False)
        ],
        lambda a, b: alphabet[b][a],
    )
    assert soft_hyphen_line_break.get_line_of_given_width(
        2000) != hard_hyphen_line_break.get_line_of_given_width(2000)
    assert soft_hyphen_line_break.get_line_of_given_width(
        2000) != hard_hyphen_line_break.get_line_of_given_width(2000)
Пример #2
0
def test_four_words_two_lines_break_by_space():
    """
    fit two words into the line that can fit only one word.
    expected behavior:
        - first call to `get_line_of_given_width` cointains the first word.
        - second call to `get_line_of_given_width` cointains the second word.
        - third call to `get_line_of_given_width` is None because there is no
            text left.
    """
    first_line_text = "hello world"
    second_line_text = "hello world"
    text = " ".join([first_line_text, second_line_text])
    fragments = [
        Fragment.from_string(text, "normal", False),
    ]
    alphabet = {
        "normal": {},
    }
    for char in text:
        alphabet["normal"][char] = 500

    multi_line_break = MultiLineBreak(fragments, lambda a, b: alphabet[b][a])
    assert multi_line_break.get_line_of_given_width(6000) == TextLine(
        fragments=[Fragment.from_string(first_line_text, "normal", False)],
        text_width=5500,
        number_of_spaces_between_words=1,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(6000) == TextLine(
        fragments=[Fragment.from_string(second_line_text, "normal", False)],
        text_width=5500,
        number_of_spaces_between_words=1,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(2500) is None
Пример #3
0
def test_trailing_soft_hyphen():
    """
    fit one word and trailing soft-hyphen into the line with extremely large width.
    expected behavior ->
        - first call to `get_line_of_given_width` cointains the word.
          soft hyphen is not included in the line.
        - second call to `get_line_of_given_width` is None because there is no
            text left.
    """
    text = "hello\u00ad"
    fragments = [
        Fragment.from_string(text, "normal", False),
    ]
    alphabet = {
        "normal": {
            "\u002d": 500
        },
    }
    for char in text:
        alphabet["normal"][char] = 500
    multi_line_break = MultiLineBreak(fragments, lambda a, b: alphabet[b][a])
    assert multi_line_break.get_line_of_given_width(5000) == TextLine(
        fragments=[Fragment.from_string("hello", "normal", False)],
        text_width=2500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(100000) is None
Пример #4
0
def test_two_words_two_lines_break_by_space_justify():
    """
    fit two words into the line that can fit only one word.
    expected behavior:
        - first call to `get_line_of_given_width` cointains the first word.
            Line is expected to be unjustified, because there are no spaces in
            the line.
        - second call to `get_line_of_given_width` cointains the second word.
            Line is expected to be unjustified, because it is the last line.
        - third call to `get_line_of_given_width` is None because there is no
            text left.
    """
    text = "hello world"
    fragments = [
        Fragment.from_string(text, "normal", False),
    ]
    multi_line_break = MultiLineBreak(fragments, lambda a, b: alphabet[b][a])
    alphabet = {
        "normal": {},
    }
    for char in text:
        alphabet["normal"][char] = 500
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=[Fragment.from_string("hello", "normal", False)],
        text_width=2500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=[Fragment.from_string("world", "normal", False)],
        text_width=2500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(2500) is None
Пример #5
0
def test_markdown_parse_simple_ok():
    assert tuple(FPDF()._markdown_parse(
        "**bold**, __italics__ and --underlined--")) == (
            Fragment.from_string("bold", "B", False),
            Fragment.from_string(", ", "", False),
            Fragment.from_string("italics", "I", False),
            Fragment.from_string(" and ", "", False),
            Fragment.from_string("underlined", "", True),
        )
Пример #6
0
def test_width_calculation():
    """
    Every character has different width
    """
    text = "abcd"
    alphabet = {
        "normal": {},
    }
    for width, char in enumerate(text):
        alphabet["normal"][char] = width + 2
    fragments = [
        Fragment.from_string(text, "normal", False),
    ]
    multi_line_break = MultiLineBreak(fragments, lambda a, b: alphabet[b][a])

    # zero width returns empty line
    assert multi_line_break.get_line_of_given_width(0) == TextLine(
        fragments=[],
        text_width=0,
        number_of_spaces_between_words=0,
        justify=False)
    # the first character has width of 2 units.
    # request of 1 unit line raises an exception
    with pytest.raises(FPDFException):
        multi_line_break.get_line_of_given_width(1)
    # get other characters one by one
    assert multi_line_break.get_line_of_given_width(2) == TextLine(
        fragments=[Fragment.from_string("a", "normal", False)],
        text_width=2,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(3) == TextLine(
        fragments=[Fragment.from_string("b", "normal", False)],
        text_width=3,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(4) == TextLine(
        fragments=[Fragment.from_string("c", "normal", False)],
        text_width=4,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(5) == TextLine(
        fragments=[Fragment.from_string("d", "normal", False)],
        text_width=5,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(100000) is None
Пример #7
0
def test_two_words_one_line_justify():
    """
    fit two words into the line with extremely large width.
    expected behavior ->
        - first call to `get_line_of_given_width` cointains all words.
            this line is expected to be unjustified, because it is the last
            line.
        - second call to `get_line_of_given_width` is None because there is no
            text left.
    """
    text = "hello world"
    fragments = [
        Fragment.from_string(text, "normal", False),
    ]
    alphabet = {
        "normal": {},
    }
    for char in text:
        alphabet["normal"][char] = 500
    multi_line_break = MultiLineBreak(fragments,
                                      lambda a, b: alphabet[b][a],
                                      justify=True)
    assert multi_line_break.get_line_of_given_width(100000) == TextLine(
        fragments=fragments,
        text_width=5500,
        number_of_spaces_between_words=1,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(100000) is None
Пример #8
0
def test_trailing_whitespace():
    """
    fit one word and trailing whitespace into the line with extremely large width.
    expected behavior ->
        - first call to `get_line_of_given_width` cointains the word and the space.
        - second call to `get_line_of_given_width` is None because there is no
            text left.
    """
    text = "hello "
    fragments = [
        Fragment.from_string(text, "normal", False),
    ]
    alphabet = {
        "normal": {},
    }
    for char in text:
        alphabet["normal"][char] = 500
    multi_line_break = MultiLineBreak(fragments, lambda a, b: alphabet[b][a])
    assert multi_line_break.get_line_of_given_width(5000) == TextLine(
        fragments=fragments,
        text_width=3000,
        number_of_spaces_between_words=1,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(100000) is None
Пример #9
0
def test_single_space_in_fragment():
    """
    there is only one space character in the input text.
    expected behavior ->
        - first call to `get_line_of_given_width` contains space.
        - second call to `get_line_of_given_width` is None because there is no
            text left.
    """
    text = " "
    fragments = [
        Fragment.from_string(text, "normal", False),
    ]
    alphabet = {
        "normal": {},
    }
    for char in text:
        alphabet["normal"][char] = 500
    multi_line_break = MultiLineBreak(fragments, lambda a, b: alphabet[b][a])
    assert multi_line_break.get_line_of_given_width(5000) == TextLine(
        fragments=fragments,
        text_width=500,
        number_of_spaces_between_words=1,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(100000) is None
Пример #10
0
def test_explicit_break_justify():
    """
    There is an explicit break character after every character
    Expected behavior:
        `get_line_of_given_width` returns single character on every call,
        returned lines are expected to be unjustified
    """
    alphabet = {
        "normal": {},
    }
    long_string = "\n".join("abcd")
    for char in long_string:
        alphabet["normal"][char] = 500

    fragments = [
        Fragment.from_string(long_string, "normal", False),
    ]
    multi_line_break = MultiLineBreak(fragments,
                                      lambda a, b: alphabet[b][a],
                                      justify=True)
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=[Fragment.from_string("a", "normal", False)],
        text_width=500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=[Fragment.from_string("b", "normal", False)],
        text_width=500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=[Fragment.from_string("c", "normal", False)],
        text_width=500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=[Fragment.from_string("d", "normal", False)],
        text_width=500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(1000) is None
Пример #11
0
def test_single_world_doesnt_fit_into_width_justify():
    """
    There is a single word that doesn't fit into requested line
    Expected behavior:
        `get_line_of_given_width` as much characters as can fit into user
        provided width. returned lines are expected to be unjustified
    """
    alphabet = {
        "normal": {},
    }
    long_string = "abcdefghijklmnop"
    for char in long_string:
        alphabet["normal"][char] = 500

    fragments = [
        Fragment.from_string(long_string, "normal", False),
    ]
    multi_line_break = MultiLineBreak(fragments,
                                      lambda a, b: alphabet[b][a],
                                      justify=True)
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=[Fragment.from_string("abcde", "normal", False)],
        text_width=2500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=[Fragment.from_string("fghij", "normal", False)],
        text_width=2500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=[Fragment.from_string("klmno", "normal", False)],
        text_width=2500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=[Fragment.from_string("p", "normal", False)],
        text_width=500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(1000) is None
Пример #12
0
def test_soft_hyphen_break_justify():
    """
    all characters are separated by soft-hyphen
    expected behavior - there is a hard hyphen at the end of every line,
    except of the last one
    """
    alphabet = {
        "normal": {
            "\u002d": 500
        },
    }
    words = ["ab cd", "ef gh", "kl mn"]
    long_string = "\u00ad".join(words)
    for char in long_string:
        alphabet["normal"][char] = 500

    fragments = [
        Fragment.from_string(long_string, "normal", False),
    ]
    multi_line_break = MultiLineBreak(fragments,
                                      lambda a, b: alphabet[b][a],
                                      justify=True)
    assert multi_line_break.get_line_of_given_width(3000) == TextLine(
        fragments=[Fragment.from_string("ab cd\u002d", "normal", False)],
        text_width=3000,
        number_of_spaces_between_words=1,
        justify=True,
    )
    assert multi_line_break.get_line_of_given_width(3000) == TextLine(
        fragments=[Fragment.from_string("ef gh\u002d", "normal", False)],
        text_width=3000,
        number_of_spaces_between_words=1,
        justify=True,
    )
    assert multi_line_break.get_line_of_given_width(3000) == TextLine(
        fragments=[Fragment.from_string("kl mn", "normal", False)],
        text_width=2500,
        number_of_spaces_between_words=1,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(1000) is None
Пример #13
0
def test_break_fragment_into_two_lines_justify():
    """
    There are multiple fragments with different styles.
    This test breaks one fragment between two lines.
    """
    alphabet = {
        "normal": {},
        "bold": {},
    }
    first_line_text = "one "
    second_line_text = "two three"
    third_line_text = " four"
    text = "".join((first_line_text, second_line_text, third_line_text))
    for char in text:
        alphabet["normal"][char] = 500
        alphabet["bold"][char] = 1000

    fragments = [
        Fragment.from_string(first_line_text, "normal", False),
        Fragment.from_string(second_line_text, "bold", False),
        Fragment.from_string(third_line_text, "normal", False),
    ]
    multi_line_break = MultiLineBreak(fragments,
                                      lambda a, b: alphabet[b][a],
                                      justify=True)
    assert multi_line_break.get_line_of_given_width(5000) == TextLine(
        fragments=[
            Fragment.from_string(first_line_text, "normal", False),
            Fragment.from_string("two", "bold", False),
        ],
        text_width=5000,
        number_of_spaces_between_words=1,
        justify=True,
    )
    assert multi_line_break.get_line_of_given_width(8000) == TextLine(
        fragments=[
            Fragment.from_string("three", "bold", False),
            Fragment.from_string(third_line_text, "normal", False),
        ],
        text_width=7500,
        number_of_spaces_between_words=1,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(6000) is None
Пример #14
0
def test_single_soft_hyphen_in_fragment():
    """
    there is only one soft hyphen character in the input text.
    expected behavior ->
        - call to `get_line_of_given_width` always returns None, because soft
          hyphen doesn't break a word
    """
    alphabet = {
        "normal": {
            "\u002d": 500
        },
    }
    text = "\u00ad"
    fragments = [
        Fragment.from_string(text, "normal", False),
    ]
    for char in text:
        alphabet["normal"][char] = 500
    multi_line_break = MultiLineBreak(fragments, lambda a, b: alphabet[b][a])
    assert multi_line_break.get_line_of_given_width(100000) is None
Пример #15
0
def test_last_line_no_justify():
    """
    Make sure that the last line is not justified.
    """
    alphabet = {
        "normal": {},
    }
    long_string = "a"
    for char in long_string:
        alphabet["normal"][char] = 500

    fragments = [
        Fragment.from_string(long_string, "normal", False),
    ]
    multi_line_break = MultiLineBreak(fragments,
                                      lambda a, b: alphabet[b][a],
                                      justify=True)
    assert multi_line_break.get_line_of_given_width(2500) == TextLine(
        fragments=fragments,
        text_width=500,
        number_of_spaces_between_words=0,
        justify=False,
    )
    assert multi_line_break.get_line_of_given_width(1000) is None
Пример #16
0
def test_markdown_parse_line_of_markers():
    assert tuple(FPDF()._markdown_parse("*** woops")) == (Fragment.from_string(
        "*** woops", "", False), )
    assert tuple(
        FPDF()._markdown_parse("----------")) == (Fragment.from_string(
            "----------", "", False), )
Пример #17
0
def test_markdown_parse_unterminated():
    assert tuple(FPDF()._markdown_parse("**bold __italics__")) == (
        Fragment.from_string("bold ", "B", False),
        Fragment.from_string("italics", "BI", False),
    )
Пример #18
0
def test_markdown_parse_crossing_markers():
    assert tuple(FPDF()._markdown_parse("**bold __and** italics__")) == (
        Fragment.from_string("bold ", "B", False),
        Fragment.from_string("and", "BI", False),
        Fragment.from_string(" italics", "I", False),
    )
Пример #19
0
def test_markdown_parse_overlapping():
    assert tuple(FPDF()._markdown_parse("**bold __italics__**")) == (
        Fragment.from_string("bold ", "B", False),
        Fragment.from_string("italics", "BI", False),
    )