|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 |
|
6 #ifndef nsRegion_h__ |
|
7 #define nsRegion_h__ |
|
8 |
|
9 #include <stddef.h> // for size_t |
|
10 #include <stdint.h> // for uint32_t, uint64_t |
|
11 #include <sys/types.h> // for int32_t |
|
12 #include "gfxCore.h" // for NS_GFX |
|
13 #include "nsCoord.h" // for nscoord |
|
14 #include "nsError.h" // for nsresult |
|
15 #include "nsPoint.h" // for nsIntPoint, nsPoint |
|
16 #include "nsRect.h" // for nsIntRect, nsRect |
|
17 #include "nsMargin.h" // for nsIntMargin |
|
18 #include "nsStringGlue.h" // for nsCString |
|
19 #include "xpcom-config.h" // for CPP_THROW_NEW |
|
20 |
|
21 class nsIntRegion; |
|
22 |
|
23 #include "pixman.h" |
|
24 |
|
25 /* For information on the internal representation look at pixman-region.c |
|
26 * |
|
27 * This replaces an older homebrew implementation of nsRegion. The |
|
28 * representation used here may use more rectangles than nsRegion however, the |
|
29 * representation is canonical. This means that there's no need for an |
|
30 * Optimize() method because for a paticular region there is only one |
|
31 * representation. This means that nsIntRegion will have more predictable |
|
32 * performance characteristics than the old nsRegion and should not become |
|
33 * degenerate. |
|
34 * |
|
35 * The pixman region code originates from X11 which has spread to a variety of |
|
36 * projects including Qt, Gtk, Wine. It should perform reasonably well. |
|
37 */ |
|
38 |
|
39 class nsRegionRectIterator; |
|
40 |
|
41 class nsRegion |
|
42 { |
|
43 |
|
44 friend class nsRegionRectIterator; |
|
45 |
|
46 public: |
|
47 nsRegion () { pixman_region32_init(&mImpl); } |
|
48 nsRegion (const nsRect& aRect) { pixman_region32_init_rect(&mImpl, |
|
49 aRect.x, |
|
50 aRect.y, |
|
51 aRect.width, |
|
52 aRect.height); } |
|
53 nsRegion (const nsRegion& aRegion) { pixman_region32_init(&mImpl); pixman_region32_copy(&mImpl,aRegion.Impl()); } |
|
54 ~nsRegion () { pixman_region32_fini(&mImpl); } |
|
55 nsRegion& operator = (const nsRect& aRect) { Copy (aRect); return *this; } |
|
56 nsRegion& operator = (const nsRegion& aRegion) { Copy (aRegion); return *this; } |
|
57 bool operator==(const nsRegion& aRgn) const |
|
58 { |
|
59 return IsEqual(aRgn); |
|
60 } |
|
61 |
|
62 void Swap(nsRegion* aOther) |
|
63 { |
|
64 pixman_region32_t tmp = mImpl; |
|
65 mImpl = aOther->mImpl; |
|
66 aOther->mImpl = tmp; |
|
67 } |
|
68 |
|
69 static |
|
70 nsresult InitStatic() |
|
71 { |
|
72 return NS_OK; |
|
73 } |
|
74 |
|
75 static |
|
76 void ShutdownStatic() {} |
|
77 |
|
78 nsRegion& And(const nsRegion& aRgn1, const nsRegion& aRgn2) |
|
79 { |
|
80 pixman_region32_intersect(&mImpl, aRgn1.Impl(), aRgn2.Impl()); |
|
81 return *this; |
|
82 } |
|
83 nsRegion& And(const nsRect& aRect, const nsRegion& aRegion) |
|
84 { |
|
85 return And(aRegion, aRect); |
|
86 } |
|
87 nsRegion& And(const nsRegion& aRegion, const nsRect& aRect) |
|
88 { |
|
89 pixman_region32_intersect_rect(&mImpl, aRegion.Impl(), aRect.x, aRect.y, aRect.width, aRect.height); |
|
90 return *this; |
|
91 } |
|
92 nsRegion& And(const nsRect& aRect1, const nsRect& aRect2) |
|
93 { |
|
94 nsRect TmpRect; |
|
95 |
|
96 TmpRect.IntersectRect(aRect1, aRect2); |
|
97 return Copy(TmpRect); |
|
98 } |
|
99 |
|
100 nsRegion& Or(const nsRegion& aRgn1, const nsRegion& aRgn2) |
|
101 { |
|
102 pixman_region32_union(&mImpl, aRgn1.Impl(), aRgn2.Impl()); |
|
103 return *this; |
|
104 } |
|
105 nsRegion& Or(const nsRegion& aRegion, const nsRect& aRect) |
|
106 { |
|
107 pixman_region32_union_rect(&mImpl, aRegion.Impl(), aRect.x, aRect.y, aRect.width, aRect.height); |
|
108 return *this; |
|
109 } |
|
110 nsRegion& Or(const nsRect& aRect, const nsRegion& aRegion) |
|
111 { |
|
112 return Or(aRegion, aRect); |
|
113 } |
|
114 nsRegion& Or(const nsRect& aRect1, const nsRect& aRect2) |
|
115 { |
|
116 Copy (aRect1); |
|
117 return Or (*this, aRect2); |
|
118 } |
|
119 |
|
120 nsRegion& Xor(const nsRegion& aRgn1, const nsRegion& aRgn2) |
|
121 { |
|
122 // this could be implemented better if pixman had direct |
|
123 // support for xoring regions. |
|
124 nsRegion p; |
|
125 p.Sub(aRgn1, aRgn2); |
|
126 nsRegion q; |
|
127 q.Sub(aRgn2, aRgn1); |
|
128 return Or(p, q); |
|
129 } |
|
130 nsRegion& Xor(const nsRegion& aRegion, const nsRect& aRect) |
|
131 { |
|
132 return Xor(aRegion, nsRegion(aRect)); |
|
133 } |
|
134 nsRegion& Xor(const nsRect& aRect, const nsRegion& aRegion) |
|
135 { |
|
136 return Xor(nsRegion(aRect), aRegion); |
|
137 } |
|
138 nsRegion& Xor(const nsRect& aRect1, const nsRect& aRect2) |
|
139 { |
|
140 return Xor(nsRegion(aRect1), nsRegion(aRect2)); |
|
141 } |
|
142 |
|
143 nsRegion ToAppUnits (nscoord aAppUnitsPerPixel) const; |
|
144 nsRegion& Sub(const nsRegion& aRgn1, const nsRegion& aRgn2) |
|
145 { |
|
146 pixman_region32_subtract(&mImpl, aRgn1.Impl(), aRgn2.Impl()); |
|
147 return *this; |
|
148 } |
|
149 nsRegion& Sub(const nsRegion& aRegion, const nsRect& aRect) |
|
150 { |
|
151 return Sub(aRegion, nsRegion(aRect)); |
|
152 } |
|
153 nsRegion& Sub(const nsRect& aRect, const nsRegion& aRegion) |
|
154 { |
|
155 return Sub(nsRegion(aRect), aRegion); |
|
156 } |
|
157 nsRegion& Sub(const nsRect& aRect1, const nsRect& aRect2) |
|
158 { |
|
159 Copy(aRect1); |
|
160 return Sub(*this, aRect2); |
|
161 } |
|
162 |
|
163 bool Contains (const nsRect& aRect) const |
|
164 { |
|
165 pixman_box32_t box = RectToBox(aRect); |
|
166 return pixman_region32_contains_rectangle(Impl(), &box) == PIXMAN_REGION_IN; |
|
167 } |
|
168 bool Contains (const nsRegion& aRgn) const; |
|
169 bool Intersects (const nsRect& aRect) const; |
|
170 |
|
171 void MoveBy (int32_t aXOffset, int32_t aYOffset) |
|
172 { |
|
173 MoveBy (nsPoint (aXOffset, aYOffset)); |
|
174 } |
|
175 void MoveBy (nsPoint aPt) { pixman_region32_translate(&mImpl, aPt.x, aPt.y); } |
|
176 void SetEmpty () |
|
177 { |
|
178 pixman_region32_clear(&mImpl); |
|
179 } |
|
180 |
|
181 nsRegion MovedBy(int32_t aXOffset, int32_t aYOffset) const |
|
182 { |
|
183 return MovedBy(nsPoint(aXOffset, aYOffset)); |
|
184 } |
|
185 nsRegion MovedBy(const nsPoint& aPt) const |
|
186 { |
|
187 nsRegion copy(*this); |
|
188 copy.MoveBy(aPt); |
|
189 return copy; |
|
190 } |
|
191 |
|
192 nsRegion Intersect(const nsRegion& aOther) const |
|
193 { |
|
194 nsRegion intersection; |
|
195 intersection.And(*this, aOther); |
|
196 return intersection; |
|
197 } |
|
198 |
|
199 void Inflate(const nsMargin& aMargin); |
|
200 |
|
201 nsRegion Inflated(const nsMargin& aMargin) const |
|
202 { |
|
203 nsRegion copy(*this); |
|
204 copy.Inflate(aMargin); |
|
205 return copy; |
|
206 } |
|
207 |
|
208 bool IsEmpty () const { return !pixman_region32_not_empty(Impl()); } |
|
209 bool IsComplex () const { return GetNumRects() > 1; } |
|
210 bool IsEqual (const nsRegion& aRegion) const |
|
211 { |
|
212 return pixman_region32_equal(Impl(), aRegion.Impl()); |
|
213 } |
|
214 uint32_t GetNumRects () const { return pixman_region32_n_rects(Impl()); } |
|
215 const nsRect GetBounds () const { return BoxToRect(mImpl.extents); } |
|
216 uint64_t Area () const; |
|
217 // Converts this region from aFromAPP, an appunits per pixel ratio, to |
|
218 // aToAPP. This applies nsRect::ConvertAppUnitsRoundOut/In to each rect of |
|
219 // the region. |
|
220 nsRegion ConvertAppUnitsRoundOut (int32_t aFromAPP, int32_t aToAPP) const; |
|
221 nsRegion ConvertAppUnitsRoundIn (int32_t aFromAPP, int32_t aToAPP) const; |
|
222 nsRegion& ScaleRoundOut(float aXScale, float aYScale); |
|
223 nsRegion& ScaleInverseRoundOut(float aXScale, float aYScale); |
|
224 nsIntRegion ScaleToOutsidePixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const; |
|
225 nsIntRegion ScaleToInsidePixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const; |
|
226 nsIntRegion ScaleToNearestPixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const; |
|
227 nsIntRegion ToOutsidePixels (nscoord aAppUnitsPerPixel) const; |
|
228 nsIntRegion ToNearestPixels (nscoord aAppUnitsPerPixel) const; |
|
229 |
|
230 /** |
|
231 * Gets the largest rectangle contained in the region. |
|
232 * @param aContainingRect if non-empty, we choose a rectangle that |
|
233 * maximizes the area intersecting with aContainingRect (and break ties by |
|
234 * then choosing the largest rectangle overall) |
|
235 */ |
|
236 nsRect GetLargestRectangle (const nsRect& aContainingRect = nsRect()) const; |
|
237 |
|
238 /** |
|
239 * Make sure the region has at most aMaxRects by adding area to it |
|
240 * if necessary. The simplified region will be a superset of the |
|
241 * original region. The simplified region's bounding box will be |
|
242 * the same as for the current region. |
|
243 */ |
|
244 void SimplifyOutward (uint32_t aMaxRects); |
|
245 /** |
|
246 * Simplify the region by adding at most aThreshold area between spans of |
|
247 * rects. The simplified region will be a superset of the original region. |
|
248 * The simplified region's bounding box will be the same as for the current |
|
249 * region. |
|
250 */ |
|
251 void SimplifyOutwardByArea(uint32_t aThreshold); |
|
252 /** |
|
253 * Make sure the region has at most aMaxRects by removing area from |
|
254 * it if necessary. The simplified region will be a subset of the |
|
255 * original region. |
|
256 */ |
|
257 void SimplifyInward (uint32_t aMaxRects); |
|
258 |
|
259 nsCString ToString() const; |
|
260 private: |
|
261 pixman_region32_t mImpl; |
|
262 |
|
263 nsIntRegion ToPixels(nscoord aAppUnitsPerPixel, bool aOutsidePixels) const; |
|
264 |
|
265 nsRegion& Copy (const nsRegion& aRegion) |
|
266 { |
|
267 pixman_region32_copy(&mImpl, aRegion.Impl()); |
|
268 return *this; |
|
269 } |
|
270 |
|
271 nsRegion& Copy (const nsRect& aRect) |
|
272 { |
|
273 // pixman needs to distinguish between an empty region and a region |
|
274 // with one rect so that it can return a different number of rectangles. |
|
275 // Empty rect: data = empty_box |
|
276 // 1 rect: data = null |
|
277 // >1 rect: data = rects |
|
278 if (aRect.IsEmpty()) { |
|
279 pixman_region32_clear(&mImpl); |
|
280 } else { |
|
281 pixman_box32_t box = RectToBox(aRect); |
|
282 pixman_region32_reset(&mImpl, &box); |
|
283 } |
|
284 return *this; |
|
285 } |
|
286 |
|
287 static inline pixman_box32_t RectToBox(const nsRect &aRect) |
|
288 { |
|
289 pixman_box32_t box = { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() }; |
|
290 return box; |
|
291 } |
|
292 |
|
293 static inline pixman_box32_t RectToBox(const nsIntRect &aRect) |
|
294 { |
|
295 pixman_box32_t box = { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() }; |
|
296 return box; |
|
297 } |
|
298 |
|
299 |
|
300 static inline nsRect BoxToRect(const pixman_box32_t &aBox) |
|
301 { |
|
302 return nsRect(aBox.x1, aBox.y1, |
|
303 aBox.x2 - aBox.x1, |
|
304 aBox.y2 - aBox.y1); |
|
305 } |
|
306 |
|
307 pixman_region32_t* Impl() const |
|
308 { |
|
309 return const_cast<pixman_region32_t*>(&mImpl); |
|
310 } |
|
311 |
|
312 }; |
|
313 |
|
314 |
|
315 class NS_GFX nsRegionRectIterator |
|
316 { |
|
317 const nsRegion* mRegion; |
|
318 int i; |
|
319 int n; |
|
320 nsRect rect; |
|
321 pixman_box32_t *boxes; |
|
322 |
|
323 public: |
|
324 nsRegionRectIterator (const nsRegion& aRegion) |
|
325 { |
|
326 mRegion = &aRegion; |
|
327 i = 0; |
|
328 boxes = pixman_region32_rectangles(aRegion.Impl(), &n); |
|
329 } |
|
330 |
|
331 const nsRect* Next () |
|
332 { |
|
333 if (i == n) |
|
334 return nullptr; |
|
335 rect = nsRegion::BoxToRect(boxes[i]); |
|
336 i++; |
|
337 return ▭ |
|
338 } |
|
339 |
|
340 const nsRect* Prev () |
|
341 { |
|
342 if (i == -1) |
|
343 return nullptr; |
|
344 rect = nsRegion::BoxToRect(boxes[i]); |
|
345 i--; |
|
346 return ▭ |
|
347 } |
|
348 |
|
349 void Reset () |
|
350 { |
|
351 i = 0; |
|
352 } |
|
353 }; |
|
354 |
|
355 /** |
|
356 * nsIntRegions use int32_t coordinates and nsIntRects. |
|
357 */ |
|
358 class NS_GFX nsIntRegion |
|
359 { |
|
360 friend class nsIntRegionRectIterator; |
|
361 friend class nsRegion; |
|
362 |
|
363 public: |
|
364 nsIntRegion () {} |
|
365 nsIntRegion (const nsIntRect& aRect) : mImpl (ToRect(aRect)) {} |
|
366 nsIntRegion (const nsIntRegion& aRegion) : mImpl (aRegion.mImpl) {} |
|
367 nsIntRegion& operator = (const nsIntRect& aRect) { mImpl = ToRect (aRect); return *this; } |
|
368 nsIntRegion& operator = (const nsIntRegion& aRegion) { mImpl = aRegion.mImpl; return *this; } |
|
369 |
|
370 bool operator==(const nsIntRegion& aRgn) const |
|
371 { |
|
372 return IsEqual(aRgn); |
|
373 } |
|
374 |
|
375 void Swap(nsIntRegion* aOther) |
|
376 { |
|
377 mImpl.Swap(&aOther->mImpl); |
|
378 } |
|
379 |
|
380 nsIntRegion& And (const nsIntRegion& aRgn1, const nsIntRegion& aRgn2) |
|
381 { |
|
382 mImpl.And (aRgn1.mImpl, aRgn2.mImpl); |
|
383 return *this; |
|
384 } |
|
385 nsIntRegion& And (const nsIntRegion& aRegion, const nsIntRect& aRect) |
|
386 { |
|
387 mImpl.And (aRegion.mImpl, ToRect (aRect)); |
|
388 return *this; |
|
389 } |
|
390 nsIntRegion& And (const nsIntRect& aRect, const nsIntRegion& aRegion) |
|
391 { |
|
392 return And (aRegion, aRect); |
|
393 } |
|
394 nsIntRegion& And (const nsIntRect& aRect1, const nsIntRect& aRect2) |
|
395 { |
|
396 nsIntRect TmpRect; |
|
397 |
|
398 TmpRect.IntersectRect (aRect1, aRect2); |
|
399 mImpl = ToRect (TmpRect); |
|
400 return *this; |
|
401 } |
|
402 |
|
403 nsIntRegion& Or (const nsIntRegion& aRgn1, const nsIntRegion& aRgn2) |
|
404 { |
|
405 mImpl.Or (aRgn1.mImpl, aRgn2.mImpl); |
|
406 return *this; |
|
407 } |
|
408 nsIntRegion& Or (const nsIntRegion& aRegion, const nsIntRect& aRect) |
|
409 { |
|
410 mImpl.Or (aRegion.mImpl, ToRect (aRect)); |
|
411 return *this; |
|
412 } |
|
413 nsIntRegion& Or (const nsIntRect& aRect, const nsIntRegion& aRegion) |
|
414 { |
|
415 return Or (aRegion, aRect); |
|
416 } |
|
417 nsIntRegion& Or (const nsIntRect& aRect1, const nsIntRect& aRect2) |
|
418 { |
|
419 mImpl = ToRect (aRect1); |
|
420 return Or (*this, aRect2); |
|
421 } |
|
422 |
|
423 nsIntRegion& Xor (const nsIntRegion& aRgn1, const nsIntRegion& aRgn2) |
|
424 { |
|
425 mImpl.Xor (aRgn1.mImpl, aRgn2.mImpl); |
|
426 return *this; |
|
427 } |
|
428 nsIntRegion& Xor (const nsIntRegion& aRegion, const nsIntRect& aRect) |
|
429 { |
|
430 mImpl.Xor (aRegion.mImpl, ToRect (aRect)); |
|
431 return *this; |
|
432 } |
|
433 nsIntRegion& Xor (const nsIntRect& aRect, const nsIntRegion& aRegion) |
|
434 { |
|
435 return Xor (aRegion, aRect); |
|
436 } |
|
437 nsIntRegion& Xor (const nsIntRect& aRect1, const nsIntRect& aRect2) |
|
438 { |
|
439 mImpl = ToRect (aRect1); |
|
440 return Xor (*this, aRect2); |
|
441 } |
|
442 |
|
443 nsIntRegion& Sub (const nsIntRegion& aRgn1, const nsIntRegion& aRgn2) |
|
444 { |
|
445 mImpl.Sub (aRgn1.mImpl, aRgn2.mImpl); |
|
446 return *this; |
|
447 } |
|
448 nsIntRegion& Sub (const nsIntRegion& aRegion, const nsIntRect& aRect) |
|
449 { |
|
450 mImpl.Sub (aRegion.mImpl, ToRect (aRect)); |
|
451 return *this; |
|
452 } |
|
453 nsIntRegion& Sub (const nsIntRect& aRect, const nsIntRegion& aRegion) |
|
454 { |
|
455 return Sub (nsIntRegion (aRect), aRegion); |
|
456 } |
|
457 nsIntRegion& Sub (const nsIntRect& aRect1, const nsIntRect& aRect2) |
|
458 { |
|
459 mImpl = ToRect (aRect1); |
|
460 return Sub (*this, aRect2); |
|
461 } |
|
462 |
|
463 bool Contains (const nsIntRect& aRect) const |
|
464 { |
|
465 return mImpl.Contains (ToRect (aRect)); |
|
466 } |
|
467 bool Contains (const nsIntRegion& aRgn) const |
|
468 { |
|
469 return mImpl.Contains (aRgn.mImpl); |
|
470 } |
|
471 bool Intersects (const nsIntRect& aRect) const |
|
472 { |
|
473 return mImpl.Intersects (ToRect (aRect)); |
|
474 } |
|
475 |
|
476 void MoveBy (int32_t aXOffset, int32_t aYOffset) |
|
477 { |
|
478 MoveBy (nsIntPoint (aXOffset, aYOffset)); |
|
479 } |
|
480 void MoveBy (nsIntPoint aPt) |
|
481 { |
|
482 mImpl.MoveBy (aPt.x, aPt.y); |
|
483 } |
|
484 nsIntRegion MovedBy(int32_t aXOffset, int32_t aYOffset) const |
|
485 { |
|
486 return MovedBy(nsIntPoint(aXOffset, aYOffset)); |
|
487 } |
|
488 nsIntRegion MovedBy(const nsIntPoint& aPt) const |
|
489 { |
|
490 nsIntRegion copy(*this); |
|
491 copy.MoveBy(aPt); |
|
492 return copy; |
|
493 } |
|
494 |
|
495 nsIntRegion Intersect(const nsIntRegion& aOther) const |
|
496 { |
|
497 nsIntRegion intersection; |
|
498 intersection.And(*this, aOther); |
|
499 return intersection; |
|
500 } |
|
501 |
|
502 void Inflate(const nsIntMargin& aMargin) |
|
503 { |
|
504 mImpl.Inflate(nsMargin(aMargin.top, aMargin.right, aMargin.bottom, aMargin.left)); |
|
505 } |
|
506 nsIntRegion Inflated(const nsIntMargin& aMargin) const |
|
507 { |
|
508 nsIntRegion copy(*this); |
|
509 copy.Inflate(aMargin); |
|
510 return copy; |
|
511 } |
|
512 |
|
513 void SetEmpty () |
|
514 { |
|
515 mImpl.SetEmpty (); |
|
516 } |
|
517 |
|
518 bool IsEmpty () const { return mImpl.IsEmpty (); } |
|
519 bool IsComplex () const { return mImpl.IsComplex (); } |
|
520 bool IsEqual (const nsIntRegion& aRegion) const |
|
521 { |
|
522 return mImpl.IsEqual (aRegion.mImpl); |
|
523 } |
|
524 uint32_t GetNumRects () const { return mImpl.GetNumRects (); } |
|
525 nsIntRect GetBounds () const { return FromRect (mImpl.GetBounds ()); } |
|
526 uint64_t Area () const { return mImpl.Area(); } |
|
527 nsRegion ToAppUnits (nscoord aAppUnitsPerPixel) const; |
|
528 nsIntRect GetLargestRectangle (const nsIntRect& aContainingRect = nsIntRect()) const |
|
529 { |
|
530 return FromRect (mImpl.GetLargestRectangle( ToRect(aContainingRect) )); |
|
531 } |
|
532 |
|
533 nsIntRegion& ScaleRoundOut (float aXScale, float aYScale) |
|
534 { |
|
535 mImpl.ScaleRoundOut(aXScale, aYScale); |
|
536 return *this; |
|
537 } |
|
538 |
|
539 /** |
|
540 * Make sure the region has at most aMaxRects by adding area to it |
|
541 * if necessary. The simplified region will be a superset of the |
|
542 * original region. The simplified region's bounding box will be |
|
543 * the same as for the current region. |
|
544 */ |
|
545 void SimplifyOutward (uint32_t aMaxRects) |
|
546 { |
|
547 mImpl.SimplifyOutward (aMaxRects); |
|
548 } |
|
549 void SimplifyOutwardByArea (uint32_t aThreshold) |
|
550 { |
|
551 mImpl.SimplifyOutwardByArea (aThreshold); |
|
552 } |
|
553 /** |
|
554 * Make sure the region has at most aMaxRects by removing area from |
|
555 * it if necessary. The simplified region will be a subset of the |
|
556 * original region. |
|
557 */ |
|
558 void SimplifyInward (uint32_t aMaxRects) |
|
559 { |
|
560 mImpl.SimplifyInward (aMaxRects); |
|
561 } |
|
562 |
|
563 nsCString ToString() const { return mImpl.ToString(); } |
|
564 |
|
565 private: |
|
566 nsRegion mImpl; |
|
567 |
|
568 static nsRect ToRect(const nsIntRect& aRect) |
|
569 { |
|
570 return nsRect (aRect.x, aRect.y, aRect.width, aRect.height); |
|
571 } |
|
572 static nsIntRect FromRect(const nsRect& aRect) |
|
573 { |
|
574 return nsIntRect (aRect.x, aRect.y, aRect.width, aRect.height); |
|
575 } |
|
576 }; |
|
577 |
|
578 class NS_GFX nsIntRegionRectIterator |
|
579 { |
|
580 nsRegionRectIterator mImpl; |
|
581 nsIntRect mTmp; |
|
582 |
|
583 public: |
|
584 nsIntRegionRectIterator (const nsIntRegion& aRegion) : mImpl (aRegion.mImpl) {} |
|
585 |
|
586 const nsIntRect* Next () |
|
587 { |
|
588 const nsRect* r = mImpl.Next(); |
|
589 if (!r) |
|
590 return nullptr; |
|
591 mTmp = nsIntRegion::FromRect (*r); |
|
592 return &mTmp; |
|
593 } |
|
594 |
|
595 const nsIntRect* Prev () |
|
596 { |
|
597 const nsRect* r = mImpl.Prev(); |
|
598 if (!r) |
|
599 return nullptr; |
|
600 mTmp = nsIntRegion::FromRect (*r); |
|
601 return &mTmp; |
|
602 } |
|
603 |
|
604 void Reset () |
|
605 { |
|
606 mImpl.Reset (); |
|
607 } |
|
608 }; |
|
609 #endif |