diff --git a/Libraries/LibGfx/Rect.h b/Libraries/LibGfx/Rect.h index 2bd79477fb1..fcf8c331510 100644 --- a/Libraries/LibGfx/Rect.h +++ b/Libraries/LibGfx/Rect.h @@ -835,6 +835,18 @@ public: return { { point.x() - size.width() / 2, point.y() - size.height() / 2 }, size }; } + void unite(Rect const& other) + { + if (is_empty()) { + *this = other; + return; + } + if (other.is_empty()) + return; + unite_horizontally(other); + unite_vertically(other); + } + void unite_horizontally(Rect const& other) { auto new_left = min(left(), other.left()); @@ -853,15 +865,8 @@ public: [[nodiscard]] Rect united(Rect const& other) const { - if (is_empty()) - return other; - if (other.is_empty()) - return *this; - Rect rect; - rect.set_left(min(left(), other.left())); - rect.set_top(min(top(), other.top())); - rect.set_right(max(right(), other.right())); - rect.set_bottom(max(bottom(), other.bottom())); + Rect rect = *this; + rect.unite(other); return rect; } diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index b4897b1f8bc..15f96b626fb 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -927,7 +927,7 @@ GC::Ref Element::get_bounding_client_rect() const auto const& rect = list->item(i); if (rect->width() == 0 || rect->height() == 0) continue; - bounding_rect = bounding_rect.united({ rect->x(), rect->y(), rect->width(), rect->height() }); + bounding_rect.unite({ rect->x(), rect->y(), rect->width(), rect->height() }); } return Geometry::DOMRect::create(realm(), bounding_rect.to_type()); } diff --git a/Libraries/LibWeb/DOM/Range.cpp b/Libraries/LibWeb/DOM/Range.cpp index 0a0f24b3ea0..4050e3bea7b 100644 --- a/Libraries/LibWeb/DOM/Range.cpp +++ b/Libraries/LibWeb/DOM/Range.cpp @@ -1243,7 +1243,7 @@ GC::Ref Range::get_bounding_client_rect() auto const& rect = list->item(i); if (rect->width() == 0 || rect->height() == 0) continue; - bounding_rect = bounding_rect.united({ rect->x(), rect->y(), rect->width(), rect->height() }); + bounding_rect.unite({ rect->x(), rect->y(), rect->width(), rect->height() }); } return Geometry::DOMRect::create(realm(), bounding_rect.to_type()); } diff --git a/Libraries/LibWeb/Layout/LayoutState.cpp b/Libraries/LibWeb/Layout/LayoutState.cpp index 6662b0e7cbd..38fac64ef28 100644 --- a/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Libraries/LibWeb/Layout/LayoutState.cpp @@ -89,9 +89,8 @@ static CSSPixelRect measure_scrollable_overflow(Box const& box) // - All line boxes directly contained by the scroll container. if (is(box.first_paintable())) { - for (auto const& fragment : static_cast(*box.first_paintable()).fragments()) { - scrollable_overflow_rect = scrollable_overflow_rect.united(fragment.absolute_rect()); - } + for (auto const& fragment : static_cast(*box.first_paintable()).fragments()) + scrollable_overflow_rect.unite(fragment.absolute_rect()); } auto content_overflow_rect = scrollable_overflow_rect; @@ -117,8 +116,8 @@ static CSSPixelRect measure_scrollable_overflow(Box const& box) if (child_border_box.bottom() < 0 || child_border_box.right() < 0) return TraversalDecision::Continue; - scrollable_overflow_rect = scrollable_overflow_rect.united(child_border_box); - content_overflow_rect = content_overflow_rect.united(child_border_box); + scrollable_overflow_rect.unite(child_border_box); + content_overflow_rect.unite(child_border_box); // - The scrollable overflow areas of all of the above boxes // (including zero-area boxes and accounting for transforms as described above), diff --git a/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Libraries/LibWeb/Painting/BackgroundPainting.cpp index 8a8c456afc5..95d660b56d4 100644 --- a/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -271,15 +271,11 @@ void paint_background(PaintContext& context, PaintableBox const& paintable_box, // However, we must first figure out the real coverage area, taking repeat etc into account. // FIXME: This could be written in a far more efficient way. - auto fill_rect = Optional {}; + DevicePixelRect fill_rect; for_each_image_device_rect([&](auto const& image_device_rect) { - if (!fill_rect.has_value()) { - fill_rect = image_device_rect; - } else { - fill_rect = fill_rect->united(image_device_rect); - } + fill_rect.unite(image_device_rect); }); - display_list_recorder.fill_rect(fill_rect->to_type(), color.value()); + display_list_recorder.fill_rect(fill_rect.to_type(), color.value()); } else if (is(image) && repeat_x && repeat_y && !repeat_x_has_gap && !repeat_y_has_gap) { // Use a dedicated painting command for repeated images instead of recording a separate command for each instance // of a repeated background, so the painter has the opportunity to optimize the painting of repeated images. diff --git a/Libraries/LibWeb/Painting/PaintableBox.cpp b/Libraries/LibWeb/Painting/PaintableBox.cpp index 6e4d6dbd0c8..f8b902a0506 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -209,7 +209,7 @@ CSSPixelRect PaintableBox::compute_absolute_paint_rect() const continue; auto inflate = shadow.spread_distance + shadow.blur_radius; auto shadow_rect = rect.inflated(inflate, inflate, inflate, inflate).translated(shadow.offset_x, shadow.offset_y); - rect = rect.united(shadow_rect); + rect.unite(shadow_rect); } return rect; } diff --git a/Tests/LibGfx/TestRect.cpp b/Tests/LibGfx/TestRect.cpp index f7625cb1111..123725bdceb 100644 --- a/Tests/LibGfx/TestRect.cpp +++ b/Tests/LibGfx/TestRect.cpp @@ -57,28 +57,41 @@ TEST_CASE(rect_closest_to) EXPECT_EQ(screen_rect.side(closest), Gfx::IntRect::Side::Top); } +TEST_CASE(rect_unite) +{ + Gfx::IntRect rect_a { 10, 10, 100, 100 }; + Gfx::IntRect rect_b { 50, 50, 60, 70 }; + + rect_a.unite(rect_b); + + EXPECT_EQ(rect_a.left(), 10); + EXPECT_EQ(rect_a.right(), 110); + EXPECT_EQ(rect_a.top(), 10); + EXPECT_EQ(rect_a.bottom(), 120); +} + TEST_CASE(rect_unite_horizontally) { - Gfx::IntRect rect { 10, 10, 100, 100 }; - Gfx::IntRect huge_rect { 0, 0, 1000, 1000 }; + Gfx::IntRect rect_a { 10, 10, 1000, 100 }; + Gfx::IntRect rect_b { 0, 0, 100, 1000 }; - rect.unite_horizontally(huge_rect); + rect_a.unite_horizontally(rect_b); - EXPECT_EQ(rect.left(), 0); - EXPECT_EQ(rect.right(), 1000); - EXPECT_EQ(rect.top(), 10); - EXPECT_EQ(rect.bottom(), 110); + EXPECT_EQ(rect_a.left(), 0); + EXPECT_EQ(rect_a.right(), 1010); + EXPECT_EQ(rect_a.top(), 10); + EXPECT_EQ(rect_a.bottom(), 110); } TEST_CASE(rect_unite_vertically) { - Gfx::IntRect rect { 10, 10, 100, 100 }; - Gfx::IntRect huge_rect { 0, 0, 1000, 1000 }; + Gfx::IntRect rect_a { 10, 10, 1000, 1000 }; + Gfx::IntRect rect_b { 0, 0, 100, 100 }; - rect.unite_vertically(huge_rect); + rect_a.unite_vertically(rect_b); - EXPECT_EQ(rect.top(), 0); - EXPECT_EQ(rect.bottom(), 1000); - EXPECT_EQ(rect.left(), 10); - EXPECT_EQ(rect.right(), 110); + EXPECT_EQ(rect_a.top(), 0); + EXPECT_EQ(rect_a.bottom(), 1010); + EXPECT_EQ(rect_a.left(), 10); + EXPECT_EQ(rect_a.right(), 1010); }