summaryrefslogtreecommitdiff
path: root/Userland/Applications
diff options
context:
space:
mode:
authorMustafa Quraish <mustafaq9@gmail.com>2021-09-07 23:33:33 -0400
committerAndreas Kling <kling@serenityos.org>2021-09-09 11:35:50 +0200
commit111ef19114e0bb3673e436f3f1ec458db66247d1 (patch)
treee6bc806909237a6969d446bad4807273b344eae9 /Userland/Applications
parentec73247e90a05d96cb16b5c85b7e41bb32e9d2a7 (diff)
downloadserenity-111ef19114e0bb3673e436f3f1ec458db66247d1.zip
PixelPaint: Add "Brush Mode" to EraseTool :^)
Previously EraseTool would only let you have hard lines, similar to PenTool. After inheriting from BrushTool in previous commits, making the eraser (optionally) behave like a brush is much easier. We only need to change how the colors are handled for the hardness, which is why the `draw_point()` call is a bit more involved. Just blending the colors doesn't work here since we actually want to replace the previous color, unlike in BrushTool where we are just layering the color on top.
Diffstat (limited to 'Userland/Applications')
-rw-r--r--Userland/Applications/PixelPaint/EraseTool.cpp65
-rw-r--r--Userland/Applications/PixelPaint/EraseTool.h5
2 files changed, 66 insertions, 4 deletions
diff --git a/Userland/Applications/PixelPaint/EraseTool.cpp b/Userland/Applications/PixelPaint/EraseTool.cpp
index 88f2cb3269..85b2130530 100644
--- a/Userland/Applications/PixelPaint/EraseTool.cpp
+++ b/Userland/Applications/PixelPaint/EraseTool.cpp
@@ -14,6 +14,7 @@
#include <LibGUI/Label.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Painter.h>
+#include <LibGUI/RadioButton.h>
#include <LibGUI/ValueSlider.h>
#include <LibGfx/Bitmap.h>
@@ -36,10 +37,26 @@ Color EraseTool::color_for(GUI::MouseEvent const&)
void EraseTool::draw_point(Gfx::Bitmap& bitmap, Gfx::Color const& color, Gfx::IntPoint const& point)
{
- int radius = size() / 2;
- Gfx::IntRect rect { point.x() - radius, point.y() - radius, size(), size() };
- GUI::Painter painter(bitmap);
- painter.clear_rect(rect, color);
+ if (m_draw_mode == DrawMode::Pencil) {
+ int radius = size() / 2;
+ Gfx::IntRect rect { point.x() - radius, point.y() - radius, size(), size() };
+ GUI::Painter painter(bitmap);
+ painter.clear_rect(rect, color);
+ } else {
+ for (int y = point.y() - size(); y < point.y() + size(); y++) {
+ for (int x = point.x() - size(); x < point.x() + size(); x++) {
+ auto distance = point.distance_from({ x, y });
+ if (x < 0 || x >= bitmap.width() || y < 0 || y >= bitmap.height())
+ continue;
+ if (distance >= size())
+ continue;
+ auto old_color = bitmap.get_pixel(x, y);
+ auto falloff = (1.0 - double { distance / size() }) * (1.0 / (100 - hardness()));
+ auto new_color = old_color.interpolate(color, falloff);
+ bitmap.set_pixel(x, y, new_color);
+ }
+ }
+ }
}
GUI::Widget* EraseTool::get_properties_widget()
@@ -65,6 +82,23 @@ GUI::Widget* EraseTool::get_properties_widget()
};
set_primary_slider(&size_slider);
+ auto& hardness_container = m_properties_widget->add<GUI::Widget>();
+ hardness_container.set_fixed_height(20);
+ hardness_container.set_layout<GUI::HorizontalBoxLayout>();
+
+ auto& hardness_label = hardness_container.add<GUI::Label>("Hardness:");
+ hardness_label.set_text_alignment(Gfx::TextAlignment::CenterLeft);
+ hardness_label.set_fixed_size(80, 20);
+
+ auto& hardness_slider = hardness_container.add<GUI::ValueSlider>(Orientation::Horizontal, "%");
+ hardness_slider.set_range(1, 99);
+ hardness_slider.set_value(hardness());
+
+ hardness_slider.on_change = [&](int value) {
+ set_hardness(value);
+ };
+ set_secondary_slider(&hardness_slider);
+
auto& secondary_color_container = m_properties_widget->add<GUI::Widget>();
secondary_color_container.set_fixed_height(20);
secondary_color_container.set_layout<GUI::HorizontalBoxLayout>();
@@ -75,6 +109,29 @@ GUI::Widget* EraseTool::get_properties_widget()
use_secondary_color_checkbox.on_checked = [&](bool checked) {
m_use_secondary_color = checked;
};
+
+ auto& mode_container = m_properties_widget->add<GUI::Widget>();
+ mode_container.set_fixed_height(46);
+ mode_container.set_layout<GUI::HorizontalBoxLayout>();
+ auto& mode_label = mode_container.add<GUI::Label>("Draw Mode:");
+ mode_label.set_text_alignment(Gfx::TextAlignment::CenterLeft);
+ mode_label.set_fixed_size(80, 20);
+
+ auto& mode_radio_container = mode_container.add<GUI::Widget>();
+ mode_radio_container.set_layout<GUI::VerticalBoxLayout>();
+ auto& pencil_mode_radio = mode_radio_container.add<GUI::RadioButton>("Pencil");
+ auto& brush_mode_radio = mode_radio_container.add<GUI::RadioButton>("Brush");
+
+ pencil_mode_radio.on_checked = [&](bool) {
+ m_draw_mode = DrawMode::Pencil;
+ hardness_slider.set_enabled(false);
+ };
+ brush_mode_radio.on_checked = [&](bool) {
+ m_draw_mode = DrawMode::Brush;
+ hardness_slider.set_enabled(true);
+ };
+
+ pencil_mode_radio.set_checked(true);
}
return m_properties_widget.ptr();
diff --git a/Userland/Applications/PixelPaint/EraseTool.h b/Userland/Applications/PixelPaint/EraseTool.h
index b8fa8a6ff2..6ae01225eb 100644
--- a/Userland/Applications/PixelPaint/EraseTool.h
+++ b/Userland/Applications/PixelPaint/EraseTool.h
@@ -28,6 +28,11 @@ protected:
private:
RefPtr<GUI::Widget> m_properties_widget;
+ enum class DrawMode {
+ Pencil,
+ Brush,
+ };
+ DrawMode m_draw_mode { DrawMode::Brush };
bool m_use_secondary_color { false };
};