embedded-text 0.7.3

TextBox for embedded-graphics
Documentation
use embedded_graphics::{
    geometry::Point,
    mock_display::MockDisplay,
    mono_font::{ascii::FONT_6X9, MonoTextStyle, MonoTextStyleBuilder},
    pixelcolor::BinaryColor,
    primitives::Rectangle,
    text::LineHeight,
    Drawable,
};

use crate::{
    alignment::HorizontalAlignment,
    rendering::test::assert_rendered,
    style::{TextBoxStyle, TextBoxStyleBuilder},
    utils::test::size_for,
    TextBox,
};

#[test]
fn simple_render() {
    assert_rendered(
        HorizontalAlignment::Left,
        "word",
        size_for(&FONT_6X9, 6, 1),
        &[
            "........................",
            "......................#.",
            "......................#.",
            "#...#...##...#.#....###.",
            "#.#.#..#..#..##.#..#..#.",
            "#.#.#..#..#..#.....#..#.",
            ".#.#....##...#......###.",
            "........................",
            "........................",
        ],
    );
}

#[test]
fn simple_render_cr() {
    let mut display = MockDisplay::new();
    display.set_allow_overdraw(true);

    let character_style = MonoTextStyle::new(&FONT_6X9, BinaryColor::On);
    let style = TextBoxStyle::with_alignment(HorizontalAlignment::Left);

    TextBox::with_textbox_style(
        "O\rX",
        Rectangle::new(Point::zero(), size_for(&FONT_6X9, 1, 1)),
        character_style,
        style,
    )
    .draw(&mut display)
    .unwrap();

    display.assert_pattern(&[
        "         ",
        "#####    ",
        "## ##    ",
        "# # #    ",
        "# # #    ",
        "## ##    ",
        "#####    ",
    ]);
}

#[test]
fn simple_word_wrapping() {
    assert_rendered(
        HorizontalAlignment::Left,
        " word wrapping",
        size_for(&FONT_6X9, 9, 2),
        &[
            "..............................                  ",
            "............................#.                  ",
            "............................#.                  ",
            "......#...#...##...#.#....###.                  ",
            "......#.#.#..#..#..##.#..#..#.                  ",
            "......#.#.#..#..#..#.....#..#.                  ",
            ".......#.#....##...#......###.                  ",
            "..............................                  ",
            "..............................                  ",
            "................................................",
            "................................#...............",
            "................................................",
            "#...#..#.#....###..###...###...##....###....##..",
            "#.#.#..##.#..#..#..#..#..#..#...#....#..#..#..#.",
            "#.#.#..#.....#..#..#..#..#..#...#....#..#..#..#.",
            ".#.#...#......###..###...###...###...#..#...###.",
            "...................#.....#....................#.",
            "...................#.....#..................##..",
        ],
    );
}

#[test]
fn simple_word_wrapping_by_space() {
    assert_rendered(
        HorizontalAlignment::Left,
        "wrapping word",
        size_for(&FONT_6X9, 8, 2),
        &[
            "................................................",
            "................................#...............",
            "................................................",
            "#...#..#.#....###..###...###...##....###....##..",
            "#.#.#..##.#..#..#..#..#..#..#...#....#..#..#..#.",
            "#.#.#..#.....#..#..#..#..#..#...#....#..#..#..#.",
            ".#.#...#......###..###...###...###...#..#...###.",
            "...................#.....#....................#.",
            "...................#.....#..................##..",
            "........................                        ",
            "......................#.                        ",
            "......................#.                        ",
            "#...#...##...#.#....###.                        ",
            "#.#.#..#..#..##.#..#..#.                        ",
            "#.#.#..#..#..#.....#..#.                        ",
            ".#.#....##...#......###.                        ",
            "........................                        ",
            "........................                        ",
        ],
    );
}

