mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:32:46 +00:00 
			
		
		
		
	PixelPaint: Allow bigger Brush-Tool sizes
This patch allows a bigger brush tool size of 250 pixels and limits the cursor bitmap to a reasonable size so that its not much bigger than the image editor size. If the cursor is bigger as the editor it is rended with a red edge to indicate that the actual cursor is bigger than displayed. This change mitigates the OOM conditions when the cursor gets unusual big.
This commit is contained in:
		
							parent
							
								
									55edfe5c3c
								
							
						
					
					
						commit
						31ee20e179
					
				
					 4 changed files with 46 additions and 22 deletions
				
			
		|  | @ -1,7 +1,7 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2020, Ben Jilks <benjyjilks@gmail.com> | ||||
|  * Copyright (c) 2021, Mustafa Quraish <mustafa@serenityos.org> | ||||
|  * Copyright (c) 2022, Torsten Engelmann <engelTorsten@gmx.de> | ||||
|  * Copyright (c) 2022-2023, Torsten Engelmann <engelTorsten@gmx.de> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
|  | @ -149,10 +149,10 @@ ErrorOr<GUI::Widget*> BrushTool::get_properties_widget() | |||
| 
 | ||||
|         auto size_label = TRY(size_container->try_add<GUI::Label>("Size:"_string)); | ||||
|         size_label->set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||
|         size_label->set_fixed_size(80, 20); | ||||
|         size_label->set_fixed_size(60, 20); | ||||
| 
 | ||||
|         auto size_slider = TRY(size_container->try_add<GUI::ValueSlider>(Orientation::Horizontal, "px"_string)); | ||||
|         size_slider->set_range(1, 100); | ||||
|         size_slider->set_range(1, 250); | ||||
|         size_slider->set_value(m_size); | ||||
|         size_slider->set_override_cursor(cursor()); | ||||
| 
 | ||||
|  | @ -169,7 +169,7 @@ ErrorOr<GUI::Widget*> BrushTool::get_properties_widget() | |||
| 
 | ||||
|         auto hardness_label = TRY(hardness_container->try_add<GUI::Label>("Hardness:"_string)); | ||||
|         hardness_label->set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||
|         hardness_label->set_fixed_size(80, 20); | ||||
|         hardness_label->set_fixed_size(60, 20); | ||||
| 
 | ||||
|         auto hardness_slider = TRY(hardness_container->try_add<GUI::ValueSlider>(Orientation::Horizontal, "%"_string)); | ||||
|         hardness_slider->set_range(1, 100); | ||||
|  | @ -188,19 +188,23 @@ ErrorOr<GUI::Widget*> BrushTool::get_properties_widget() | |||
| NonnullRefPtr<Gfx::Bitmap> BrushTool::build_cursor() | ||||
| { | ||||
|     m_scale_last_created_cursor = m_editor ? m_editor->scale() : 1; | ||||
|     auto scaled_size = size() * m_scale_last_created_cursor; | ||||
|     auto containing_box_size = 2 * scaled_size; | ||||
|     auto containing_box_size = AK::clamp(preferred_cursor_size(), 1.0f, max_allowed_cursor_size()); | ||||
|     auto centered = containing_box_size / 2; | ||||
|     NonnullRefPtr<Gfx::Bitmap> new_cursor = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, Gfx::IntSize(containing_box_size, containing_box_size)).release_value_but_fixme_should_propagate_errors(); | ||||
| 
 | ||||
|     Gfx::Painter painter { new_cursor }; | ||||
|     Gfx::AntiAliasingPainter aa_painter { painter }; | ||||
| 
 | ||||
