// // Created by erki on 13.05.21. // #include "utility_fonts_5x7.hpp" #include "utility_pixelbuffer.hpp" #include #define TEST_WIDGET "[utility],[pixelbuffer]" using PixelBuffer = Utility::PixelBuffer<10, 15>; using compare_array = std::array; using Font = Utility::Font5x7; TEST_CASE("Pixelbuffer fill fills the array with data.", TEST_WIDGET) { SECTION("Fill works as expected") { PixelBuffer pb; pb.fill(100); for (const auto& px : pb) { REQUIRE(px == 100); } } SECTION("Default pixelbuffer is zero-filled.") { PixelBuffer pb; for (const auto& px : pb) { REQUIRE(px == 0); } } SECTION("Filled constructor fills the array.") { PixelBuffer pb(200); for (const auto& px : pb) { REQUIRE(px == 200); } } } TEST_CASE("Coordinate access retreives the appropriate pixels.", TEST_WIDGET) { PixelBuffer pb(200); const uint8_t* value_ptr = &pb.at(5, 2); const uint8_t* aritm_ptr = &(*(pb.cbegin() + (5 + 2 * 10))); REQUIRE(value_ptr == aritm_ptr); const uint8_t* value_ptr_c = &pb.at({5, 2}); REQUIRE(value_ptr_c == aritm_ptr); } TEST_CASE("Pixelbuffer draws rectangle correctly.", TEST_WIDGET) { PixelBuffer pb; pb.rectangle({0, 0}, {5, 10}, 10); // clang-format off compare_array etalon = { 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0 }; // clang-format on REQUIRE(pb.data() == etalon); } TEST_CASE("Pixelbuffer draws line correctly.", TEST_WIDGET) { PixelBuffer pb; SECTION("Straight line on X axis is correct.") { pb.line({0, 0}, {3, 0}, 10); compare_array etalon = { 10, 10, 10}; REQUIRE(pb.data() == etalon); } SECTION("Straight line on Y axis is correct.") { pb.line({0, 0}, {0, 3}, 10); // clang-format off compare_array etalon = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 }; // clang-format on REQUIRE(pb.data() == etalon); } SECTION("Straight line on X axis is correct with reversed coordinates.") { pb.line({3, 0}, {0, 0}, 10); compare_array etalon = { 10, 10, 10}; REQUIRE(pb.data() == etalon); } SECTION("Straight line on Y axis is correct with reversed coordinates.") { pb.line({0, 3}, {0, 0}, 10); // clang-format off compare_array etalon = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 }; // clang-format on REQUIRE(pb.data() == etalon); } SECTION("Diagonal line is correct.") { pb.line({0, 0}, {4, 4}, 10); // clang-format off compare_array etalon = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; // clang-format on REQUIRE(pb.data() == etalon); } SECTION("Diagonal line is correct if points are reversed.") { pb.line({4, 4}, {0, 0}, 10); // clang-format off compare_array etalon = { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; // clang-format on REQUIRE(pb.data() == etalon); } } TEST_CASE("Pixelbuffer draws circle properly.", TEST_WIDGET) { PixelBuffer pb; pb.circle({5, 5}, 2, 10); // clang-format off compare_array etalon = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 10, 10, 10, 0, 0, 0 }; // clang-format on REQUIRE(pb.data() == etalon); } TEST_CASE("Pixelbuffer outputs fonts correctly.", TEST_WIDGET) { PixelBuffer pb; pb.text("!", {0, 0}, 0xFF); // clang-format off compare_array etalon = { 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // clang-format on REQUIRE(pb.data() == etalon); } TEST_CASE("Pixelbuffer cuts off fonts when required.", TEST_WIDGET) { PixelBuffer pb; pb.text("!", {0, 13}, 0xFF); // clang-format off compare_array etalon = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0 }; // clang-format on REQUIRE(pb.data() == etalon); } TEST_CASE("Pixelbuffer::View provides the correct offsets.", TEST_WIDGET) { PixelBuffer pb; const auto view = pb.view<2, 2>({1, 1}); const auto* ptr_pb = &pb.at(2, 2); const auto* ptr_view = &view.at(1, 1); REQUIRE(ptr_pb == ptr_view); REQUIRE(decltype(view)::width == 2); REQUIRE(decltype(view)::height == 2); }