#include #include namespace { using namespace aethera; using namespace aethera::render_2d; void paint_translucent_red(Frame_2D& frame) { auto& target = aethera::render_2d::detail::Frame_2D_Access::render_target(&frame); aethera::render_2d::detail::Painter painter(target, Size{1, 1}); painter.rect(Rect_F{0.0, 0.0, 1.0, 1.0}, Pen{Color::transparent(), 0.0, Line_Style::none}, Brush{Color{255, 0, 0, 128}, Brush_Style::solid}); } } TEST(frame_pixel_format, publishes_native_bgra_premultiplied_by_default) { Frame_2D frame{Frame_Identity{1, 0}}; paint_translucent_red(frame); const auto pixels = frame.output_pixels(); ASSERT_EQ(pixels.format, Pixel_Format::bgra8_premultiplied); ASSERT_EQ(pixels.bytes.size(), 4U); EXPECT_EQ(std::to_integer(pixels.bytes[0]), 0U); EXPECT_EQ(std::to_integer(pixels.bytes[1]), 0U); EXPECT_EQ(std::to_integer(pixels.bytes[2]), 128U); EXPECT_EQ(std::to_integer(pixels.bytes[3]), 128U); } TEST(frame_pixel_format, uses_blend2d_to_publish_straight_rgba) { Frame_2D frame{Frame_Identity{2, 0}, Pixel_Format::rgba8}; paint_translucent_red(frame); const auto pixels = frame.output_pixels(); ASSERT_EQ(pixels.format, Pixel_Format::rgba8); ASSERT_EQ(pixels.bytes.size(), 4U); EXPECT_GE(std::to_integer(pixels.bytes[0]), 254U); EXPECT_EQ(std::to_integer(pixels.bytes[1]), 0U); EXPECT_EQ(std::to_integer(pixels.bytes[2]), 0U); EXPECT_EQ(std::to_integer(pixels.bytes[3]), 128U); } TEST(framebuffer_view, writes_only_the_requested_external_image_region) { Blend2D_Cache framebuffer; framebuffer.ensure_size(Size{8, 6}); { aethera::render_2d::detail::Painter painter( framebuffer, Size{8, 6}, Rect_F{2.0, 1.0, 3.0, 2.0}); painter.rect(Rect_F{0.0, 0.0, 8.0, 6.0}, Pen{.style = Line_Style::none}, Brush{Color::red_color(), Brush_Style::solid}); } const Image_View view = framebuffer.view(); ASSERT_EQ(view.width, 8); ASSERT_EQ(view.height, 6); for (int y = 0; y < view.height; ++y) { const auto* row = reinterpret_cast( view.data + static_cast(y) * view.stride); for (int x = 0; x < view.width; ++x) { const bool inside = x >= 2 && x < 5 && y >= 1 && y < 3; EXPECT_EQ(row[x] != 0, inside) << "pixel " << x << ',' << y; } } } TEST(framebuffer_view, overlapping_views_share_the_same_authoritative_pixels) { Blend2D_Cache framebuffer; framebuffer.ensure_size(Size{8, 6}); { aethera::render_2d::detail::Painter first( framebuffer, Size{8, 6}, Rect_F{1.0, 1.0, 4.0, 3.0}); first.rect(Rect_F{0.0, 0.0, 8.0, 6.0}, Pen{.style = Line_Style::none}, Brush{Color::red_color(), Brush_Style::solid}); } { aethera::render_2d::detail::Painter second( framebuffer, Size{8, 6}, Rect_F{3.0, 2.0, 4.0, 3.0}); second.rect(Rect_F{0.0, 0.0, 8.0, 6.0}, Pen{.style = Line_Style::none}, Brush{Color{0, 0, 255, 255}, Brush_Style::solid}); } const Image_View view = framebuffer.view(); const auto pixel = [&](int x, int y) { const auto* row = reinterpret_cast( view.data + static_cast(y) * view.stride); return row[x]; }; EXPECT_NE(pixel(2, 2), 0u); EXPECT_NE(pixel(4, 3), 0u); EXPECT_NE(pixel(2, 2), pixel(4, 3)); }