lb 0.6.0

A TUI library with ASCII/Unicode graphics.
Documentation
use lb::color;
use lb::glyph;
use lb::img;
use lb::mat::Matrix;
use lb::mat::MatrixMut;
use lb::typeset::Typesetter;
use lb::typesetters;

use std::thread;

const BLACK: color::Rgb = color::Rgb::new(0, 0, 0);
const WHITE: color::Rgb = color::Rgb::new(255, 255, 255);
const RED: color::Rgb = color::Rgb::new(255, 0, 0);
const GREEN: color::Rgb = color::Rgb::new(0, 255, 0);
const BLUE: color::Rgb = color::Rgb::new(0, 0, 255);
const CYAN: color::Rgb = color::Rgb::new(0, 255, 255);
const MAGENTA: color::Rgb = color::Rgb::new(255, 0, 255);
const YELLOW: color::Rgb = color::Rgb::new(255, 255, 0);

#[test]
fn typesetter_asymmetric_fill() {
    let rgb = [
        BLACK, BLACK, BLACK, WHITE, //
        BLACK, BLACK, BLACK, WHITE, //
        BLACK, BLACK, BLACK, WHITE, //
        BLACK, BLACK, BLACK, WHITE, //
        BLACK, BLACK, BLACK, WHITE, //
        BLACK, BLACK, BLACK, WHITE, //
        BLACK, BLACK, BLACK, WHITE, //
        BLACK, BLACK, BLACK, WHITE, //
    ];
    let img = img::ImgRef::new(&rgb, (4, 8).into()).unwrap();

    let asymmetric = typesetters::Asymmetric;
    let size = img.size().to_buffer_size(&asymmetric);

    assert_eq!(size, (1, 1).into());

    let mut glyphs = glyph::GlyphsVec::with_default(size);

    asymmetric.compose(glyphs.as_mut(), img);

    let actual = glyphs.as_slice();

    let expected = glyph::Glyph {
        char: '',
        foreground: Some(BLACK),
        background: Some(WHITE),
    };

    assert_eq!(actual, [expected]);
}

#[test]
fn typesetter_block_fill() {
    let rgb = [
        WHITE, //
    ];
    let img = img::ImgRef::new(&rgb, (1, 1).into()).unwrap();

    let block = typesetters::Block;
    let size = img.size().to_buffer_size(&block);

    assert_eq!(size, (1, 1).into());

    let mut glyphs = glyph::GlyphsVec::with_default(size);

    block.compose(glyphs.as_mut(), img);

    let actual = glyphs.as_slice();

    let expected = glyph::Glyph {
        char: ' ',
        foreground: None,
        background: Some(WHITE),
    };

    assert_eq!(actual, [expected]);
}

#[test]
fn typesetter_half_fill() {
    let rgb = [
        BLUE,   //
        YELLOW, //
    ];
    let img = img::ImgRef::new(&rgb, (1, 2).into()).unwrap();

    let half = typesetters::Half;
    let size = img.size().to_buffer_size(&half);

    assert_eq!(size, (1, 1).into());

    let mut glyphs = glyph::GlyphsVec::with_default(size);

    half.compose(glyphs.as_mut(), img);

    let actual = glyphs.as_slice();

    let expected = glyph::Glyph {
        char: '',
        foreground: Some(YELLOW),
        background: Some(BLUE),
    };

    assert_eq!(actual, [expected]);
}

#[test]
fn typesetter_quadrant_fill() {
    let rgb = [
        RED, WHITE, //
        WHITE, WHITE, //
    ];
    let img = img::ImgRef::new(&rgb, (2, 2).into()).unwrap();

    let quadrant = typesetters::Quadrant;
    let size = img.size().to_buffer_size(&quadrant);

    assert_eq!(size, (1, 1).into());

    let mut glyphs = glyph::GlyphsVec::with_default(size);

    quadrant.compose(glyphs.as_mut(), img);

    let actual = glyphs.as_slice();

    let expected = glyph::Glyph {
        char: '',
        foreground: Some(WHITE),
        background: Some(RED),
    };

    assert_eq!(actual, [expected]);
}

#[test]
fn typesetter_sextant_fill() {
    let rgb = [
        BLACK, MAGENTA, //
        BLACK, MAGENTA, //
        BLACK, MAGENTA, //
    ];
    let img = img::ImgRef::new(&rgb, (2, 3).into()).unwrap();

    let sextant = typesetters::Sextant;
    let size = img.size().to_buffer_size(&sextant);

    assert_eq!(size, (1, 1).into());

    let mut glyphs = glyph::GlyphsVec::with_default(size);

    sextant.compose(glyphs.as_mut(), img);

    let actual = glyphs.as_slice();

    let expected = glyph::Glyph {
        char: '',
        foreground: Some(MAGENTA),
        background: Some(BLACK),
    };

    assert_eq!(actual, [expected]);
}

#[test]
fn typesetter_half_workloads_fill() {
    let rgb = [
        GREEN, RED, //
        GREEN, YELLOW, //
        CYAN, BLUE, //
        BLACK, BLUE, //
    ];
    let img = img::ImgRef::new(&rgb, (2, 4).into()).unwrap();

    let half = typesetters::Half;
    let size = img.size().to_buffer_size(&half);

    assert_eq!(size, (2, 2).into());

    let mut glyphs = glyph::GlyphsVec::with_default(size);

    thread::scope(|s| {
        for workload in half.workloads(glyphs.as_mut(), img, 8) {
            s.spawn(move || workload.run());
        }
    });

    let actual = glyphs.as_slice();

    let expected = [
        glyph::Glyph {
            char: ' ',
            foreground: None,
            background: Some(GREEN),
        },
        glyph::Glyph {
            char: '',
            foreground: Some(YELLOW),
            background: Some(RED),
        },
        glyph::Glyph {
            char: '',
            foreground: Some(CYAN),
            background: Some(BLACK),
        },
        glyph::Glyph {
            char: ' ',
            foreground: None,
            background: Some(BLUE),
        },
    ];

    assert_eq!(actual, expected);
}

#[test]
fn workloads_size_hint() {
    let img = img::ImgRef::from(&[
        [GREEN, RED],    //
        [GREEN, YELLOW], //
        [CYAN, BLUE],    //
        [BLACK, BLUE],   //
    ]);

    let half = typesetters::Half;
    let size = img.size().to_buffer_size(&half);

    assert_eq!(size, (2, 2).into());

    let mut glyphs = glyph::GlyphsVec::with_default(size);

    let mut workloads = half.workloads(glyphs.as_mut(), img, 8);

    assert_eq!(workloads.size_hint(), (2, Some(2)));
    _ = workloads.next();
    assert_eq!(workloads.size_hint(), (1, Some(1)));
    _ = workloads.next();
    assert_eq!(workloads.size_hint(), (0, Some(0)));
    _ = workloads.next();
    assert_eq!(workloads.size_hint(), (0, Some(0)));
    assert_eq!(workloads.count(), 0);
}