|     painter.draw_line({ scaled_size - 5, scaled_size }, { scaled_size + 5, scaled_size }, Color::LightGray, 3); | ||||
|     painter.draw_line({ scaled_size, scaled_size - 5 }, { scaled_size, scaled_size + 5 }, Color::LightGray, 3); | ||||
|     painter.draw_line({ scaled_size - 5, scaled_size }, { scaled_size + 5, scaled_size }, Color::MidGray, 1); | ||||
|     painter.draw_line({ scaled_size, scaled_size - 5 }, { scaled_size, scaled_size + 5 }, Color::MidGray, 1); | ||||
|     aa_painter.draw_ellipse(Gfx::IntRect(0, 0, containing_box_size, containing_box_size), Color::LightGray, 1); | ||||
| 
 | ||||
|     painter.draw_line({ centered - 5, centered }, { centered + 5, centered }, Color::LightGray, 3); | ||||
|     painter.draw_line({ centered, centered - 5 }, { centered, centered + 5 }, Color::LightGray, 3); | ||||
|     painter.draw_line({ centered - 5, centered }, { centered + 5, centered }, Color::MidGray, 1); | ||||
|     painter.draw_line({ centered, centered - 5 }, { centered, centered + 5 }, Color::MidGray, 1); | ||||
|     if (max_allowed_cursor_size() != containing_box_size) { | ||||
|         aa_painter.draw_ellipse(Gfx::IntRect(0, 0, containing_box_size, containing_box_size), Color::LightGray, 1); | ||||
|     } else { | ||||
|         aa_painter.draw_ellipse(Gfx::IntRect(0, 0, containing_box_size, containing_box_size), Color::Red, 1); | ||||
|         aa_painter.draw_ellipse(Gfx::IntRect(3, 3, containing_box_size - 6, containing_box_size - 6), Color::LightGray, 1); | ||||
|     } | ||||
|     return new_cursor; | ||||
| } | ||||
| 
 | ||||
|  | @ -211,4 +215,13 @@ void BrushTool::refresh_editor_cursor() | |||
|         m_editor->update_tool_cursor(); | ||||
| } | ||||
| 
 | ||||
| float BrushTool::preferred_cursor_size() | ||||
| { | ||||
|     return 2 * size() * (m_editor ? m_editor->scale() : 1); | ||||
| } | ||||
| 
 | ||||
| float BrushTool::max_allowed_cursor_size() | ||||
| { | ||||
|     return m_editor ? Gfx::IntPoint(0, 0).distance_from({ m_editor->width(), m_editor->height() }) * 1.1f : 500; | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
|  * Copyright (c) 2020, Ben Jilks <benjyjilks@gmail.com> | ||||
|  * Copyright (c) 2021, Mustafa Quraish <mustafa@serenityos.org> | ||||
|  * Copyright (c) 2022, the SerenityOS developers. | ||||
|  * Copyright (c) 2022, Torsten Engelmann <engelTorsten@gmx.de> | ||||
|  * Copyright (c) 2022-2023, Torsten Engelmann <engelTorsten@gmx.de> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
|  | @ -50,6 +50,8 @@ protected: | |||
|     virtual void draw_line(Gfx::Bitmap& bitmap, Gfx::Color color, Gfx::IntPoint start, Gfx::IntPoint end); | ||||
|     virtual NonnullRefPtr<Gfx::Bitmap> build_cursor(); | ||||
|     void refresh_editor_cursor(); | ||||
|     virtual float preferred_cursor_size(); | ||||
|     virtual float max_allowed_cursor_size(); | ||||
|     float m_scale_last_created_cursor = 0; | ||||
| 
 | ||||
| private: | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ ErrorOr<GUI::Widget*> EraseTool::get_properties_widget() | |||
|         size_label->set_fixed_size(80, 20); | ||||
| 
 | ||||
|         auto size_slider = TRY(size_container->try_add<GUI::ValueSlider>(Orientation::Horizontal, "px"_string)); | ||||
|         size_slider->set_range(1, 100); | ||||
|         size_slider->set_range(1, 250); | ||||
|         size_slider->set_value(size()); | ||||
| 
 | ||||
|         size_slider->on_change = [this, size_slider](int value) { | ||||
|  | @ -144,20 +144,28 @@ NonnullRefPtr<Gfx::Bitmap> EraseTool::build_cursor() | |||
|         return BrushTool::build_cursor(); | ||||
| 
 | ||||
|     m_scale_last_created_cursor = m_editor ? m_editor->scale() : 1; | ||||
|     int scaled_size = size() * m_scale_last_created_cursor; | ||||
|     int cursor_size = AK::clamp(preferred_cursor_size(), 1, max_allowed_cursor_size()); | ||||
| 
 | ||||
|     NonnullRefPtr<Gfx::Bitmap> new_cursor = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, Gfx::IntSize(scaled_size, scaled_size)).release_value_but_fixme_should_propagate_errors(); | ||||
|     NonnullRefPtr<Gfx::Bitmap> new_cursor = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, Gfx::IntSize(cursor_size, cursor_size)).release_value_but_fixme_should_propagate_errors(); | ||||
| 
 | ||||
