EraseTool.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Mustafa Quraish <mustafa@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "EraseTool.h"
  8. #include "../ImageEditor.h"
  9. #include "../Layer.h"
  10. #include <LibGUI/Action.h>
  11. #include <LibGUI/BoxLayout.h>
  12. #include <LibGUI/CheckBox.h>
  13. #include <LibGUI/Label.h>
  14. #include <LibGUI/Menu.h>
  15. #include <LibGUI/Painter.h>
  16. #include <LibGUI/RadioButton.h>
  17. #include <LibGUI/ValueSlider.h>
  18. #include <LibGfx/Bitmap.h>
  19. namespace PixelPaint {
  20. EraseTool::EraseTool()
  21. {
  22. }
  23. EraseTool::~EraseTool()
  24. {
  25. }
  26. Color EraseTool::color_for(GUI::MouseEvent const&)
  27. {
  28. if (m_use_secondary_color)
  29. return m_editor->secondary_color();
  30. return Color(255, 255, 255, 0);
  31. }
  32. void EraseTool::draw_point(Gfx::Bitmap& bitmap, Gfx::Color const& color, Gfx::IntPoint const& point)
  33. {
  34. if (m_draw_mode == DrawMode::Pencil) {
  35. int radius = size() / 2;
  36. Gfx::IntRect rect { point.x() - radius, point.y() - radius, size(), size() };
  37. GUI::Painter painter(bitmap);
  38. painter.clear_rect(rect, color);
  39. } else {
  40. for (int y = point.y() - size(); y < point.y() + size(); y++) {
  41. for (int x = point.x() - size(); x < point.x() + size(); x++) {
  42. auto distance = point.distance_from({ x, y });
  43. if (x < 0 || x >= bitmap.width() || y < 0 || y >= bitmap.height())
  44. continue;
  45. if (distance >= size())
  46. continue;
  47. auto old_color = bitmap.get_pixel(x, y);
  48. auto falloff = get_falloff(distance);
  49. auto new_color = old_color.interpolate(color, falloff);
  50. bitmap.set_pixel(x, y, new_color);
  51. }
  52. }
  53. }
  54. }
  55. GUI::Widget* EraseTool::get_properties_widget()
  56. {
  57. if (!m_properties_widget) {
  58. m_properties_widget = GUI::Widget::construct();
  59. m_properties_widget->set_layout<GUI::VerticalBoxLayout>();
  60. auto& size_container = m_properties_widget->add<GUI::Widget>();
  61. size_container.set_fixed_height(20);
  62. size_container.set_layout<GUI::HorizontalBoxLayout>();
  63. auto& size_label = size_container.add<GUI::Label>("Size:");
  64. size_label.set_text_alignment(Gfx::TextAlignment::CenterLeft);
  65. size_label.set_fixed_size(80, 20);
  66. auto& size_slider = size_container.add<GUI::ValueSlider>(Orientation::Horizontal, "px");
  67. size_slider.set_range(1, 100);
  68. size_slider.set_value(size());
  69. size_slider.on_change = [&](int value) {
  70. set_size(value);
  71. };
  72. set_primary_slider(&size_slider);
  73. auto& hardness_container = m_properties_widget->add<GUI::Widget>();
  74. hardness_container.set_fixed_height(20);
  75. hardness_container.set_layout<GUI::HorizontalBoxLayout>();
  76. auto& hardness_label = hardness_container.add<GUI::Label>("Hardness:");
  77. hardness_label.set_text_alignment(Gfx::TextAlignment::CenterLeft);
  78. hardness_label.set_fixed_size(80, 20);
  79. auto& hardness_slider = hardness_container.add<GUI::ValueSlider>(Orientation::Horizontal, "%");
  80. hardness_slider.set_range(1, 100);
  81. hardness_slider.set_value(hardness());
  82. hardness_slider.on_change = [&](int value) {
  83. set_hardness(value);
  84. };
  85. set_secondary_slider(&hardness_slider);
  86. auto& secondary_color_container = m_properties_widget->add<GUI::Widget>();
  87. secondary_color_container.set_fixed_height(20);
  88. secondary_color_container.set_layout<GUI::HorizontalBoxLayout>();
  89. auto& use_secondary_color_checkbox = secondary_color_container.add<GUI::CheckBox>();
  90. use_secondary_color_checkbox.set_checked(m_use_secondary_color);
  91. use_secondary_color_checkbox.set_text("Use secondary color");
  92. use_secondary_color_checkbox.on_checked = [&](bool checked) {
  93. m_use_secondary_color = checked;
  94. };
  95. auto& mode_container = m_properties_widget->add<GUI::Widget>();
  96. mode_container.set_fixed_height(46);
  97. mode_container.set_layout<GUI::HorizontalBoxLayout>();
  98. auto& mode_label = mode_container.add<GUI::Label>("Draw Mode:");
  99. mode_label.set_text_alignment(Gfx::TextAlignment::CenterLeft);
  100. mode_label.set_fixed_size(80, 20);
  101. auto& mode_radio_container = mode_container.add<GUI::Widget>();
  102. mode_radio_container.set_layout<GUI::VerticalBoxLayout>();
  103. auto& pencil_mode_radio = mode_radio_container.add<GUI::RadioButton>("Pencil");
  104. auto& brush_mode_radio = mode_radio_container.add<GUI::RadioButton>("Brush");
  105. pencil_mode_radio.on_checked = [&](bool) {
  106. m_draw_mode = DrawMode::Pencil;
  107. hardness_slider.set_enabled(false);
  108. };
  109. brush_mode_radio.on_checked = [&](bool) {
  110. m_draw_mode = DrawMode::Brush;
  111. hardness_slider.set_enabled(true);
  112. };
  113. pencil_mode_radio.set_checked(true);
  114. }
  115. return m_properties_widget.ptr();
  116. }
  117. }