diff --git a/Userland/Applications/PixelPaint/ImageEditor.cpp b/Userland/Applications/PixelPaint/ImageEditor.cpp index e23ae92859..f4478e7dd2 100644 --- a/Userland/Applications/PixelPaint/ImageEditor.cpp +++ b/Userland/Applications/PixelPaint/ImageEditor.cpp @@ -127,7 +127,7 @@ void ImageEditor::paint_event(GUI::PaintEvent& event) painter.add_clip_rect(frame_inner_rect()); { - Gfx::DisjointRectSet background_rects; + Gfx::DisjointIntRectSet background_rects; background_rects.add(frame_inner_rect()); background_rects.shatter(content_rect()); for (auto& rect : background_rects.rects()) diff --git a/Userland/Libraries/LibGfx/DisjointRectSet.h b/Userland/Libraries/LibGfx/DisjointRectSet.h index ac2a4c9878..6d4850802c 100644 --- a/Userland/Libraries/LibGfx/DisjointRectSet.h +++ b/Userland/Libraries/LibGfx/DisjointRectSet.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2022, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -12,6 +13,7 @@ namespace Gfx { +template class DisjointRectSet { public: DisjointRectSet(DisjointRectSet const&) = delete; @@ -20,7 +22,7 @@ public: DisjointRectSet() = default; ~DisjointRectSet() = default; - DisjointRectSet(IntRect const& rect) + DisjointRectSet(Rect const& rect) { m_rects.append(rect); } @@ -35,17 +37,17 @@ public: return rects; } - void move_by(int dx, int dy) + void move_by(T dx, T dy) { for (auto& r : m_rects) r.translate_by(dx, dy); } - void move_by(IntPoint const& delta) + void move_by(Point const& delta) { move_by(delta.x(), delta.y()); } - void add(IntRect const& rect) + void add(Rect const& rect) { if (add_no_shatter(rect) && m_rects.size() > 1) shatter(); @@ -74,7 +76,7 @@ public: } } - DisjointRectSet shatter(IntRect const& hammer) const + DisjointRectSet shatter(Rect const& hammer) const { if (hammer.is_empty()) return clone(); @@ -107,7 +109,7 @@ public: return shards; } - bool contains(IntRect const& rect) const + bool contains(Rect const& rect) const { if (is_empty() || rect.is_empty()) return false; @@ -123,7 +125,7 @@ public: return false; } - bool intersects(IntRect const& rect) const + bool intersects(Rect const& rect) const { for (auto& r : m_rects) { if (r.intersects(rect)) @@ -145,7 +147,7 @@ public: return false; } - DisjointRectSet intersected(IntRect const& rect) const + DisjointRectSet intersected(Rect const& rect) const { DisjointRectSet intersected_rects; intersected_rects.m_rects.ensure_capacity(m_rects.capacity()); @@ -178,7 +180,7 @@ public: } template - IterationDecision for_each_intersected(IntRect const& rect, Function f) const + IterationDecision for_each_intersected(Rect const& rect, Function f) const { if (is_empty() || rect.is_empty()) return IterationDecision::Continue; @@ -224,22 +226,22 @@ public: void clear() { m_rects.clear(); } void clear_with_capacity() { m_rects.clear_with_capacity(); } - Vector const& rects() const { return m_rects; } - Vector take_rects() { return move(m_rects); } + Vector, 32> const& rects() const { return m_rects; } + Vector, 32> take_rects() { return move(m_rects); } - void translate_by(int dx, int dy) + void translate_by(T dx, T dy) { for (auto& rect : m_rects) rect.translate_by(dx, dy); } - void translate_by(Gfx::IntPoint const& delta) + void translate_by(Point const& delta) { for (auto& rect : m_rects) rect.translate_by(delta); } private: - bool add_no_shatter(IntRect const& new_rect) + bool add_no_shatter(Rect const& new_rect) { if (new_rect.is_empty()) return false; @@ -254,7 +256,7 @@ private: void shatter() { - Vector output; + Vector, 32> output; output.ensure_capacity(m_rects.size()); bool pass_had_intersections = false; do { @@ -284,7 +286,7 @@ private: } while (pass_had_intersections); } - Vector m_rects; + Vector, 32> m_rects; }; } diff --git a/Userland/Libraries/LibGfx/Forward.h b/Userland/Libraries/LibGfx/Forward.h index 5477b5a6f1..369e1b072f 100644 --- a/Userland/Libraries/LibGfx/Forward.h +++ b/Userland/Libraries/LibGfx/Forward.h @@ -11,7 +11,10 @@ namespace Gfx { class Bitmap; class CharacterBitmap; class Color; + +template class DisjointRectSet; + class Emoji; class Font; class GlyphBitmap; @@ -44,6 +47,9 @@ class Rect; template class Quad; +using DisjointIntRectSet = DisjointRectSet; +using DisjointFloatRectSet = DisjointRectSet; + using IntLine = Line; using FloatLine = Line; diff --git a/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp b/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp index 15d43949d3..710b7a83b4 100644 --- a/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp @@ -39,7 +39,7 @@ void paint_box_shadow(PaintContext& context, Gfx::IntRect const& content_rect, B continue; auto fill_rect_masked = [](auto& painter, auto fill_rect, auto mask_rect, auto color) { - Gfx::DisjointRectSet rect_set; + Gfx::DisjointIntRectSet rect_set; rect_set.add(fill_rect); auto shattered = rect_set.shatter(mask_rect); for (auto& rect : shattered.rects()) diff --git a/Userland/Services/WindowServer/Animation.cpp b/Userland/Services/WindowServer/Animation.cpp index 37067a9c43..8f90694bda 100644 --- a/Userland/Services/WindowServer/Animation.cpp +++ b/Userland/Services/WindowServer/Animation.cpp @@ -45,7 +45,7 @@ void Animation::was_removed(Badge) m_was_removed = true; } -bool Animation::update(Badge, Gfx::Painter& painter, Screen& screen, Gfx::DisjointRectSet& flush_rects) +bool Animation::update(Badge, Gfx::Painter& painter, Screen& screen, Gfx::DisjointIntRectSet& flush_rects) { int elapsed_ms = m_timer.elapsed(); float progress = min((float)elapsed_ms / (float)m_duration, 1.0f); diff --git a/Userland/Services/WindowServer/Animation.h b/Userland/Services/WindowServer/Animation.h index 89f5e7787d..ab1386b6a4 100644 --- a/Userland/Services/WindowServer/Animation.h +++ b/Userland/Services/WindowServer/Animation.h @@ -33,9 +33,9 @@ public: void set_duration(int duration_in_ms); int duration() const { return m_duration; } - bool update(Badge, Gfx::Painter&, Screen&, Gfx::DisjointRectSet& flush_rects); + bool update(Badge, Gfx::Painter&, Screen&, Gfx::DisjointIntRectSet& flush_rects); - Function on_update; + Function on_update; Function on_stop; private: diff --git a/Userland/Services/WindowServer/Compositor.cpp b/Userland/Services/WindowServer/Compositor.cpp index d44f321d4f..b705f18137 100644 --- a/Userland/Services/WindowServer/Compositor.cpp +++ b/Userland/Services/WindowServer/Compositor.cpp @@ -746,7 +746,7 @@ void Compositor::invalidate_screen(Gfx::IntRect const& screen_rect) start_compose_async_timer(); } -void Compositor::invalidate_screen(Gfx::DisjointRectSet const& rects) +void Compositor::invalidate_screen(Gfx::DisjointIntRectSet const& rects) { m_dirty_screen_rects.add(rects.intersected(Screen::bounding_rect())); @@ -1210,7 +1210,7 @@ void Compositor::recompute_occlusions() m_opaque_wallpaper_rects.clear(); } if (!fullscreen_window || (fullscreen_window && !fullscreen_window->is_opaque())) { - Gfx::DisjointRectSet remaining_visible_screen_rects; + Gfx::DisjointIntRectSet remaining_visible_screen_rects; remaining_visible_screen_rects.add_many(Screen::rects()); bool have_transparent = false; wm.for_each_visible_window_from_front_to_back([&](Window& w) { @@ -1264,8 +1264,8 @@ void Compositor::recompute_occlusions() auto render_rect_on_screen = w.frame().render_rect().translated(transition_offset); auto visible_window_rects = remaining_visible_screen_rects.intersected(w.rect().translated(transition_offset)); - Gfx::DisjointRectSet opaque_covering; - Gfx::DisjointRectSet transparent_covering; + Gfx::DisjointIntRectSet opaque_covering; + Gfx::DisjointIntRectSet transparent_covering; bool found_this_window = false; wm.for_each_visible_window_from_back_to_front([&](Window& w2) { if (!found_this_window) { @@ -1412,7 +1412,7 @@ void Compositor::recompute_occlusions() } // Figure out the affected transparency rects underneath. First figure out if any transparency is visible at all - Gfx::DisjointRectSet transparent_underneath; + Gfx::DisjointIntRectSet transparent_underneath; wm.for_each_visible_window_from_back_to_front([&](Window& w2) { if (&w == &w2) return IterationDecision::Break; @@ -1517,7 +1517,7 @@ void Compositor::unregister_animation(Badge, Animation& animation) VERIFY(was_removed); } -void Compositor::update_animations(Screen& screen, Gfx::DisjointRectSet& flush_rects) +void Compositor::update_animations(Screen& screen, Gfx::DisjointIntRectSet& flush_rects) { auto& painter = *screen.compositor_screen_data().m_back_painter; // Iterating over the animations using remove_all_matching we can iterate @@ -1697,7 +1697,7 @@ void Compositor::switch_to_window_stack(WindowStack& new_window_stack, bool show VERIFY(!m_window_stack_transition_animation); m_window_stack_transition_animation = Animation::create(); m_window_stack_transition_animation->set_duration(250); - m_window_stack_transition_animation->on_update = [this, delta_x, delta_y](float progress, Gfx::Painter&, Screen&, Gfx::DisjointRectSet&) { + m_window_stack_transition_animation->on_update = [this, delta_x, delta_y](float progress, Gfx::Painter&, Screen&, Gfx::DisjointIntRectSet&) { VERIFY(m_transitioning_to_window_stack); VERIFY(m_current_window_stack); diff --git a/Userland/Services/WindowServer/Compositor.h b/Userland/Services/WindowServer/Compositor.h index 32924bb8c0..0be51b9f28 100644 --- a/Userland/Services/WindowServer/Compositor.h +++ b/Userland/Services/WindowServer/Compositor.h @@ -52,9 +52,9 @@ struct CompositorScreenData { bool m_cursor_back_is_valid { false }; bool m_have_flush_rects { false }; - Gfx::DisjointRectSet m_flush_rects; - Gfx::DisjointRectSet m_flush_transparent_rects; - Gfx::DisjointRectSet m_flush_special_rects; + Gfx::DisjointIntRectSet m_flush_rects; + Gfx::DisjointIntRectSet m_flush_transparent_rects; + Gfx::DisjointIntRectSet m_flush_special_rects; Gfx::Painter& overlay_painter() { return *m_temp_painter; } @@ -68,7 +68,7 @@ struct CompositorScreenData { template IterationDecision for_each_intersected_flushing_rect(Gfx::IntRect const& intersecting_rect, F f) { - auto iterate_flush_rects = [&](Gfx::DisjointRectSet const& flush_rects) { + auto iterate_flush_rects = [&](Gfx::DisjointIntRectSet const& flush_rects) { for (auto& rect : flush_rects.rects()) { auto intersection = intersecting_rect.intersected(rect); if (intersection.is_empty()) @@ -101,7 +101,7 @@ public: void invalidate_window(); void invalidate_screen(); void invalidate_screen(Gfx::IntRect const&); - void invalidate_screen(Gfx::DisjointRectSet const&); + void invalidate_screen(Gfx::DisjointIntRectSet const&); void screen_resolution_changed(); @@ -209,7 +209,7 @@ private: void change_cursor(Cursor const*); void flush(Screen&); Gfx::IntPoint window_transition_offset(Window&); - void update_animations(Screen&, Gfx::DisjointRectSet& flush_rects); + void update_animations(Screen&, Gfx::DisjointIntRectSet& flush_rects); void create_window_stack_switch_overlay(WindowStack&); void remove_window_stack_switch_overlays(); void stop_window_stack_switch_overlay_timer(); @@ -227,10 +227,10 @@ private: bool m_overlay_rects_changed { false }; IntrusiveList<&Overlay::m_list_node> m_overlay_list; - Gfx::DisjointRectSet m_overlay_rects; - Gfx::DisjointRectSet m_dirty_screen_rects; - Gfx::DisjointRectSet m_opaque_wallpaper_rects; - Gfx::DisjointRectSet m_transparent_wallpaper_rects; + Gfx::DisjointIntRectSet m_overlay_rects; + Gfx::DisjointIntRectSet m_dirty_screen_rects; + Gfx::DisjointIntRectSet m_opaque_wallpaper_rects; + Gfx::DisjointIntRectSet m_transparent_wallpaper_rects; WallpaperMode m_wallpaper_mode { WallpaperMode::Unchecked }; RefPtr m_wallpaper; diff --git a/Userland/Services/WindowServer/Screen.cpp b/Userland/Services/WindowServer/Screen.cpp index 378811c8db..27f86b5d5c 100644 --- a/Userland/Services/WindowServer/Screen.cpp +++ b/Userland/Services/WindowServer/Screen.cpp @@ -469,7 +469,7 @@ void Screen::constrain_pending_flush_rects() if (flush_rects.pending_flush_rects.is_empty()) return; Gfx::IntRect screen_rect({}, rect().size()); - Gfx::DisjointRectSet rects; + Gfx::DisjointIntRectSet rects; for (auto& fb_rect : flush_rects.pending_flush_rects) { Gfx::IntRect rect { (int)fb_rect.x, (int)fb_rect.y, (int)fb_rect.width, (int)fb_rect.height }; auto intersected_rect = rect.intersected(screen_rect); diff --git a/Userland/Services/WindowServer/Window.cpp b/Userland/Services/WindowServer/Window.cpp index d786a1ddb7..0ed9464faf 100644 --- a/Userland/Services/WindowServer/Window.cpp +++ b/Userland/Services/WindowServer/Window.cpp @@ -322,7 +322,7 @@ void Window::start_minimize_animation() } m_animation = Animation::create(); m_animation->set_duration(150); - m_animation->on_update = [this](float progress, Gfx::Painter& painter, Screen& screen, Gfx::DisjointRectSet& flush_rects) { + m_animation->on_update = [this](float progress, Gfx::Painter& painter, Screen& screen, Gfx::DisjointIntRectSet& flush_rects) { Gfx::PainterStateSaver saver(painter); painter.set_draw_op(Gfx::Painter::DrawOp::Invert); @@ -350,7 +350,7 @@ void Window::start_launch_animation(Gfx::IntRect const& launch_origin_rect) m_animation = Animation::create(); m_animation->set_duration(150); - m_animation->on_update = [this, launch_origin_rect](float progress, Gfx::Painter& painter, Screen& screen, Gfx::DisjointRectSet& flush_rects) { + m_animation->on_update = [this, launch_origin_rect](float progress, Gfx::Painter& painter, Screen& screen, Gfx::DisjointIntRectSet& flush_rects) { Gfx::PainterStateSaver saver(painter); painter.set_draw_op(Gfx::Painter::DrawOp::Invert); diff --git a/Userland/Services/WindowServer/Window.h b/Userland/Services/WindowServer/Window.h index 40918644f3..a7d8210973 100644 --- a/Userland/Services/WindowServer/Window.h +++ b/Userland/Services/WindowServer/Window.h @@ -227,7 +227,7 @@ public: void prepare_dirty_rects(); void clear_dirty_rects(); - Gfx::DisjointRectSet& dirty_rects() { return m_dirty_rects; } + Gfx::DisjointIntRectSet& dirty_rects() { return m_dirty_rects; } // Only used by WindowType::Applet. Perhaps it could be a Window subclass? I don't know. void set_rect_in_applet_area(Gfx::IntRect const& rect) { m_rect_in_applet_area = rect; } @@ -290,7 +290,7 @@ public: void remove_cursor_override() { m_cursor_override = nullptr; } void request_update(Gfx::IntRect const&, bool ignore_occlusion = false); - Gfx::DisjointRectSet take_pending_paint_rects() { return move(m_pending_paint_rects); } + Gfx::DisjointIntRectSet take_pending_paint_rects() { return move(m_pending_paint_rects); } void start_minimize_animation(); @@ -335,9 +335,9 @@ public: return true; } - Gfx::DisjointRectSet& opaque_rects() { return m_opaque_rects; } - Gfx::DisjointRectSet& transparency_rects() { return m_transparency_rects; } - Gfx::DisjointRectSet& transparency_wallpaper_rects() { return m_transparency_wallpaper_rects; } + Gfx::DisjointIntRectSet& opaque_rects() { return m_opaque_rects; } + Gfx::DisjointIntRectSet& transparency_rects() { return m_transparency_rects; } + Gfx::DisjointIntRectSet& transparency_wallpaper_rects() { return m_transparency_wallpaper_rects; } // The affected transparency rects are the rectangles of other windows (above or below) // that also need to be marked dirty whenever a window's dirty rect in a transparency // area needs to be rendered @@ -401,11 +401,11 @@ private: Gfx::IntRect m_saved_nonfullscreen_rect; Gfx::IntRect m_taskbar_rect; Vector m_screens; - Gfx::DisjointRectSet m_dirty_rects; - Gfx::DisjointRectSet m_opaque_rects; - Gfx::DisjointRectSet m_transparency_rects; - Gfx::DisjointRectSet m_transparency_wallpaper_rects; - HashMap m_affected_transparency_rects; + Gfx::DisjointIntRectSet m_dirty_rects; + Gfx::DisjointIntRectSet m_opaque_rects; + Gfx::DisjointIntRectSet m_transparency_rects; + Gfx::DisjointIntRectSet m_transparency_wallpaper_rects; + HashMap m_affected_transparency_rects; WindowType m_type { WindowType::Normal }; WindowMode m_mode { WindowMode::Modeless }; bool m_automatic_cursor_tracking_enabled { false }; @@ -448,7 +448,7 @@ private: RefPtr m_cursor; RefPtr m_cursor_override; WindowFrame m_frame; - Gfx::DisjointRectSet m_pending_paint_rects; + Gfx::DisjointIntRectSet m_pending_paint_rects; Gfx::IntRect m_rect_in_applet_area; RefPtr m_window_menu; MenuItem* m_window_menu_minimize_item { nullptr }; diff --git a/Userland/Services/WindowServer/WindowFrame.cpp b/Userland/Services/WindowServer/WindowFrame.cpp index 3dc2d3d0e4..1dbb42c5c6 100644 --- a/Userland/Services/WindowServer/WindowFrame.cpp +++ b/Userland/Services/WindowServer/WindowFrame.cpp @@ -595,7 +595,7 @@ Gfx::IntRect WindowFrame::unconstrained_render_rect() const return inflated_for_shadow(rect()); } -Gfx::DisjointRectSet WindowFrame::opaque_render_rects() const +Gfx::DisjointIntRectSet WindowFrame::opaque_render_rects() const { auto border_radius = WindowManager::the().palette().window_border_radius(); if (has_alpha_channel() || border_radius > 0) { @@ -605,17 +605,17 @@ Gfx::DisjointRectSet WindowFrame::opaque_render_rects() const } if (m_window.is_opaque()) return constrained_render_rect_to_screen(rect()); - Gfx::DisjointRectSet opaque_rects; + Gfx::DisjointIntRectSet opaque_rects; opaque_rects.add_many(constrained_render_rect_to_screen(rect()).shatter(m_window.rect())); return opaque_rects; } -Gfx::DisjointRectSet WindowFrame::transparent_render_rects() const +Gfx::DisjointIntRectSet WindowFrame::transparent_render_rects() const { auto border_radius = WindowManager::the().palette().window_border_radius(); if (has_alpha_channel() || border_radius > 0) { if (m_window.is_opaque()) { - Gfx::DisjointRectSet transparent_rects; + Gfx::DisjointIntRectSet transparent_rects; transparent_rects.add_many(render_rect().shatter(m_window.rect())); return transparent_rects; } @@ -623,7 +623,7 @@ Gfx::DisjointRectSet WindowFrame::transparent_render_rects() const } auto total_render_rect = render_rect(); - Gfx::DisjointRectSet transparent_rects; + Gfx::DisjointIntRectSet transparent_rects; if (has_shadow()) transparent_rects.add_many(total_render_rect.shatter(rect())); if (!m_window.is_opaque()) diff --git a/Userland/Services/WindowServer/WindowFrame.h b/Userland/Services/WindowServer/WindowFrame.h index e7611a2d38..2f104f69ec 100644 --- a/Userland/Services/WindowServer/WindowFrame.h +++ b/Userland/Services/WindowServer/WindowFrame.h @@ -56,8 +56,8 @@ public: Gfx::IntRect rect() const; Gfx::IntRect render_rect() const; Gfx::IntRect unconstrained_render_rect() const; - Gfx::DisjointRectSet opaque_render_rects() const; - Gfx::DisjointRectSet transparent_render_rects() const; + Gfx::DisjointIntRectSet opaque_render_rects() const; + Gfx::DisjointIntRectSet transparent_render_rects() const; void paint(Screen&, Gfx::Painter&, Gfx::IntRect const&); void render(Screen&, Gfx::Painter&);