Skip to content

Commit

Permalink
LibGfx+Everywhere: Make DisjointRectSet work for non-int Rects
Browse files Browse the repository at this point in the history
For convenience, `DisjointIntRectSet` is an alias for
`DisjointRectSet<int>`, and is used everywhere for now.
  • Loading branch information
AtkinsSJ authored and awesomekling committed Oct 27, 2022
1 parent f52413a commit ff0a2b1
Show file tree
Hide file tree
Showing 13 changed files with 67 additions and 59 deletions.
2 changes: 1 addition & 1 deletion Userland/Applications/PixelPaint/ImageEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
34 changes: 18 additions & 16 deletions Userland/Libraries/LibGfx/DisjointRectSet.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <[email protected]>
* Copyright (c) 2022, Sam Atkins <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
Expand All @@ -12,6 +13,7 @@

namespace Gfx {

template<typename T>
class DisjointRectSet {
public:
DisjointRectSet(DisjointRectSet const&) = delete;
Expand All @@ -20,7 +22,7 @@ class DisjointRectSet {
DisjointRectSet() = default;
~DisjointRectSet() = default;

DisjointRectSet(IntRect const& rect)
DisjointRectSet(Rect<T> const& rect)
{
m_rects.append(rect);
}
Expand All @@ -35,17 +37,17 @@ class DisjointRectSet {
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<T> const& delta)
{
move_by(delta.x(), delta.y());
}

void add(IntRect const& rect)
void add(Rect<T> const& rect)
{
if (add_no_shatter(rect) && m_rects.size() > 1)
shatter();
Expand Down Expand Up @@ -74,7 +76,7 @@ class DisjointRectSet {
}
}

DisjointRectSet shatter(IntRect const& hammer) const
DisjointRectSet shatter(Rect<T> const& hammer) const
{
if (hammer.is_empty())
return clone();
Expand Down Expand Up @@ -107,7 +109,7 @@ class DisjointRectSet {
return shards;
}

bool contains(IntRect const& rect) const
bool contains(Rect<T> const& rect) const
{
if (is_empty() || rect.is_empty())
return false;
Expand All @@ -123,7 +125,7 @@ class DisjointRectSet {
return false;
}

bool intersects(IntRect const& rect) const
bool intersects(Rect<T> const& rect) const
{
for (auto& r : m_rects) {
if (r.intersects(rect))
Expand All @@ -145,7 +147,7 @@ class DisjointRectSet {
return false;
}

DisjointRectSet intersected(IntRect const& rect) const
DisjointRectSet intersected(Rect<T> const& rect) const
{
DisjointRectSet intersected_rects;
intersected_rects.m_rects.ensure_capacity(m_rects.capacity());
Expand Down Expand Up @@ -178,7 +180,7 @@ class DisjointRectSet {
}

template<typename Function>
IterationDecision for_each_intersected(IntRect const& rect, Function f) const
IterationDecision for_each_intersected(Rect<T> const& rect, Function f) const
{
if (is_empty() || rect.is_empty())
return IterationDecision::Continue;
Expand Down Expand Up @@ -224,22 +226,22 @@ class DisjointRectSet {

void clear() { m_rects.clear(); }
void clear_with_capacity() { m_rects.clear_with_capacity(); }
Vector<IntRect, 32> const& rects() const { return m_rects; }
Vector<IntRect, 32> take_rects() { return move(m_rects); }
Vector<Rect<T>, 32> const& rects() const { return m_rects; }
Vector<Rect<T>, 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<T> 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<T> const& new_rect)
{
if (new_rect.is_empty())
return false;
Expand All @@ -254,7 +256,7 @@ class DisjointRectSet {

void shatter()
{
Vector<IntRect, 32> output;
Vector<Rect<T>, 32> output;
output.ensure_capacity(m_rects.size());
bool pass_had_intersections = false;
do {
Expand Down Expand Up @@ -284,7 +286,7 @@ class DisjointRectSet {
} while (pass_had_intersections);
}

Vector<IntRect, 32> m_rects;
Vector<Rect<T>, 32> m_rects;
};

}
6 changes: 6 additions & 0 deletions Userland/Libraries/LibGfx/Forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ namespace Gfx {
class Bitmap;
class CharacterBitmap;
class Color;

template<typename T>
class DisjointRectSet;

class Emoji;
class Font;
class GlyphBitmap;
Expand Down Expand Up @@ -44,6 +47,9 @@ class Rect;
template<typename T>
class Quad;

using DisjointIntRectSet = DisjointRectSet<int>;
using DisjointFloatRectSet = DisjointRectSet<float>;

using IntLine = Line<int>;
using FloatLine = Line<float>;

Expand Down
2 changes: 1 addition & 1 deletion Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
2 changes: 1 addition & 1 deletion Userland/Services/WindowServer/Animation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void Animation::was_removed(Badge<Compositor>)
m_was_removed = true;
}

bool Animation::update(Badge<Compositor>, Gfx::Painter& painter, Screen& screen, Gfx::DisjointRectSet& flush_rects)
bool Animation::update(Badge<Compositor>, 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);
Expand Down
4 changes: 2 additions & 2 deletions Userland/Services/WindowServer/Animation.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ class Animation : public RefCounted<Animation> {
void set_duration(int duration_in_ms);
int duration() const { return m_duration; }

bool update(Badge<Compositor>, Gfx::Painter&, Screen&, Gfx::DisjointRectSet& flush_rects);
bool update(Badge<Compositor>, Gfx::Painter&, Screen&, Gfx::DisjointIntRectSet& flush_rects);

Function<void(float progress, Gfx::Painter&, Screen&, Gfx::DisjointRectSet& flush_rects)> on_update;
Function<void(float progress, Gfx::Painter&, Screen&, Gfx::DisjointIntRectSet& flush_rects)> on_update;
Function<void()> on_stop;

private:
Expand Down
14 changes: 7 additions & 7 deletions Userland/Services/WindowServer/Compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()));

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1517,7 +1517,7 @@ void Compositor::unregister_animation(Badge<Animation>, 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
Expand Down Expand Up @@ -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);

Expand Down
20 changes: 10 additions & 10 deletions Userland/Services/WindowServer/Compositor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand All @@ -68,7 +68,7 @@ struct CompositorScreenData {
template<typename F>
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())
Expand Down Expand Up @@ -101,7 +101,7 @@ class Compositor final : public Core::Object {
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();

Expand Down Expand Up @@ -209,7 +209,7 @@ class Compositor final : public Core::Object {
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();
Expand All @@ -227,10 +227,10 @@ class Compositor final : public Core::Object {
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<Gfx::Bitmap> m_wallpaper;
Expand Down
2 changes: 1 addition & 1 deletion Userland/Services/WindowServer/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions Userland/Services/WindowServer/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down
22 changes: 11 additions & 11 deletions Userland/Services/WindowServer/Window.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ class Window final : public Core::Object {

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; }
Expand Down Expand Up @@ -290,7 +290,7 @@ class Window final : public Core::Object {
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();

Expand Down Expand Up @@ -335,9 +335,9 @@ class Window final : public Core::Object {
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
Expand Down Expand Up @@ -401,11 +401,11 @@ class Window final : public Core::Object {
Gfx::IntRect m_saved_nonfullscreen_rect;
Gfx::IntRect m_taskbar_rect;
Vector<Screen*, default_screen_count> m_screens;
Gfx::DisjointRectSet m_dirty_rects;
Gfx::DisjointRectSet m_opaque_rects;
Gfx::DisjointRectSet m_transparency_rects;
Gfx::DisjointRectSet m_transparency_wallpaper_rects;
HashMap<Window*, Gfx::DisjointRectSet> 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<Window*, Gfx::DisjointIntRectSet> m_affected_transparency_rects;
WindowType m_type { WindowType::Normal };
WindowMode m_mode { WindowMode::Modeless };
bool m_automatic_cursor_tracking_enabled { false };
Expand Down Expand Up @@ -448,7 +448,7 @@ class Window final : public Core::Object {
RefPtr<Cursor> m_cursor;
RefPtr<Cursor> 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<Menu> m_window_menu;
MenuItem* m_window_menu_minimize_item { nullptr };
Expand Down
Loading

0 comments on commit ff0a2b1

Please sign in to comment.