summaryrefslogtreecommitdiff
path: root/Libraries/LibGfx
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-09-07 22:25:30 -0600
committerAndreas Kling <kling@serenityos.org>2020-09-08 10:45:35 +0200
commit607c78336be1aeb754419e24de4f4296add04fcd (patch)
treeb8bf4469d305044966c5a45f952bca737a832bf5 /Libraries/LibGfx
parentc460f4a3cbe891225b528319f0a53dea7685d55c (diff)
downloadserenity-607c78336be1aeb754419e24de4f4296add04fcd.zip
LibGfx: Add ability to draw inverted rectangles
Diffstat (limited to 'Libraries/LibGfx')
-rw-r--r--Libraries/LibGfx/Color.h7
-rw-r--r--Libraries/LibGfx/Painter.cpp52
-rw-r--r--Libraries/LibGfx/Painter.h4
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);