|     Gfx::IntRect rect { 0, 0, scaled_size, scaled_size }; | ||||
|     Gfx::Painter painter { new_cursor }; | ||||
| 
 | ||||
|     painter.draw_rect(rect, Color::LightGray); | ||||
|     painter.draw_line({ scaled_size / 2 - 5, scaled_size / 2 }, { scaled_size / 2 + 5, scaled_size / 2 }, Color::LightGray, 3); | ||||
|     painter.draw_line({ scaled_size / 2, scaled_size / 2 - 5 }, { scaled_size / 2, scaled_size / 2 + 5 }, Color::LightGray, 3); | ||||
|     painter.draw_line({ scaled_size / 2 - 5, scaled_size / 2 }, { scaled_size / 2 + 5, scaled_size / 2 }, Color::MidGray, 1); | ||||
|     painter.draw_line({ scaled_size / 2, scaled_size / 2 - 5 }, { scaled_size / 2, scaled_size / 2 + 5 }, Color::MidGray, 1); | ||||
|     if (preferred_cursor_size() > max_allowed_cursor_size()) { | ||||
|         painter.draw_rect({ 0, 0, cursor_size, cursor_size }, Color::Red); | ||||
|         painter.draw_rect({ 3, 3, cursor_size - 6, cursor_size - 6 }, Color::LightGray); | ||||
|     } else { | ||||
|         painter.draw_rect({ 0, 0, cursor_size, cursor_size }, Color::LightGray); | ||||
|     } | ||||
|     painter.draw_line({ cursor_size / 2 - 5, cursor_size / 2 }, { cursor_size / 2 + 5, cursor_size / 2 }, Color::LightGray, 3); | ||||
|     painter.draw_line({ cursor_size / 2, cursor_size / 2 - 5 }, { cursor_size / 2, cursor_size / 2 + 5 }, Color::LightGray, 3); | ||||
|     painter.draw_line({ cursor_size / 2 - 5, cursor_size / 2 }, { cursor_size / 2 + 5, cursor_size / 2 }, Color::MidGray, 1); | ||||
|     painter.draw_line({ cursor_size / 2, cursor_size / 2 - 5 }, { cursor_size / 2, cursor_size / 2 + 5 }, Color::MidGray, 1); | ||||
| 
 | ||||
|     return new_cursor; | ||||
| } | ||||
| 
 | ||||
| float EraseTool::preferred_cursor_size() | ||||
| { | ||||
|     return size() * (m_editor ? m_editor->scale() : 1); | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ protected: | |||
|     virtual Color color_for(GUI::MouseEvent const& event) override; | ||||
|     virtual void draw_point(Gfx::Bitmap& bitmap, Gfx::Color color, Gfx::IntPoint point) override; | ||||
|     virtual NonnullRefPtr<Gfx::Bitmap> build_cursor() override; | ||||
|     virtual float preferred_cursor_size() override; | ||||
| 
 | ||||
| private: | ||||
|     virtual StringView tool_name() const override { return "Erase Tool"sv; } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Torstennator
						Torstennator