mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:17:44 +00:00
LibGfx: Add ability to draw inverted rectangles
This commit is contained in:
parent
c460f4a3cb
commit
607c78336b
3 changed files with 52 additions and 11 deletions
|
@ -156,7 +156,12 @@ public:
|
||||||
|
|
||||||
Color inverted() const
|
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; }
|
RGBA32 value() const { return m_value; }
|
||||||
|
|
|
@ -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()) {
|
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 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();
|
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;
|
++min_y;
|
||||||
}
|
}
|
||||||
if (rect.bottom() >= clipped_rect.top() && rect.bottom() <= clipped_rect.bottom()) {
|
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 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();
|
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;
|
--max_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,16 +308,16 @@ void Painter::draw_rect(const IntRect& a_rect, Color color, bool rough)
|
||||||
// Specialized loop when drawing both sides.
|
// Specialized loop when drawing both sides.
|
||||||
for (int y = min_y; y <= max_y; ++y) {
|
for (int y = min_y; y <= max_y; ++y) {
|
||||||
auto* bits = m_target->scanline(y);
|
auto* bits = m_target->scanline(y);
|
||||||
bits[rect.left()] = color.value();
|
set_pixel_with_draw_op(bits[rect.left()], color);
|
||||||
bits[rect.right()] = color.value();
|
set_pixel_with_draw_op(bits[rect.right()], color);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int y = min_y; y <= max_y; ++y) {
|
for (int y = min_y; y <= max_y; ++y) {
|
||||||
auto* bits = m_target->scanline(y);
|
auto* bits = m_target->scanline(y);
|
||||||
if (draw_left_side)
|
if (draw_left_side)
|
||||||
bits[rect.left()] = color.value();
|
set_pixel_with_draw_op(bits[rect.left()], color);
|
||||||
if (draw_right_side)
|
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)
|
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();
|
pixel = color.value();
|
||||||
else if (draw_op() == DrawOp::Xor)
|
break;
|
||||||
pixel ^= color.value();
|
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)
|
void Painter::draw_pixel(const IntPoint& position, Color color, int thickness)
|
||||||
|
|
|
@ -103,7 +103,8 @@ public:
|
||||||
|
|
||||||
enum class DrawOp {
|
enum class DrawOp {
|
||||||
Copy,
|
Copy,
|
||||||
Xor
|
Xor,
|
||||||
|
Invert
|
||||||
};
|
};
|
||||||
void set_draw_op(DrawOp op) { state().draw_op = op; }
|
void set_draw_op(DrawOp op) { state().draw_op = op; }
|
||||||
DrawOp draw_op() const { return state().draw_op; }
|
DrawOp draw_op() const { return state().draw_op; }
|
||||||
|
@ -128,6 +129,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void set_pixel_with_draw_op(u32& pixel, const Color&);
|
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 fill_rect_with_draw_op(const IntRect&, Color);
|
||||||
void blit_with_alpha(const IntPoint&, const Gfx::Bitmap&, const IntRect& src_rect);
|
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);
|
void blit_with_opacity(const IntPoint&, const Gfx::Bitmap&, const IntRect& src_rect, float opacity);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue