diff --git a/Applications/PaintBrush/PenTool.cpp b/Applications/PaintBrush/PenTool.cpp index 2a2edc104a..7a9a493be5 100644 --- a/Applications/PaintBrush/PenTool.cpp +++ b/Applications/PaintBrush/PenTool.cpp @@ -1,5 +1,7 @@ #include "PenTool.h" #include "PaintableWidget.h" +#include +#include #include PenTool::PenTool() @@ -16,8 +18,8 @@ void PenTool::on_mousedown(GMouseEvent& event) return; GPainter painter(m_widget->bitmap()); - painter.set_pixel(event.position(), m_widget->color_for(event)); - m_widget->update({ event.position(), { 1, 1 } }); + painter.draw_line(event.position(), event.position(), m_widget->color_for(event), m_thickness); + m_widget->update(); m_last_drawing_event_position = event.position(); } @@ -35,14 +37,32 @@ void PenTool::on_mousemove(GMouseEvent& event) if (event.buttons() & GMouseButton::Left || event.buttons() & GMouseButton::Right) { GPainter painter(m_widget->bitmap()); - if (m_last_drawing_event_position != Point(-1, -1)) { - painter.draw_line(m_last_drawing_event_position, event.position(), m_widget->color_for(event)); - m_widget->update(); - } else { - painter.set_pixel(event.position(), m_widget->color_for(event)); - m_widget->update({ event.position(), { 1, 1 } }); - } + if (m_last_drawing_event_position != Point(-1, -1)) + painter.draw_line(m_last_drawing_event_position, event.position(), m_widget->color_for(event), m_thickness); + else + painter.draw_line(event.position(), event.position(), m_widget->color_for(event), m_thickness); + m_widget->update(); m_last_drawing_event_position = event.position(); } } + +void PenTool::on_contextmenu(GContextMenuEvent& event) +{ + if (!m_context_menu) { + m_context_menu = make("PenTool Context Menu"); + m_context_menu->add_action(GAction::create("1", [this](auto&) { + m_thickness = 1; + })); + m_context_menu->add_action(GAction::create("2", [this](auto&) { + m_thickness = 2; + })); + m_context_menu->add_action(GAction::create("3", [this](auto&) { + m_thickness = 3; + })); + m_context_menu->add_action(GAction::create("4", [this](auto&) { + m_thickness = 4; + })); + } + m_context_menu->popup(event.screen_position()); +} diff --git a/Applications/PaintBrush/PenTool.h b/Applications/PaintBrush/PenTool.h index 20dbc4f567..2ef8f7c7aa 100644 --- a/Applications/PaintBrush/PenTool.h +++ b/Applications/PaintBrush/PenTool.h @@ -3,6 +3,8 @@ #include "Tool.h" #include +class GMenu; + class PenTool final : public Tool { public: PenTool(); @@ -11,9 +13,12 @@ public: virtual void on_mousedown(GMouseEvent&) override; virtual void on_mousemove(GMouseEvent&) override; virtual void on_mouseup(GMouseEvent&) override; + virtual void on_contextmenu(GContextMenuEvent&) override; private: virtual const char* class_name() const override { return "PenTool"; } Point m_last_drawing_event_position { -1, -1 }; + OwnPtr m_context_menu; + int m_thickness { 1 }; }; diff --git a/Applications/PaintBrush/Tool.h b/Applications/PaintBrush/Tool.h index 62fa299ad8..a57a79bc60 100644 --- a/Applications/PaintBrush/Tool.h +++ b/Applications/PaintBrush/Tool.h @@ -12,6 +12,7 @@ public: virtual void on_mousedown(GMouseEvent&) { } virtual void on_mousemove(GMouseEvent&) { } virtual void on_mouseup(GMouseEvent&) { } + virtual void on_contextmenu(GContextMenuEvent&) { } void clear() { m_widget = nullptr; } void setup(PaintableWidget& widget) { m_widget = widget.make_weak_ptr(); } diff --git a/Applications/PaintBrush/ToolboxWidget.cpp b/Applications/PaintBrush/ToolboxWidget.cpp index 7c7d0c764d..fec67ad132 100644 --- a/Applications/PaintBrush/ToolboxWidget.cpp +++ b/Applications/PaintBrush/ToolboxWidget.cpp @@ -20,6 +20,11 @@ public: const Tool& tool() const { return *m_tool; } Tool& tool() { return *m_tool; } + virtual void context_menu_event(GContextMenuEvent& event) override + { + m_tool->on_contextmenu(event); + } + private: OwnPtr m_tool; }; diff --git a/SharedGraphics/Painter.cpp b/SharedGraphics/Painter.cpp index 31d505fc9e..5f73a72083 100644 --- a/SharedGraphics/Painter.cpp +++ b/SharedGraphics/Painter.cpp @@ -636,7 +636,16 @@ void Painter::set_pixel(const Point& p, Color color) pixel ^= color.value(); } -void Painter::draw_line(const Point& p1, const Point& p2, Color color) +void Painter::draw_pixel(const Point& position, Color color, int thickness) +{ + ASSERT(draw_op() == DrawOp::Copy); + if (thickness == 1) + return set_pixel_with_draw_op(m_target->scanline(position.y())[position.x()], color); + Rect rect { position.translated(-(thickness / 2), -(thickness / 2)), { thickness, thickness } }; + fill_rect(rect, color); +} + +void Painter::draw_line(const Point& p1, const Point& p2, Color color, int thickness) { auto clip_rect = this->clip_rect(); @@ -660,7 +669,7 @@ void Painter::draw_line(const Point& p1, const Point& p2, Color color) int min_y = max(point1.y(), clip_rect.top()); int max_y = min(point2.y(), clip_rect.bottom()); for (int y = min_y; y <= max_y; ++y) - set_pixel_with_draw_op(m_target->scanline(y)[x], color); + draw_pixel({ x, y }, color, thickness); return; } @@ -677,13 +686,8 @@ void Painter::draw_line(const Point& p1, const Point& p2, Color color) return; int min_x = max(point1.x(), clip_rect.left()); int max_x = min(point2.x(), clip_rect.right()); - auto* pixels = m_target->scanline(point1.y()); - if (draw_op() == DrawOp::Copy) { - fast_dword_fill(pixels + min_x, color.value(), max_x - min_x + 1); - } else { - for (int x = min_x; x <= max_x; ++x) - set_pixel_with_draw_op(pixels[x], color); - } + for (int x = min_x; x <= max_x; ++x) + draw_pixel({ x, y }, color, thickness); return; } @@ -709,7 +713,7 @@ void Painter::draw_line(const Point& p1, const Point& p2, Color color) int y = point1.y(); for (int x = point1.x(); x <= point2.x(); ++x) { if (clip_rect.contains(x, y)) - m_target->scanline(y)[x] = color.value(); + draw_pixel({ x, y }, color, thickness); error += delta_error; if (error >= 0.5) { y = (double)y + y_step; @@ -722,7 +726,7 @@ void Painter::draw_line(const Point& p1, const Point& p2, Color color) int x = point1.x(); for (int y = point1.y(); y <= point2.y(); ++y) { if (clip_rect.contains(x, y)) - m_target->scanline(y)[x] = color.value(); + draw_pixel({ x, y }, color, thickness); error += delta_error; if (error >= 0.5) { x = (double)x + x_step; diff --git a/SharedGraphics/Painter.h b/SharedGraphics/Painter.h index 94dd2c4eea..31c27e7b20 100644 --- a/SharedGraphics/Painter.h +++ b/SharedGraphics/Painter.h @@ -23,7 +23,7 @@ public: void draw_bitmap(const Point&, const CharacterBitmap&, Color = Color()); void draw_bitmap(const Point&, const GlyphBitmap&, Color = Color()); void set_pixel(const Point&, Color); - void draw_line(const Point&, const Point&, Color); + void draw_line(const Point&, const Point&, Color, int thickness = 1); void draw_scaled_bitmap(const Rect& dst_rect, const GraphicsBitmap&, const Rect& src_rect); void blit(const Point&, const GraphicsBitmap&, const Rect& src_rect, float opacity = 1.0f); void blit_dimmed(const Point&, const GraphicsBitmap&, const Rect& src_rect); @@ -68,6 +68,7 @@ protected: void fill_rect_with_draw_op(const Rect&, Color); void blit_with_alpha(const Point&, const GraphicsBitmap&, const Rect& src_rect); void blit_with_opacity(const Point&, const GraphicsBitmap&, const Rect& src_rect, float opacity); + void draw_pixel(const Point&, Color, int thickness = 1); struct State { const Font* font;