#[test]
fn simple_word_wrapping_with_line_spacing() {
    let mut display = MockDisplay::new();

    let character_style = MonoTextStyleBuilder::new()
        .font(&FONT_6X9)
        .text_color(BinaryColor::On)
        .background_color(BinaryColor::Off)
        .build();

    let style = TextBoxStyleBuilder::new()
        .alignment(HorizontalAlignment::Left)
        .line_height(LineHeight::Pixels(11))
        .build();

    TextBox::with_textbox_style(
        "wrapping word",
        Rectangle::new(Point::zero(), size_for(&FONT_6X9, 8, 3)),
        character_style,
        style,
    )
    .draw(&mut display)
    .unwrap();

    display.assert_pattern(&[
        "................................................",
        "................................#...............",
        "................................................",
        "#...#..#.#....###..###...###...##....###....##..",
        "#.#.#..##.#..#..#..#..#..#..#...#....#..#..#..#.",
        "#.#.#..#.....#..#..#..#..#..#...#....#..#..#..#.",
        ".#.#...#......###..###...###...###...#..#...###.",
        "...................#.....#....................#.",
        "...................#.....#..................##..",
        "                                                ",
        "                                                ",
        "........................                        ",
        "......................#.                        ",
        "......................#.                        ",
        "#...#...##...#.#....###.                        ",
        "#.#.#..#..#..##.#..#..#.                        ",
        "#.#.#..#..#..#.....#..#.                        ",
        ".#.#....##...#......###.                        ",
        "........................                        ",
        "........................                        ",
    ]);
}

#[test]
fn simple_word_wrapping_with_negative_line_spacing() {
    let mut display = MockDisplay::new();
    display.set_allow_overdraw(true);

    let character_style = MonoTextStyleBuilder::new()
        .font(&FONT_6X9)
        .text_color(BinaryColor::On)
        .background_color(BinaryColor::Off)
        .build();

    let style = TextBoxStyleBuilder::new()
        .alignment(HorizontalAlignment::Left)
        .line_height(LineHeight::Pixels(7))
        .build();

    TextBox::with_textbox_style(
        "wrapping word",
        Rectangle::new(Point::zero(), size_for(&FONT_6X9, 8, 2)),
        character_style,
        style,
    )
    .draw(&mut display)
    .unwrap();

    display.assert_pattern(&[
        "................................................",
        "................................#...............",
        "................................................",
        "#...#..#.#....###..###...###...##....###....##..",
        "#.#.#..##.#..#..#..#..#..#..#...#....#..#..#..#.",
        "#.#.#..#.....#..#..#..#..#..#...#....#..#..#..#.",
        ".#.#...#......###..###...###...###...#..#...###.",
        ".........................#....................#.", // note the overdraw
        "......................#..#..................##..",
        "......................#.                        ",
        "#...#...##...#.#....###.                        ",
        "#.#.#..#..#..##.#..#..#.                        ",
        "#.#.#..#..#..#.....#..#.                        ",
        ".#.#....##...#......###.                        ",
        "........................                        ",
        "........................                        ",
    ]);
}

#[test]
fn whitespace_word_wrapping() {
    assert_rendered(
        HorizontalAlignment::Left,
        "word  wrap",
        size_for(&FONT_6X9, 6, 2),
        &[
            "........................",
            "......................#.",
            "......................#.",
            "#...#...##...#.#....###.",
            "#.#.#..#..#..##.#..#..#.",
            "#.#.#..#..#..#.....#..#.",
            ".#.#....##...#......###.",
            "........................",
            "........................",
            "........................",
            "........................",
            "........................",
            "#...#..#.#....###..###..",
            "#.#.#..##.#..#..#..#..#.",
            "#.#.#..#.....#..#..#..#.",
            ".#.#...#......###..###..",
            "...................#....",
            "...................#....",
        ],
    );
}

#[test]
fn word_longer_than_line_wraps_word_and_removes_a_space() {
    assert_rendered(
        HorizontalAlignment::Left,
        "word  somereallylongword",
        size_for(&FONT_6X9, 9, 3),
        &[
            "........................                              ",
            "......................#.                              ",
            "......................#.                              ",
            "#...#...##...#.#....###.                              ",
            "#.#.#..#..#..##.#..#..#.                              ",
            "#.#.#..#..#..#.....#..#.                              ",
            ".#.#....##...#......###.                              ",
            "........................                              ",
            "........................                              ",
            "......................................................",
            "...........................................##....##...",
            "............................................#.....#...",
            "..###...##..##.#....##...#.#....##....###...#.....#...",
            ".##....#..#.#.#.#..#.##..##.#..#.##..#..#...#.....#...",
            "...##..#..#.#.#.#..##....#.....##....#..#...#.....#...",
            ".###....##..#...#...###..#......###...###..###...###..",
            "......................................................",
            "......................................................",
            "......................................................",
            ".......##...........................................#.",
            "........#...........................................#.",
            ".#..#...#.....##...###....##..#...#...##...#.#....###.",
            ".#..#...#....#..#..#..#..#..#.#.#.#..#..#..##.#..#..#.",
            ".#..#...#....#..#..#..#..#..#.#.#.#..#..#..#.....#..#.",
            "..###..###....##...#..#...###..#.#....##...#......###.",
            ".#..#.......................#.........................",
            "..##......................##..........................",
        ],
    );
}

#[test]
fn first_word_longer_than_line_wraps_word() {
    assert_rendered(
        HorizontalAlignment::Left,
        "somereallylongword",
        size_for(&FONT_6X9, 9, 2),
        &[
            "......................................................",
            "...........................................##....##...",
            "............................................#.....#...",
            "..###...##..##.#....##...#.#....##....###...#.....#...",
            ".##....#..#.#.#.#..#.##..##.#..#.##..#..#...#.....#...",
            "...##..#..#.#.#.#..##....#.....##....#..#...#.....#...",
            ".###....##..#...#...###..#......###...###..###...###..",
            "......................................................",
            "......................................................",
            "......................................................",
            ".......##...........................................#.",
            "........#...........................................#.",
            ".#..#...#.....##...###....##..#...#...##...#.#....###.",
            ".#..#...#....#..#..#..#..#..#.#.#.#..#..#..##.#..#..#.",
            ".#..#...#....#..#..#..#..#..#.#.#.#..#..#..#.....#..#.",
            "..###..###....##...#..#...###..#.#....##...#......###.",
            ".#..#.......................#.........................",
            "..##......................##..........................",
        ],
    );
}

#[test]
fn soft_hyphen_rendering() {
    assert_rendered(
        HorizontalAlignment::Left,
        "soft\u{AD}hyphen",
        size_for(&FONT_6X9, 6, 2),
        &[
            "..............................      ",
            "...............#....#.........      ",
            "..............#.#...#.........      ",
            "..###...##....#....###........      ",
            ".##....#..#..###....#...#####.      ",
            "...##..#..#...#.....#.#.......      ",
            ".###....##....#......#........      ",
            "..............................      ",
            "..............................      ",
            "....................................",
            ".#.................#................",
            ".#.................#................",
            ".###...#..#..###...###....##...###..",
            ".#..#..#..#..#..#..#..#..#.##..#..#.",
            ".#..#..#..#..#..#..#..#..##....#..#.",
            ".#..#...###..###...#..#...###..#..#.",
            ".......#..#..#......................",
            "........##...#......................",
        ],
    );
}

#[test]
fn trailing_spaces() {
    let mut display = MockDisplay::new();

    let character_style = MonoTextStyleBuilder::new()
        .font(&FONT_6X9)
        .text_color(BinaryColor::On)
        .background_color(BinaryColor::Off)
        .build();

    TextBox::new(
        "Hello wrap \nWorld ",
        Rectangle::new(Point::zero(), size_for(&FONT_6X9, 6, 3)),
        character_style,
    )
    .draw(&mut display)
    .unwrap();

    // This test covers wrapping by whitespace, newline and end-of-text cases.
    display.assert_pattern(&[
        "..............................",
        ".#..#........##....##.........",
        ".#..#.........#.....#.........",
        ".####...##....#.....#.....##..",
        ".#..#..#.##...#.....#....#..#.",
        ".#..#..##.....#.....#....#..#.",
        ".#..#...###..###...###....##..",
        "..............................",
        "..............................",
        "........................      ",
        "........................      ",
        "........................      ",
        "#...#..#.#....###..###..      ",
        "#.#.#..##.#..#..#..#..#.      ",
        "#.#.#..#.....#..#..#..#.      ",
        ".#.#...#......###..###..      ",
        "...................#....      ",
        "...................#....      ",
        "..............................",
        "#...#..............##.......#.",
        "#...#...............#.......#.",
        "#.#.#...##...#.#....#.....###.",
        "#.#.#..#..#..##.#...#....#..#.",
        "##.##..#..#..#......#....#..#.",
        "#...#...##...#.....###....###.",
        "..............................",
        "..............................",
    ]);
}