7 const int kRectAllocSize
= 16;
16 Region::Region(const Region
©Region
)
29 Region
& Region::SetTo(const Region
©Region
)
31 AllocSpace(copyRegion
.fNumRects
);
32 fNumRects
= copyRegion
.fNumRects
;
33 memcpy(fRects
, copyRegion
.fRects
, fNumRects
* sizeof(Rect
));
37 Region
& Region::operator=(const Region
©Region
)
39 return SetTo(copyRegion
);
42 Rect
Region::Bounds() const
44 Rect
bounds(COORD_MAX
, COORD_MAX
, -COORD_MAX
, -COORD_MAX
);
45 for (int i
= 0; i
< fNumRects
; i
++) {
46 const Rect
&rect
= RectAt(i
);
47 bounds
.left
= min(bounds
.left
, rect
.left
);
48 bounds
.right
= max(bounds
.right
, rect
.right
);
49 bounds
.top
= min(bounds
.top
, rect
.top
);
50 bounds
.bottom
= max(bounds
.bottom
, rect
.bottom
);
56 Region
& Region::Include(const Rect
&rect
)
61 // Make sure that there are no overlaps
63 for (int i
= 0; i
< fNumRects
; i
++)
64 temp
.Exclude(RectAt(i
));
71 Region
& Region::Include(const Region
®ion
)
74 for (int i
= 0; i
< region
.CountRects(); i
++)
75 Include(region
.RectAt(i
));
81 #define SPLIT_TEST(rect1, rect2) \
82 (max(rect1.left, rect2.left) < min(rect1.right, rect2.right) \
83 && max(rect1.top, rect2.top) < min(rect1.bottom, rect2.bottom))
85 Region
& Region::Exclude(const Rect
&excludeRect
)
89 int rectsToCheck
= fNumRects
;
90 while (index
< rectsToCheck
) {
91 Rect
&clipRect
= fRects
[index
];
93 if (!excludeRect
.Intersects(clipRect
)) {
98 // This clip rect intersects the excluded rect, and could be divided into
99 // as many as eight pieces. Test for each case. Note that none of these
100 // rectangles overlap!!!!
101 Rect
quad1(clipRect
.left
, clipRect
.top
, excludeRect
.left
- 1, excludeRect
.top
- 1);
102 if (SPLIT_TEST(clipRect
, quad1
)) {
103 quad1
.Intersect(clipRect
);
107 Rect
quad2(excludeRect
.left
, clipRect
.top
, excludeRect
.right
, excludeRect
.top
- 1);
108 if (SPLIT_TEST(clipRect
, quad2
)) {
109 quad2
.Intersect(clipRect
);
113 Rect
quad3(excludeRect
.right
+ 1, clipRect
.top
, clipRect
.right
, excludeRect
.top
- 1);
114 if (SPLIT_TEST(clipRect
, quad3
)) {
115 quad3
.Intersect(clipRect
);
119 Rect
quad4(clipRect
.left
, excludeRect
.top
, excludeRect
.left
- 1, excludeRect
.bottom
);
120 if (SPLIT_TEST(clipRect
, quad4
)) {
121 quad4
.Intersect(clipRect
);
125 Rect
quad5(excludeRect
.right
+ 1, excludeRect
.top
, clipRect
.right
, excludeRect
.bottom
);
126 if (SPLIT_TEST(clipRect
, quad5
)) {
127 quad5
.Intersect(clipRect
);
131 Rect
quad6(clipRect
.left
, excludeRect
.bottom
+ 1, excludeRect
.left
- 1, clipRect
.bottom
);
132 if (SPLIT_TEST(clipRect
, quad6
)) {
133 quad6
.Intersect(clipRect
);
137 Rect
quad7(excludeRect
.left
, excludeRect
.bottom
+ 1, excludeRect
.right
, clipRect
.bottom
);
138 if (SPLIT_TEST(clipRect
, quad7
)) {
139 quad7
.Intersect(clipRect
);
143 Rect
quad8(excludeRect
.right
+ 1, excludeRect
.bottom
+ 1, clipRect
.right
, clipRect
.bottom
);
144 if (SPLIT_TEST(clipRect
, quad8
)) {
145 quad8
.Intersect(clipRect
);
149 // This rect has been split, remove it. Note we don't
158 Region
& Region::Exclude(const Region
&ex
)
170 Region
& Region::Clear()
177 Region
& Region::ConstrainTo(const Rect
&rect
)
180 for (int i
= fNumRects
- 1; i
>= 0; i
--) {
181 fRects
[i
].left
= max(rect
.left
, fRects
[i
].left
);
182 fRects
[i
].right
= min(rect
.right
, fRects
[i
].right
);
183 fRects
[i
].top
= max(rect
.top
, fRects
[i
].top
);
184 fRects
[i
].bottom
= min(rect
.bottom
, fRects
[i
].bottom
);
185 if (!fRects
[i
].Valid())
193 Region
& Region::Translate(int x
, int y
)
195 for (int i
= 0; i
< fNumRects
; i
++) {
197 fRects
[i
].right
+= x
;
199 fRects
[i
].bottom
+= y
;
205 Region
& Region::Intersect(const Region
&intersectRegion
)
209 for (int i
= 0; i
< fNumRects
; i
++) {
210 for (int j
= 0; j
< intersectRegion
.fNumRects
; j
++) {
211 if (RectAt(i
).Intersects(intersectRegion
.RectAt(j
))) {
212 Rect
temp(RectAt(i
));
213 temp
.Intersect(intersectRegion
.RectAt(j
));
214 newRegion
.AddRect(temp
);
224 bool Region::Intersects(const Rect
&intersectsRect
) const
226 for (int i
= 0; i
< fNumRects
; i
++) {
227 if(RectAt(i
).Intersects(intersectsRect
))
233 Region
& Region::Invert()
237 temp
.Include(Rect(-COORD_MAX
, -COORD_MAX
, COORD_MAX
, COORD_MAX
));
238 for (int i
= 0; i
< fNumRects
; i
++)
239 temp
.Exclude(fRects
[i
]);
246 const bool Region::FindRect(int x
, int y
, Rect
&outRect
) const
248 for (int i
= 0; i
< CountRects(); i
++) {
249 if (RectAt(i
).Contains(x
, y
)) {
258 void Region::AddRect(const Rect
&rect
)
260 AllocSpace(fNumRects
+ 1);
261 fRects
[fNumRects
++] = rect
;
264 void Region::RemoveRect(int index
)
267 memcpy(fRects
+ index
, fRects
+ index
+ 1, (fNumRects
- index
) * sizeof(Rect
));
268 AllocSpace(fNumRects
);
271 void Region::AddRegionRects(const Region
®ion
)
273 for (int i
= 0; i
< region
.fNumRects
; i
++)
274 AddRect(region
.RectAt(i
));
277 void Region::Consolidate()
279 // Optimize region by consolidating adjacent rectangles.
280 for (int i
= 0; i
< fNumRects
; i
++) {
281 for (int j
= fNumRects
- 1; j
> i
; j
--) {
282 Rect
&rect1
= fRects
[i
];
283 Rect
&rect2
= fRects
[j
];
284 if (rect1
.top
== rect2
.top
&& rect1
.bottom
== rect2
.bottom
) {
285 if (rect1
.right
+ 1 == rect2
.left
) {
286 rect1
.right
= rect2
.right
;
288 } else if (rect2
.right
+ 1 == rect1
.left
) {
289 rect1
.left
= rect2
.left
;
292 } else if (rect1
.left
== rect2
.left
&& rect1
.right
== rect2
.right
) {
293 if (rect1
.top
== rect2
.bottom
+ 1) {
294 rect1
.top
= rect2
.top
;
296 } else if (rect1
.bottom
+ 1 == rect2
.top
) {
297 rect1
.bottom
= rect2
.bottom
;
305 void Region::AllocSpace(int numRects
)
307 int currentAlloc
= ((fNumRects
+ kRectAllocSize
- 1) / kRectAllocSize
)
309 int sizeWanted
= ((numRects
+ kRectAllocSize
- 1) / kRectAllocSize
)
312 if (sizeWanted
!= currentAlloc
) {
313 if (fRects
== 0 && sizeWanted
> 0)
314 fRects
= (Rect
*) malloc(sizeWanted
* sizeof(Rect
));
315 else if (sizeWanted
== 0 && fRects
!= 0) {
319 fRects
= (Rect
*) realloc(fRects
, sizeWanted
* sizeof(Rect
));
324 void Region::BeginOperation()
329 void Region::EndOperation()
334 ASSERT(fOpLevel
>= 0);
339 void Region::Dump() const
342 for (int i
= 0; i
< fNumRects
; i
++) {
345 printf("(%d %d %d %d) ", fRects
[i
].left
, fRects
[i
].top
, fRects
[i
].right
,