Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 4c72d5c

Browse files
authored
[Impeller] Add rect cutout (#38020)
* [Impeller] Incorporate difference clips in stencil coverage * [Impeller] Add rect cutout
1 parent 025aefc commit 4c72d5c

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

impeller/geometry/geometry_unittests.cc

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,6 +1369,65 @@ TEST(GeometryTest, RectIntersectsWithRect) {
13691369
}
13701370
}
13711371

1372+
TEST(GeometryTest, RectCutout) {
1373+
// No cutout.
1374+
{
1375+
Rect a(0, 0, 100, 100);
1376+
Rect b(0, 0, 50, 50);
1377+
auto u = a.Cutout(b);
1378+
ASSERT_TRUE(u.has_value());
1379+
ASSERT_RECT_NEAR(u.value(), a);
1380+
}
1381+
1382+
// Full cutout.
1383+
{
1384+
Rect a(0, 0, 100, 100);
1385+
Rect b(-10, -10, 120, 120);
1386+
auto u = a.Cutout(b);
1387+
ASSERT_FALSE(u.has_value());
1388+
}
1389+
1390+
// Cutout from top.
1391+
{
1392+
auto a = Rect::MakeLTRB(0, 0, 100, 100);
1393+
auto b = Rect::MakeLTRB(-10, -10, 110, 90);
1394+
auto u = a.Cutout(b);
1395+
auto expected = Rect::MakeLTRB(0, 90, 100, 100);
1396+
ASSERT_TRUE(u.has_value());
1397+
ASSERT_RECT_NEAR(u.value(), expected);
1398+
}
1399+
1400+
// Cutout from bottom.
1401+
{
1402+
auto a = Rect::MakeLTRB(0, 0, 100, 100);
1403+
auto b = Rect::MakeLTRB(-10, 10, 110, 110);
1404+
auto u = a.Cutout(b);
1405+
auto expected = Rect::MakeLTRB(0, 0, 100, 10);
1406+
ASSERT_TRUE(u.has_value());
1407+
ASSERT_RECT_NEAR(u.value(), expected);
1408+
}
1409+
1410+
// Cutout from left.
1411+
{
1412+
auto a = Rect::MakeLTRB(0, 0, 100, 100);
1413+
auto b = Rect::MakeLTRB(-10, -10, 90, 110);
1414+
auto u = a.Cutout(b);
1415+
auto expected = Rect::MakeLTRB(90, 0, 100, 100);
1416+
ASSERT_TRUE(u.has_value());
1417+
ASSERT_RECT_NEAR(u.value(), expected);
1418+
}
1419+
1420+
// Cutout from right.
1421+
{
1422+
auto a = Rect::MakeLTRB(0, 0, 100, 100);
1423+
auto b = Rect::MakeLTRB(10, -10, 110, 110);
1424+
auto u = a.Cutout(b);
1425+
auto expected = Rect::MakeLTRB(0, 0, 10, 100);
1426+
ASSERT_TRUE(u.has_value());
1427+
ASSERT_RECT_NEAR(u.value(), expected);
1428+
}
1429+
}
1430+
13721431
TEST(GeometryTest, RectContainsPoint) {
13731432
{
13741433
// Origin is inclusive

impeller/geometry/rect.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,39 @@ struct TRect {
204204
constexpr bool IntersectsWithRect(const TRect& o) const {
205205
return Intersection(o).has_value();
206206
}
207+
208+
/// @brief Returns the new boundary rectangle that would result from the
209+
/// rectangle being cutout by a second rectangle.
210+
constexpr std::optional<TRect<T>> Cutout(const TRect& o) const {
211+
const auto& [a_left, a_top, a_right, a_bottom] = GetLTRB(); // Source rect.
212+
const auto& [b_left, b_top, b_right, b_bottom] = o.GetLTRB(); // Cutout.
213+
if (b_left <= a_left && b_right >= a_right) {
214+
if (b_top <= a_top && b_bottom >= a_bottom) {
215+
// Full cutout.
216+
return std::nullopt;
217+
}
218+
if (b_top <= a_top) {
219+
// Cuts off the top.
220+
return TRect::MakeLTRB(a_left, b_bottom, a_right, a_bottom);
221+
}
222+
if (b_bottom >= b_bottom) {
223+
// Cuts out the bottom.
224+
return TRect::MakeLTRB(a_left, a_top, a_right, b_top);
225+
}
226+
}
227+
if (b_top <= a_top && b_bottom >= a_bottom) {
228+
if (b_left <= a_left) {
229+
// Cuts out the left.
230+
return TRect::MakeLTRB(b_right, a_top, a_right, a_bottom);
231+
}
232+
if (b_right >= a_right) {
233+
// Cuts out the right.
234+
return TRect::MakeLTRB(a_left, a_top, b_left, a_bottom);
235+
}
236+
}
237+
238+
return *this;
239+
}
207240
};
208241

209242
using Rect = TRect<Scalar>;

0 commit comments

Comments
 (0)