summaryrefslogtreecommitdiff
path: root/Userland/Applications
diff options
context:
space:
mode:
authorTorstennator <engelTorsten@gmx.de>2023-04-25 17:48:21 +0200
committerSam Atkins <atkinssj@gmail.com>2023-04-29 11:55:31 +0100
commitcd33f271b16fda7213a35b3ae1bad04ff270b7eb (patch)
treebc00b472e5043b2c23b23630e1750186c658afb7 /Userland/Applications
parentabcfaca3da4cde641894e724cb6ab1541c6d93e6 (diff)
downloadserenity-cd33f271b16fda7213a35b3ae1bad04ff270b7eb.zip
PixelPaint: Add radial gradient support
This patch adds radial gradients to the gradients tool.
Diffstat (limited to 'Userland/Applications')
-rw-r--r--Userland/Applications/PixelPaint/Tools/GradientTool.cpp231
-rw-r--r--Userland/Applications/PixelPaint/Tools/GradientTool.h31
2 files changed, 221 insertions, 41 deletions
diff --git a/Userland/Applications/PixelPaint/Tools/GradientTool.cpp b/Userland/Applications/PixelPaint/Tools/GradientTool.cpp
index d5b3e17007..2d89f7b335 100644
--- a/Userland/Applications/PixelPaint/Tools/GradientTool.cpp
+++ b/Userland/Applications/PixelPaint/Tools/GradientTool.cpp
@@ -13,6 +13,8 @@
#include <LibGUI/BoxLayout.h>
#include <LibGUI/Button.h>
#include <LibGUI/CheckBox.h>
+#include <LibGUI/ComboBox.h>
+#include <LibGUI/ItemListModel.h>
#include <LibGUI/Label.h>
#include <LibGUI/OpacitySlider.h>
#include <LibGUI/Painter.h>
@@ -26,7 +28,7 @@ namespace PixelPaint {
Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap const>> GradientTool::cursor()
{
- if (m_hover_over_drag_handle || m_hover_over_start_handle || m_hover_over_end_handle)
+ if (m_hover_over_drag_handle || m_hover_over_start_handle || m_hover_over_end_handle || m_hover_over_transversal_a_handle || m_hover_over_transversal_b_handle)
return Gfx::StandardCursor::Hand;
if (m_button_pressed)
@@ -45,11 +47,11 @@ void GradientTool::on_mousedown(Layer* layer, MouseEvent& event)
return;
m_button_pressed = true;
- if (!m_hover_over_start_handle && !m_hover_over_end_handle) {
- if (has_gradient_start_end()) {
+ if (!m_hover_over_start_handle && !m_hover_over_end_handle && !m_hover_over_transversal_a_handle && !m_hover_over_transversal_b_handle) {
+ if (has_gradient_data()) {
Gfx::IntPoint movement_delta = layer_event.position() - m_gradient_center.value();
m_gradient_center = layer_event.position();
- translate_gradient_start_end(movement_delta, false);
+ move_gradient_position(movement_delta);
calculate_gradient_lines();
} else {
m_gradient_center = layer_event.position();
@@ -64,7 +66,7 @@ void GradientTool::on_mousedown(Layer* layer, MouseEvent& event)
void GradientTool::on_mousemove(Layer* layer, MouseEvent& event)
{
// Check if user is hovering over a handle
- if (layer && m_editor && !m_button_pressed && has_gradient_start_end()) {
+ if (layer && m_editor && !m_button_pressed && has_gradient_data()) {
auto set_hover_flag = [&](bool& flag, Optional<Gfx::IntPoint> const p) {
auto handle_offset = m_editor->content_to_frame_position(layer->location());
float scale = m_editor->scale();
@@ -80,6 +82,11 @@ void GradientTool::on_mousemove(Layer* layer, MouseEvent& event)
set_hover_flag(m_hover_over_start_handle, m_gradient_start.value());
set_hover_flag(m_hover_over_drag_handle, m_gradient_center.value());
set_hover_flag(m_hover_over_end_handle, m_gradient_end.value());
+
+ if (m_mode == GradientMode::Radial) {
+ set_hover_flag(m_hover_over_transversal_a_handle, m_gradient_transversal_a.value());
+ set_hover_flag(m_hover_over_transversal_b_handle, m_gradient_transversal_b.value());
+ }
}
if (!layer || !m_button_pressed)
@@ -88,20 +95,26 @@ void GradientTool::on_mousemove(Layer* layer, MouseEvent& event)
auto& layer_event = event.layer_event();
if (!m_hover_over_drag_handle && (m_hover_over_start_handle || m_hover_over_end_handle)) {
auto movement_delta = m_hover_over_start_handle ? layer_event.position() - m_gradient_start.value() : layer_event.position() - m_gradient_end.value();
- translate_gradient_start_end(m_hover_over_start_handle ? movement_delta.scaled({ -1, -1 }) : movement_delta);
+ rotate_gradient_points(m_hover_over_start_handle ? movement_delta.scaled({ -1, -1 }) : movement_delta);
+ }
+
+ if (!m_hover_over_drag_handle && (m_hover_over_transversal_a_handle || m_hover_over_transversal_b_handle)) {
+ auto distance_to_center = layer_event.position().distance_from(m_gradient_center.value());
+ auto new_left_right_distance_fraction = distance_to_center / m_gradient_center.value().distance_from(m_gradient_start.value());
+ calculate_transversal_points(new_left_right_distance_fraction);
}
if (m_hover_over_drag_handle) {
auto movement_delta = layer_event.position() - m_gradient_center.value();
m_gradient_center.value().translate_by(movement_delta);
- translate_gradient_start_end(movement_delta, false);
+ move_gradient_position(movement_delta);
}
- if (!(m_hover_over_drag_handle || m_hover_over_start_handle || m_hover_over_end_handle))
- update_gradient_end_and_derive_start(layer_event.position());
+ if (!(m_hover_over_drag_handle || m_hover_over_start_handle || m_hover_over_end_handle || m_hover_over_transversal_a_handle || m_hover_over_transversal_b_handle))
+ update_gradient_with_initial_values(layer_event.position());
// If Shift is pressed, align the gradient horizontally or vertically
- if (m_shift_pressed && has_gradient_start_end()) {
+ if (m_shift_pressed && has_gradient_data() && m_mode == GradientMode::Linear) {
auto delta = m_gradient_center.value() - m_gradient_end.value();
if (AK::abs(delta.x()) < AK::abs(delta.y())) {
m_gradient_start.value().set_x(m_gradient_center.value().x());
@@ -158,7 +171,7 @@ void GradientTool::on_keyup(GUI::KeyEvent& event)
void GradientTool::on_second_paint(Layer const* layer, GUI::PaintEvent& event)
{
- if (!layer || !has_gradient_start_end())
+ if (!layer || !has_gradient_data())
return;
GUI::Painter painter(*m_editor);
@@ -168,13 +181,13 @@ void GradientTool::on_second_paint(Layer const* layer, GUI::PaintEvent& event)
void GradientTool::on_primary_color_change(Color)
{
- if (m_gradient_end.has_value())
+ if (has_gradient_data())
m_editor->update();
}
void GradientTool::on_secondary_color_change(Color)
{
- if (m_gradient_end.has_value())
+ if (has_gradient_data())
m_editor->update();
}
@@ -189,6 +202,35 @@ ErrorOr<GUI::Widget*> GradientTool::get_properties_widget()
auto properties_widget = TRY(GUI::Widget::try_create());
(void)TRY(properties_widget->try_set_layout<GUI::VerticalBoxLayout>());
+ auto mode_container = TRY(properties_widget->try_add<GUI::Widget>());
+ mode_container->set_fixed_height(20);
+ (void)TRY(mode_container->try_set_layout<GUI::HorizontalBoxLayout>());
+ auto mode_label = TRY(mode_container->try_add<GUI::Label>("Gradient Type:"));
+ mode_label->set_text_alignment(Gfx::TextAlignment::CenterLeft);
+ mode_label->set_fixed_size(80, 20);
+
+ static constexpr auto s_mode_names = [] {
+ Array<StringView, (int)GradientMode::__Count> names;
+ for (size_t i = 0; i < names.size(); i++) {
+ switch ((GradientMode)i) {
+ case GradientMode::Linear:
+ names[i] = "Linear"sv;
+ break;
+ case GradientMode::Radial:
+ names[i] = "Radial"sv;
+ break;
+ default:
+ break;
+ }
+ }
+ return names;
+ }();
+
+ auto mode_combobox = TRY(mode_container->try_add<GUI::ComboBox>());
+ mode_combobox->set_only_allow_values_from_model(true);
+ mode_combobox->set_model(*GUI::ItemListModel<StringView, decltype(s_mode_names)>::create(s_mode_names));
+ mode_combobox->set_selected_index((int)m_mode, GUI::AllowCallback::No);
+
auto size_container = TRY(properties_widget->try_add<GUI::Widget>());
size_container->set_fixed_height(20);
(void)TRY(size_container->try_set_layout<GUI::HorizontalBoxLayout>());
@@ -208,6 +250,39 @@ ErrorOr<GUI::Widget*> GradientTool::get_properties_widget()
set_primary_slider(opacity_slider);
+ auto hardness_container = TRY(properties_widget->try_add<GUI::Widget>());
+ (void)TRY(hardness_container->try_set_layout<GUI::HorizontalBoxLayout>());
+ hardness_container->set_fixed_height(20);
+ hardness_container->set_visible(m_mode == GradientMode::Radial);
+
+ mode_combobox->on_change = [this, hardness_container](auto&, auto& model_index) {
+ VERIFY(model_index.row() >= 0);
+ VERIFY(model_index.row() < (int)GradientMode::__Count);
+
+ GradientMode selected_mode = model_index.row() == 0 ? GradientMode::Linear : GradientMode::Radial;
+
+ if (m_mode != selected_mode) {
+ m_mode = selected_mode;
+ reset();
+ }
+
+ hardness_container->set_visible(m_mode == GradientMode::Radial);
+ };
+
+ auto hardness_label = TRY(hardness_container->try_add<GUI::Label>("Hardness:"));
+ hardness_label->set_text_alignment(Gfx::TextAlignment::CenterLeft);
+
+ auto hardness_slider = TRY(hardness_container->try_add<GUI::HorizontalOpacitySlider>());
+ hardness_slider->set_range(1, 99);
+ hardness_slider->set_value(m_hardness);
+ hardness_slider->on_change = [this](int value) {
+ if (m_mode == GradientMode::Radial && m_editor) {
+ m_hardness = value;
+ m_editor->update();
+ }
+ };
+ set_secondary_slider(hardness_slider);
+
auto use_secondary_color_checkbox = TRY(properties_widget->try_add<GUI::CheckBox>(TRY("Use secondary color"_string)));
use_secondary_color_checkbox->on_checked = [this](bool checked) {
m_use_secondary_color = checked;
@@ -231,10 +306,8 @@ ErrorOr<GUI::Widget*> GradientTool::get_properties_widget()
void GradientTool::rasterize_gradient()
{
- if (!has_gradient_start_end())
- return;
auto layer = m_editor->active_layer();
- if (!layer)
+ if (!layer || !has_gradient_data())
return;
GUI::Painter painter(layer->get_scratch_edited_bitmap());
@@ -278,7 +351,7 @@ void GradientTool::draw_gradient(GUI::Painter& painter, bool with_guidelines, co
int height = m_editor->active_layer()->rect().height() * scale;
float rotation_radians = atan2f(t_gradient_begin_line.a().y() - t_gradient_end_line.a().y(), t_gradient_begin_line.a().x() - t_gradient_end_line.a().x());
- float rotation_degrees = ((rotation_radians * 180) / static_cast<float>(M_PI)) - 90;
+ float rotation_degrees = (rotation_radians * 180) / AK::Pi<float>;
auto determine_required_side_length = [&](int center, int side_length) {
if (center < 0)
@@ -289,10 +362,12 @@ void GradientTool::draw_gradient(GUI::Painter& painter, bool with_guidelines, co
return 2 * (AK::max(center + side_length, side_length - center));
};
+ auto scaled_gradient_center = m_gradient_center.value().to_type<float>().scaled(scale, scale).to_type<int>();
auto gradient_rect_height = determine_required_side_length(t_gradient_center.y(), height);
auto gradient_rect_width = determine_required_side_length(t_gradient_center.x(), width);
- auto gradient_rect = Gfx::IntRect::centered_at(t_gradient_center, { gradient_rect_width, gradient_rect_height });
- float overall_gradient_length_in_rect = Gfx::calculate_gradient_length(gradient_rect.size(), rotation_degrees);
+ auto gradient_max_side_length = AK::max(gradient_rect_height, gradient_rect_width);
+ auto gradient_rect = Gfx::IntRect::centered_at(t_gradient_center, { gradient_max_side_length, gradient_max_side_length });
+ float overall_gradient_length_in_rect = Gfx::calculate_gradient_length(gradient_rect.size(), rotation_degrees - 90);
if (m_gradient_half_length == 0 || overall_gradient_length_in_rect == 0 || isnan(overall_gradient_length_in_rect))
return;
@@ -313,32 +388,83 @@ void GradientTool::draw_gradient(GUI::Painter& painter, bool with_guidelines, co
Gfx::PainterStateSaver saver(painter);
if (gradient_clip.has_value())
painter.add_clip_rect(*gradient_clip);
- painter.fill_rect_with_linear_gradient(gradient_rect, Array { Gfx::ColorStop { start_color, 0.5f - gradient_half_width_percentage_offset }, Gfx::ColorStop { end_color, 0.5f + gradient_half_width_percentage_offset } }, rotation_degrees);
+
+ switch (m_mode) {
+ case GradientMode::__Count:
+ break;
+ case GradientMode::Linear:
+ painter.fill_rect_with_linear_gradient(gradient_rect, Array { Gfx::ColorStop { start_color, 0.5f - gradient_half_width_percentage_offset }, Gfx::ColorStop { end_color, 0.5f + gradient_half_width_percentage_offset } }, rotation_degrees - 90);
+ break;
+ case GradientMode::Radial:
+
+ auto t_gradient_longitudinal = m_gradient_start.value().to_type<float>().scaled(scale, scale).translated(drawing_offset).to_type<int>();
+ auto t_gradient_transversal = m_gradient_transversal_a.value().to_type<float>().scaled(scale, scale).translated(drawing_offset).to_type<int>();
+ auto radial_size = Gfx::IntSize((AK::abs(t_gradient_center.distance_from(t_gradient_longitudinal))), (AK::abs(t_gradient_center.distance_from(t_gradient_transversal))));
+
+ AK::Array<Gfx::ColorStop, 3> colors = {
+ Gfx::ColorStop { .color = start_color, .position = 0.0f },
+ Gfx::ColorStop { .color = start_color, .position = m_hardness / 100.0f },
+ Gfx::ColorStop { .color = end_color, .position = 1.0f },
+ };
+
+ painter.fill_rect_with_radial_gradient(Gfx::IntRect(drawing_offset, { width, height }), colors, scaled_gradient_center, radial_size, {}, 180 - rotation_degrees);
+ break;
+ }
}
if (with_guidelines) {
Gfx::AntiAliasingPainter aa_painter = Gfx::AntiAliasingPainter(painter);
- aa_painter.draw_line(t_gradient_begin_line, Color::LightGray);
- aa_painter.draw_line(t_gradient_center_line, Color::MidGray);
- aa_painter.draw_line(t_gradient_end_line, Color::Black);
-
Gfx::FloatLine icon_line1_rotated_offset = Gfx::FloatLine({ -2, -4 }, { -2, 4 }).rotated(rotation_radians);
Gfx::FloatLine icon_line2_rotated_offset = Gfx::FloatLine({ 2, -4 }, { 2, 4 }).rotated(rotation_radians);
+ Gfx::FloatLine icon_line3_rotated_offset = Gfx::FloatLine({ -3, -2 }, { -3, 2 }).rotated(rotation_radians);
+ Gfx::FloatLine icon_line4_rotated_offset = Gfx::FloatLine({ 3, -2 }, { 3, 2 }).rotated(rotation_radians);
+ Gfx::FloatLine icon_line5_rotated_offset = Gfx::FloatLine({ 0, -5 }, { 0, 5 }).rotated(rotation_radians);
- auto draw_handle = [&](Gfx::IntPoint p, bool is_hovered, bool with_icon) {
+ auto draw_handle = [&](Gfx::IntPoint p, bool is_hovered, IconStyle with_icon) {
auto alpha = is_hovered ? 255 : 100;
auto translated_p = p.to_type<float>().scaled(scale, scale).translated(drawing_offset);
aa_painter.fill_circle(translated_p.to_type<int>(), 10, Color(Color::MidGray).with_alpha(alpha));
aa_painter.fill_circle(translated_p.to_type<int>(), 8, Color(Color::LightGray).with_alpha(alpha));
- if (with_icon) {
+ if (with_icon == IconStyle::ChangeWidthAndAngle) {
aa_painter.draw_line(icon_line1_rotated_offset.translated(translated_p), Color(Color::MidGray).with_alpha(alpha), 2);
aa_painter.draw_line(icon_line2_rotated_offset.translated(translated_p), Color(Color::MidGray).with_alpha(alpha), 2);
}
+ if (with_icon == IconStyle::RadialWidth) {
+ auto make_triangle_path = [&](Gfx::FloatPoint p1, Gfx::FloatPoint p2, Gfx::FloatPoint p3) {
+ Gfx::Path triangle;
+ triangle.move_to(p1.translated(translated_p));
+ triangle.line_to(p2.translated(translated_p));
+ triangle.line_to(p3.translated(translated_p));
+ triangle.close();
+ return triangle;
+ };
+
+ aa_painter.fill_path(make_triangle_path(
+ icon_line3_rotated_offset.a(),
+ icon_line4_rotated_offset.a(),
+ icon_line5_rotated_offset.a()),
+ Color(Color::MidGray).with_alpha(alpha), Gfx::Painter::WindingRule::EvenOdd);
+ aa_painter.fill_path(make_triangle_path(
+ icon_line3_rotated_offset.b(),
+ icon_line4_rotated_offset.b(),
+ icon_line5_rotated_offset.b()),
+ Color(Color::MidGray).with_alpha(alpha), Gfx::Painter::WindingRule::EvenOdd);
+ }
};
- draw_handle(m_gradient_start.value(), m_hover_over_start_handle, true);
- draw_handle(m_gradient_center.value(), m_hover_over_drag_handle, false);
- draw_handle(m_gradient_end.value(), m_hover_over_end_handle, true);
+
+ if (m_mode == GradientMode::Linear) {
+ aa_painter.draw_line(t_gradient_begin_line, Color::Black);
+ aa_painter.draw_line(t_gradient_center_line, Color::MidGray);
+ aa_painter.draw_line(t_gradient_end_line, Color::LightGray);
+ } else {
+ draw_handle(m_gradient_transversal_a.value(), m_hover_over_transversal_a_handle, IconStyle::RadialWidth);
+ draw_handle(m_gradient_transversal_b.value(), m_hover_over_transversal_b_handle, IconStyle::RadialWidth);
+ }
+
+ draw_handle(m_gradient_start.value(), m_hover_over_start_handle, IconStyle::ChangeWidthAndAngle);
+ draw_handle(m_gradient_center.value(), m_hover_over_drag_handle, IconStyle::None);
+ draw_handle(m_gradient_end.value(), m_hover_over_end_handle, IconStyle::ChangeWidthAndAngle);
}
}
@@ -347,11 +473,15 @@ void GradientTool::reset()
m_gradient_start = {};
m_gradient_center = {};
m_gradient_end = {};
+ m_gradient_transversal_a = {};
+ m_gradient_transversal_b = {};
m_gradient_half_length = 0;
m_physical_diagonal_layer_length = 0;
m_hover_over_drag_handle = false;
m_hover_over_start_handle = false;
m_hover_over_end_handle = false;
+ m_hover_over_transversal_a_handle = false;
+ m_hover_over_transversal_b_handle = false;
if (m_editor) {
m_editor->update();
@@ -359,20 +489,49 @@ void GradientTool::reset()
}
}
-void GradientTool::update_gradient_end_and_derive_start(Gfx::IntPoint const new_end_point)
+void GradientTool::update_gradient_with_initial_values(Gfx::IntPoint const new_end_point)
{
VERIFY(m_gradient_center.has_value());
m_gradient_end = new_end_point;
- m_gradient_start = m_gradient_center.value() - (m_gradient_end.value() - m_gradient_center.value());
+ auto deltaCenter = m_gradient_end.value() - m_gradient_center.value();
+ m_gradient_start = m_gradient_center.value() - deltaCenter;
+
+ if (m_mode == GradientMode::Radial) {
+ Gfx::IntPoint perpendicularDeltaCenter = { -deltaCenter.y(), deltaCenter.x() };
+ m_gradient_transversal_a = m_gradient_center.value() + perpendicularDeltaCenter;
+ m_gradient_transversal_b = m_gradient_center.value() - perpendicularDeltaCenter;
+ }
}
-void GradientTool::translate_gradient_start_end(Gfx::IntPoint const delta, bool update_start_counterwise)
+void GradientTool::move_gradient_position(Gfx::IntPoint const movement_delta)
+{
+ m_gradient_end.value().translate_by(movement_delta);
+ m_gradient_start.value().translate_by(movement_delta);
+
+ if (m_mode == GradientMode::Radial) {
+ m_gradient_transversal_a.value().translate_by(movement_delta);
+ m_gradient_transversal_b.value().translate_by(movement_delta);
+ }
+}
+
+void GradientTool::rotate_gradient_points(Gfx::IntPoint const delta)
{
m_gradient_end.value().translate_by(delta);
- if (update_start_counterwise)
- m_gradient_start.value().translate_by(delta.scaled(-1, -1));
- else
- m_gradient_start.value().translate_by(delta);
+ auto translation_distance_to_center = m_gradient_center.value().distance_from(m_gradient_end.value()) - m_gradient_center.value().distance_from(m_gradient_start.value());
+ m_gradient_start.value().translate_by(delta.scaled(-1, -1));
+
+ if (m_mode == GradientMode::Radial) {
+ auto new_horizontal_distance_fraction = (translation_distance_to_center + m_gradient_center.value().distance_from(m_gradient_transversal_a.value())) / m_gradient_center.value().distance_from(m_gradient_start.value());
+ calculate_transversal_points(new_horizontal_distance_fraction);
+ }
+}
+
+void GradientTool::calculate_transversal_points(float scale_fraction)
+{
+ m_gradient_transversal_a = Gfx::IntPoint(m_gradient_center.value().x() + (scale_fraction * (m_gradient_center.value().x() - m_perpendicular_point.x())),
+ m_gradient_center.value().y() + (scale_fraction * (m_gradient_center.value().y() - m_perpendicular_point.y())));
+ m_gradient_transversal_b = Gfx::IntPoint(m_gradient_center.value().x() + (-scale_fraction * (m_gradient_center.value().x() - m_perpendicular_point.x())),
+ m_gradient_center.value().y() + (-scale_fraction * (m_gradient_center.value().y() - m_perpendicular_point.y())));
}
}
diff --git a/Userland/Applications/PixelPaint/Tools/GradientTool.h b/Userland/Applications/PixelPaint/Tools/GradientTool.h
index 0ced524a2a..43c38cdbac 100644
--- a/Userland/Applications/PixelPaint/Tools/GradientTool.h
+++ b/Userland/Applications/PixelPaint/Tools/GradientTool.h
@@ -32,12 +32,29 @@ protected:
virtual StringView tool_name() const override { return "Gradient Tool"sv; }
private:
+ enum class GradientMode {
+ Linear,
+ Radial,
+ __Count,
+ };
+
+ enum class IconStyle {
+ None,
+ ChangeWidthAndAngle,
+ RadialWidth,
+ };
+
RefPtr<GUI::Widget> m_properties_widget;
Optional<Gfx::IntPoint> m_gradient_start;
Optional<Gfx::IntPoint> m_gradient_center;
Optional<Gfx::IntPoint> m_gradient_end;
+ Optional<Gfx::IntPoint> m_gradient_transversal_a;
+ Optional<Gfx::IntPoint> m_gradient_transversal_b;
Gfx::IntPoint m_perpendicular_point;
+ GradientMode m_mode = GradientMode::Linear;
+ int m_hardness = 25;
+
float m_gradient_half_length = 0;
float m_physical_diagonal_layer_length = 0;
bool m_button_pressed = false;
@@ -45,19 +62,23 @@ private:
bool m_hover_over_drag_handle = false;
bool m_hover_over_start_handle = false;
bool m_hover_over_end_handle = false;
+ bool m_hover_over_transversal_a_handle = false;
+ bool m_hover_over_transversal_b_handle = false;
int m_opacity = 100;
bool m_use_secondary_color { false };
Gfx::FloatLine m_gradient_begin_line;
Gfx::FloatLine m_gradient_center_line;
Gfx::FloatLine m_gradient_end_line;
- void reset();
+ void calculate_gradient_lines();
+ void calculate_transversal_points(float scale_fraction);
void draw_gradient(GUI::Painter&, bool with_guidelines = false, const Gfx::FloatPoint drawing_offset = { 0.0f, 0.0f }, float scale = 1, Optional<Gfx::IntRect const&> gradient_clip = {});
+ bool has_gradient_data() { return m_gradient_center.has_value() && m_gradient_end.has_value() && m_gradient_start.has_value(); }
+ void move_gradient_position(Gfx::IntPoint const movement_delta);
void rasterize_gradient();
- void calculate_gradient_lines();
- void update_gradient_end_and_derive_start(Gfx::IntPoint const);
- void translate_gradient_start_end(Gfx::IntPoint const delta, bool update_start_counterwise = true);
- bool has_gradient_start_end() { return m_gradient_center.has_value() && m_gradient_end.has_value() && m_gradient_start.has_value(); }
+ void reset();
+ void rotate_gradient_points(Gfx::IntPoint const delta);
+ void update_gradient_with_initial_values(Gfx::IntPoint const);
};
}