diff options
author | Tom <tomut@yahoo.com> | 2020-09-07 22:25:30 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-09-08 10:45:35 +0200 |
commit | 607c78336be1aeb754419e24de4f4296add04fcd (patch) | |
tree | b8bf4469d305044966c5a45f952bca737a832bf5 /Libraries/LibGfx | |
parent | c460f4a3cbe891225b528319f0a53dea7685d55c (diff) | |
download | serenity-607c78336be1aeb754419e24de4f4296add04fcd.zip |
LibGfx: Add ability to draw inverted rectangles
Diffstat (limited to 'Libraries/LibGfx')
-rw-r--r-- | Libraries/LibGfx/Color.h | 7 | ||||
-rw-r--r-- | Libraries/LibGfx/Painter.cpp | 52 | ||||
-rw-r--r-- | Libraries/LibGfx/Painter.h | 4 |
3 files changed, 52 insertions, 11 deletions
diff --git a/Libraries/LibGfx/Color.h b/Libraries/LibGfx/Color.h index 619be7da05..c0c5eeed78 100644 --- a/Libraries/LibGfx/Color.h +++ b/Libraries/LibGfx/Color.h @@ -156,7 +156,12 @@ public: Color inverted() const { - return Color(~red(), ~green(), ~blue()); + return Color(~red(), ~green(), ~blue(), alpha()); + } + + Color xored(const Color& other) const + { + return Color(((other.m_value ^ m_value) & 0x00ffffff) | (m_value & 0xff000000)); } RGBA32 value() const { return m_value; } diff --git a/Libraries/LibGfx/Painter.cpp b/Libraries/LibGfx/Painter.cpp index ebafd9c726..9f218c36f9 100644 --- a/Libraries/LibGfx/Painter.cpp +++ b/Libraries/LibGfx/Painter.cpp @@ -291,13 +291,13 @@ void Painter::draw_rect(const IntRect& a_rect, Color color, bool rough) if (rect.top() >= clipped_rect.top() && rect.top() <= clipped_rect.bottom()) { int start_x = rough ? max(rect.x() + 1, clipped_rect.x()) : clipped_rect.x(); int width = rough ? min(rect.width() - 2, clipped_rect.width()) : clipped_rect.width(); - fast_u32_fill(m_target->scanline(rect.top()) + start_x, color.value(), width); + fill_scanline_with_draw_op(rect.top(), start_x, width, color); ++min_y; } if (rect.bottom() >= clipped_rect.top() && rect.bottom() <= clipped_rect.bottom()) { int start_x = rough ? max(rect.x() + 1, clipped_rect.x()) : clipped_rect.x(); int width = rough ? min(rect.width() - 2, clipped_rect.width()) : clipped_rect.width(); - fast_u32_fill(m_target->scanline(rect.bottom()) + start_x, color.value(), width); + fill_scanline_with_draw_op(rect.bottom(), start_x, width, color); --max_y; } @@ -308,16 +308,16 @@ void Painter::draw_rect(const IntRect& a_rect, Color color, bool rough) // Specialized loop when drawing both sides. for (int y = min_y; y <= max_y; ++y) { auto* bits = m_target->scanline(y); - bits[rect.left()] = color.value(); - bits[rect.right()] = color.value(); + set_pixel_with_draw_op(bits[rect.left()], color); + set_pixel_with_draw_op(bits[rect.right()], color); } } else { for (int y = min_y; y <= max_y; ++y) { auto* bits = m_target->scanline(y); if (draw_left_side) - bits[rect.left()] = color.value(); + set_pixel_with_draw_op(bits[rect.left()], color); if (draw_right_side) - bits[rect.right()] = color.value(); + set_pixel_with_draw_op(bits[rect.right()], color); } } } @@ -1125,10 +1125,44 @@ void Painter::set_pixel(const IntPoint& p, Color color) ALWAYS_INLINE void Painter::set_pixel_with_draw_op(u32& pixel, const Color& color) { - if (draw_op() == DrawOp::Copy) + switch (draw_op()) { + case DrawOp::Copy: pixel = color.value(); - else if (draw_op() == DrawOp::Xor) - pixel ^= color.value(); + break; + case DrawOp::Xor: + pixel = color.xored(Color::from_rgba(pixel)).value(); + break; + case DrawOp::Invert: + pixel = Color::from_rgba(pixel).inverted().value(); + break; + } +} + +ALWAYS_INLINE void Painter::fill_scanline_with_draw_op(int y, int x, int width, const Color& color) +{ + switch (draw_op()) { + case DrawOp::Copy: + fast_u32_fill(m_target->scanline(y) + x, color.value(), width); + break; + case DrawOp::Xor: { + auto* pixel = m_target->scanline(y) + x; + auto* end = pixel + width; + while (pixel < end) { + *pixel = Color::from_rgba(*pixel).xored(color).value(); + pixel++; + } + break; + } + case DrawOp::Invert: { + auto* pixel = m_target->scanline(y) + x; + auto* end = pixel + width; + while (pixel < end) { + *pixel = Color::from_rgba(*pixel).inverted().value(); + pixel++; + } + break; + } + } } void Painter::draw_pixel(const IntPoint& position, Color color, int thickness) diff --git a/Libraries/LibGfx/Painter.h b/Libraries/LibGfx/Painter.h index 1febfd2068..cb3271214b 100644 --- a/Libraries/LibGfx/Painter.h +++ b/Libraries/LibGfx/Painter.h @@ -103,7 +103,8 @@ public: enum class DrawOp { Copy, - Xor + Xor, + Invert }; void set_draw_op(DrawOp op) { state().draw_op = op; } DrawOp draw_op() const { return state().draw_op; } @@ -128,6 +129,7 @@ public: protected: void set_pixel_with_draw_op(u32& pixel, const Color&); + void fill_scanline_with_draw_op(int y, int x, int width, const Color& color); void fill_rect_with_draw_op(const IntRect&, Color); void blit_with_alpha(const IntPoint&, const Gfx::Bitmap&, const IntRect& src_rect); void blit_with_opacity(const IntPoint&, const Gfx::Bitmap&, const IntRect& src_rect, float opacity); |