• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * These tests are taken from
17  * https://cs.android.com/android/platform/superproject/+/master:cts/tests/tests/graphics/src/android/graphics/cts/RegionTest.java
18  */
19 
20 package org.robolectric.integrationtests.nativegraphics;
21 
22 import static android.os.Build.VERSION_CODES.O;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNotSame;
26 import static org.junit.Assert.assertThrows;
27 import static org.junit.Assert.assertTrue;
28 
29 import android.graphics.Path;
30 import android.graphics.Rect;
31 import android.graphics.Region;
32 import androidx.test.ext.junit.runners.AndroidJUnit4;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 import org.robolectric.annotation.Config;
37 
38 @RunWith(AndroidJUnit4.class)
39 @Config(minSdk = O)
40 public class ShadowNativeRegionTest {
41   // DIFFERENCE
42   private static final int[][] DIFFERENCE_WITH1 = {
43     {0, 0}, {4, 4}, {10, 10}, {19, 19}, {19, 0}, {10, 4}, {4, 10}, {0, 19}
44   };
45   private static final int[][] DIFFERENCE_WITHOUT1 = {{5, 5}, {9, 9}, {9, 5}, {5, 9}};
46 
47   private static final int[][] DIFFERENCE_WITH2 = {
48     {0, 0}, {19, 0}, {9, 9}, {19, 9}, {0, 19}, {9, 19}
49   };
50   private static final int[][] DIFFERENCE_WITHOUT2 = {
51     {10, 10}, {19, 10}, {10, 19}, {19, 19}, {29, 10}, {29, 29}, {10, 29}
52   };
53 
54   private static final int[][] DIFFERENCE_WITH3 = {{0, 0}, {19, 0}, {0, 19}, {19, 19}};
55   private static final int[][] DIFFERENCE_WITHOUT3 = {{40, 40}, {40, 59}, {59, 40}, {59, 59}};
56 
57   // INTERSECT
58   private static final int[][] INTERSECT_WITH1 = {{5, 5}, {9, 9}, {9, 5}, {5, 9}};
59   private static final int[][] INTERSECT_WITHOUT1 = {
60     {0, 0}, {2, 2}, {4, 4}, {10, 10}, {19, 19}, {19, 0}, {10, 4}, {4, 10}, {0, 19}
61   };
62 
63   private static final int[][] INTERSECT_WITH2 = {{10, 10}, {19, 10}, {10, 19}, {19, 19}};
64   private static final int[][] INTERSECT_WITHOUT2 = {
65     {0, 0}, {19, 0}, {9, 9}, {19, 9}, {0, 19}, {9, 19}, {29, 10}, {29, 29}, {10, 29}
66   };
67 
68   // UNION
69   private static final int[][] UNION_WITH1 = {
70     {0, 0}, {2, 2}, {4, 4}, {6, 6}, {10, 10}, {19, 19}, {19, 0}, {10, 4}, {4, 10}, {0, 19}, {5, 5},
71     {9, 9}, {9, 5}, {5, 9}
72   };
73   private static final int[][] UNION_WITHOUT1 = {{0, 20}, {20, 20}, {20, 0}};
74 
75   private static final int[][] UNION_WITH2 = {
76     {0, 0}, {2, 2}, {19, 0}, {9, 9}, {19, 9}, {0, 19}, {9, 19}, {21, 21}, {10, 10}, {19, 10},
77     {10, 19}, {19, 19}, {29, 10}, {29, 29}, {10, 29}
78   };
79   private static final int[][] UNION_WITHOUT2 = {
80     {0, 29}, {0, 20}, {9, 29}, {9, 20},
81     {29, 0}, {20, 0}, {29, 9}, {20, 9}
82   };
83 
84   private static final int[][] UNION_WITH3 = {
85     {0, 0}, {2, 2}, {19, 0}, {0, 19}, {19, 19},
86     {40, 40}, {41, 41}, {40, 59}, {59, 40}, {59, 59}
87   };
88   private static final int[][] UNION_WITHOUT3 = {{20, 20}, {39, 39}};
89 
90   // XOR
91   private static final int[][] XOR_WITH1 = {
92     {0, 0}, {2, 2}, {4, 4}, {10, 10}, {19, 19}, {19, 0}, {10, 4}, {4, 10}, {0, 19}
93   };
94   private static final int[][] XOR_WITHOUT1 = {{5, 5}, {6, 6}, {9, 9}, {9, 5}, {5, 9}};
95 
96   private static final int[][] XOR_WITH2 = {
97     {0, 0}, {2, 2}, {19, 0}, {9, 9}, {19, 9}, {0, 19}, {9, 19}, {21, 21}, {29, 10}, {10, 29},
98     {20, 10}, {10, 20}, {20, 20}, {29, 29}
99   };
100   private static final int[][] XOR_WITHOUT2 = {{10, 10}, {11, 11}, {19, 10}, {10, 19}, {19, 19}};
101 
102   private static final int[][] XOR_WITH3 = {
103     {0, 0}, {2, 2}, {19, 0}, {0, 19}, {19, 19},
104     {40, 40}, {41, 41}, {40, 59}, {59, 40}, {59, 59}
105   };
106   private static final int[][] XOR_WITHOUT3 = {{20, 20}, {39, 39}};
107 
108   // REVERSE_DIFFERENCE
109   private static final int[][] REVERSE_DIFFERENCE_WITH2 = {
110     {29, 10}, {10, 29}, {20, 10}, {10, 20}, {20, 20}, {29, 29}, {21, 21}
111   };
112   private static final int[][] REVERSE_DIFFERENCE_WITHOUT2 = {
113     {0, 0}, {19, 0}, {0, 19}, {19, 19}, {2, 2}, {11, 11}
114   };
115 
116   private static final int[][] REVERSE_DIFFERENCE_WITH3 = {
117     {40, 40}, {40, 59}, {59, 40}, {59, 59}, {41, 41}
118   };
119   private static final int[][] REVERSE_DIFFERENCE_WITHOUT3 = {
120     {0, 0}, {19, 0}, {0, 19}, {19, 19}, {20, 20}, {39, 39}, {2, 2}
121   };
122 
123   private Region region;
124 
verifyPointsInsideRegion(int[][] area)125   private void verifyPointsInsideRegion(int[][] area) {
126     for (int i = 0; i < area.length; i++) {
127       assertTrue(region.contains(area[i][0], area[i][1]));
128     }
129   }
130 
verifyPointsOutsideRegion(int[][] area)131   private void verifyPointsOutsideRegion(int[][] area) {
132     for (int i = 0; i < area.length; i++) {
133       assertFalse(region.contains(area[i][0], area[i][1]));
134     }
135   }
136 
137   @Before
setup()138   public void setup() {
139     region = new Region();
140   }
141 
142   @Test
testConstructor()143   public void testConstructor() {
144     // We don't actually care about the result of quickContains in this function (tested later).
145     // We call it because in robolectric native runtime, it's not static and so if the constructor
146     // is set up incorrectly, it will crash trying to get the instance from mNativeRegion.
147     Rect rect = new Rect();
148 
149     // Test Region()
150     Region defaultRegion = new Region();
151     defaultRegion.quickContains(rect);
152 
153     // Test Region(Region)
154     Region oriRegion = new Region();
155     Region copyRegion = new Region(oriRegion);
156     copyRegion.quickContains(rect);
157 
158     // Test Region(Rect)
159     Region rectRegion = new Region(rect);
160     rectRegion.quickContains(rect);
161 
162     // Test Region(int, int, int, int)
163     Region intRegion = new Region(0, 0, 100, 100);
164     intRegion.quickContains(rect);
165   }
166 
167   @Test
testSet1()168   public void testSet1() {
169     Rect rect = new Rect(1, 2, 3, 4);
170     Region oriRegion = new Region(rect);
171     assertTrue(region.set(oriRegion));
172     assertEquals(1, region.getBounds().left);
173     assertEquals(2, region.getBounds().top);
174     assertEquals(3, region.getBounds().right);
175     assertEquals(4, region.getBounds().bottom);
176   }
177 
178   @Test
testSet2()179   public void testSet2() {
180     Rect rect = new Rect(1, 2, 3, 4);
181     assertTrue(region.set(rect));
182     assertEquals(1, region.getBounds().left);
183     assertEquals(2, region.getBounds().top);
184     assertEquals(3, region.getBounds().right);
185     assertEquals(4, region.getBounds().bottom);
186   }
187 
188   @Test
testSet3()189   public void testSet3() {
190     assertTrue(region.set(1, 2, 3, 4));
191     assertEquals(1, region.getBounds().left);
192     assertEquals(2, region.getBounds().top);
193     assertEquals(3, region.getBounds().right);
194     assertEquals(4, region.getBounds().bottom);
195   }
196 
197   @Test
testIsRect()198   public void testIsRect() {
199     assertFalse(region.isRect());
200     region = new Region(1, 2, 3, 4);
201     assertTrue(region.isRect());
202   }
203 
204   @Test
testIsComplex()205   public void testIsComplex() {
206     // Region is empty
207     assertFalse(region.isComplex());
208 
209     // Only one rectangle
210     region = new Region();
211     region.set(1, 2, 3, 4);
212     assertFalse(region.isComplex());
213 
214     // More than one rectangle
215     region = new Region();
216     region.set(1, 1, 2, 2);
217     region.union(new Rect(3, 3, 5, 5));
218     assertTrue(region.isComplex());
219   }
220 
221   @Test
testQuickContains1()222   public void testQuickContains1() {
223     Rect rect = new Rect(1, 2, 3, 4);
224     // This region not contains expected rectangle.
225     assertFalse(region.quickContains(rect));
226     region.set(rect);
227     // This region contains only one rectangle and it is the expected one.
228     assertTrue(region.quickContains(rect));
229     region.set(5, 6, 7, 8);
230     // This region contains more than one rectangle.
231     assertFalse(region.quickContains(rect));
232   }
233 
234   @Test
testQuickContains2()235   public void testQuickContains2() {
236     // This region not contains expected rectangle.
237     assertFalse(region.quickContains(1, 2, 3, 4));
238     region.set(1, 2, 3, 4);
239     // This region contains only one rectangle and it is the expected one.
240     assertTrue(region.quickContains(1, 2, 3, 4));
241     region.set(5, 6, 7, 8);
242     // This region contains more than one rectangle.
243     assertFalse(region.quickContains(1, 2, 3, 4));
244   }
245 
246   @Test
testUnion()247   public void testUnion() {
248     Rect rect1 = new Rect();
249     Rect rect2 = new Rect(0, 0, 20, 20);
250     Rect rect3 = new Rect(5, 5, 10, 10);
251     Rect rect4 = new Rect(10, 10, 30, 30);
252     Rect rect5 = new Rect(40, 40, 60, 60);
253 
254     // union (inclusive-or) the two regions
255     region.set(rect2);
256     // union null rectangle
257     assertTrue(region.contains(6, 6));
258     assertTrue(region.union(rect1));
259     assertTrue(region.contains(6, 6));
260 
261     // 1. union rectangle inside this region
262     region.set(rect2);
263     assertTrue(region.contains(2, 2));
264     assertTrue(region.contains(6, 6));
265     assertTrue(region.union(rect3));
266     verifyPointsInsideRegion(UNION_WITH1);
267     verifyPointsOutsideRegion(UNION_WITHOUT1);
268 
269     // 2. union rectangle overlap this region
270     region.set(rect2);
271     assertTrue(region.contains(2, 2));
272     assertFalse(region.contains(21, 21));
273     assertTrue(region.union(rect4));
274     verifyPointsInsideRegion(UNION_WITH2);
275     verifyPointsOutsideRegion(UNION_WITHOUT2);
276 
277     // 3. union rectangle out of this region
278     region.set(rect2);
279     assertTrue(region.contains(2, 2));
280     assertFalse(region.contains(41, 41));
281     assertTrue(region.union(rect5));
282     verifyPointsInsideRegion(UNION_WITH3);
283     verifyPointsOutsideRegion(UNION_WITHOUT3);
284   }
285 
286   @Test
testContains()287   public void testContains() {
288     region.set(2, 2, 5, 5);
289     // Not contain (1, 1).
290     assertFalse(region.contains(1, 1));
291 
292     // Test point inside this region.
293     assertTrue(region.contains(3, 3));
294 
295     // Test left-top corner.
296     assertTrue(region.contains(2, 2));
297 
298     // Test left-bottom corner.
299     assertTrue(region.contains(2, 4));
300 
301     // Test right-top corner.
302     assertTrue(region.contains(4, 2));
303 
304     // Test right-bottom corner.
305     assertTrue(region.contains(4, 4));
306 
307     // Though you set 5, but 5 is not contained by this region.
308     assertFalse(region.contains(5, 5));
309     assertFalse(region.contains(2, 5));
310     assertFalse(region.contains(5, 2));
311 
312     // Set a new rectangle.
313     region.set(6, 6, 8, 8);
314     assertFalse(region.contains(3, 3));
315     assertTrue(region.contains(7, 7));
316   }
317 
318   @Test
testEmpty()319   public void testEmpty() {
320     assertTrue(region.isEmpty());
321     region = null;
322     region = new Region(1, 2, 3, 4);
323     assertFalse(region.isEmpty());
324     region.setEmpty();
325     assertTrue(region.isEmpty());
326   }
327 
328   @Test
testGetBoundsNull()329   public void testGetBoundsNull() {
330     assertThrows(NullPointerException.class, () -> region.getBounds(null));
331   }
332 
333   @Test
testGetBounds()334   public void testGetBounds() {
335     // Normal, return true.
336     Rect rect1 = new Rect(1, 2, 3, 4);
337     region = new Region(rect1);
338     assertTrue(region.getBounds(rect1));
339 
340     region.setEmpty();
341     Rect rect2 = new Rect(5, 6, 7, 8);
342     assertFalse(region.getBounds(rect2));
343   }
344 
345   @Test
testOp1()346   public void testOp1() {
347     Rect rect1 = new Rect();
348     Rect rect2 = new Rect(0, 0, 20, 20);
349     Rect rect3 = new Rect(5, 5, 10, 10);
350     Rect rect4 = new Rect(10, 10, 30, 30);
351     Rect rect5 = new Rect(40, 40, 60, 60);
352 
353     verifyNullRegionOp1(rect1);
354     verifyDifferenceOp1(rect1, rect2, rect3, rect4, rect5);
355     verifyIntersectOp1(rect1, rect2, rect3, rect4, rect5);
356     verifyUnionOp1(rect1, rect2, rect3, rect4, rect5);
357     verifyXorOp1(rect1, rect2, rect3, rect4, rect5);
358     verifyReverseDifferenceOp1(rect1, rect2, rect3, rect4, rect5);
359     verifyReplaceOp1(rect1, rect2, rect3, rect4, rect5);
360   }
361 
verifyNullRegionOp1(Rect rect1)362   private void verifyNullRegionOp1(Rect rect1) {
363     // Region without rectangle
364     region = new Region();
365     assertFalse(region.op(rect1, Region.Op.DIFFERENCE));
366     assertFalse(region.op(rect1, Region.Op.INTERSECT));
367     assertFalse(region.op(rect1, Region.Op.UNION));
368     assertFalse(region.op(rect1, Region.Op.XOR));
369     assertFalse(region.op(rect1, Region.Op.REVERSE_DIFFERENCE));
370     assertFalse(region.op(rect1, Region.Op.REPLACE));
371   }
372 
verifyDifferenceOp1(Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5)373   private void verifyDifferenceOp1(Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5) {
374     // DIFFERENCE, Region with rectangle
375     // subtract the op region from the first region
376     region = new Region();
377     // subtract null rectangle
378     region.set(rect2);
379     assertTrue(region.op(rect1, Region.Op.DIFFERENCE));
380 
381     // 1. subtract rectangle inside this region
382     region.set(rect2);
383     assertTrue(region.contains(6, 6));
384     assertTrue(region.op(rect3, Region.Op.DIFFERENCE));
385     verifyPointsInsideRegion(DIFFERENCE_WITH1);
386     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT1);
387 
388     // 2. subtract rectangle overlap this region
389     region.set(rect2);
390     assertTrue(region.contains(11, 11));
391     assertTrue(region.op(rect4, Region.Op.DIFFERENCE));
392     verifyPointsInsideRegion(DIFFERENCE_WITH2);
393     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT2);
394 
395     // 3. subtract rectangle out of this region
396     region.set(rect2);
397     assertTrue(region.op(rect5, Region.Op.DIFFERENCE));
398     verifyPointsInsideRegion(DIFFERENCE_WITH3);
399     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT3);
400   }
401 
verifyIntersectOp1(Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5)402   private void verifyIntersectOp1(Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5) {
403     // INTERSECT, Region with rectangle
404     // intersect the two regions
405     region = new Region();
406     // intersect null rectangle
407     region.set(rect2);
408     assertFalse(region.op(rect1, Region.Op.INTERSECT));
409 
410     // 1. intersect rectangle inside this region
411     region.set(rect2);
412     assertTrue(region.contains(2, 2));
413     assertTrue(region.op(rect3, Region.Op.INTERSECT));
414     verifyPointsInsideRegion(INTERSECT_WITH1);
415     verifyPointsOutsideRegion(INTERSECT_WITHOUT1);
416 
417     // 2. intersect rectangle overlap this region
418     region.set(rect2);
419     assertTrue(region.contains(9, 9));
420     assertTrue(region.op(rect4, Region.Op.INTERSECT));
421     verifyPointsInsideRegion(INTERSECT_WITH2);
422     verifyPointsOutsideRegion(INTERSECT_WITHOUT2);
423 
424     // 3. intersect rectangle out of this region
425     region.set(rect2);
426     assertFalse(region.op(rect5, Region.Op.INTERSECT));
427   }
428 
verifyUnionOp1(Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5)429   private void verifyUnionOp1(Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5) {
430     // UNION, Region with rectangle
431     // union (inclusive-or) the two regions
432     region = new Region();
433     region.set(rect2);
434     // union null rectangle
435     assertTrue(region.contains(6, 6));
436     assertTrue(region.op(rect1, Region.Op.UNION));
437     assertTrue(region.contains(6, 6));
438 
439     // 1. union rectangle inside this region
440     region.set(rect2);
441     assertTrue(region.contains(2, 2));
442     assertTrue(region.contains(6, 6));
443     assertTrue(region.op(rect3, Region.Op.UNION));
444     verifyPointsInsideRegion(UNION_WITH1);
445     verifyPointsOutsideRegion(UNION_WITHOUT1);
446 
447     // 2. union rectangle overlap this region
448     region.set(rect2);
449     assertTrue(region.contains(2, 2));
450     assertFalse(region.contains(21, 21));
451     assertTrue(region.op(rect4, Region.Op.UNION));
452     verifyPointsInsideRegion(UNION_WITH2);
453     verifyPointsOutsideRegion(UNION_WITHOUT2);
454 
455     // 3. union rectangle out of this region
456     region.set(rect2);
457     assertTrue(region.contains(2, 2));
458     assertFalse(region.contains(41, 41));
459     assertTrue(region.op(rect5, Region.Op.UNION));
460     verifyPointsInsideRegion(UNION_WITH3);
461     verifyPointsOutsideRegion(UNION_WITHOUT3);
462   }
463 
verifyXorOp1(Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5)464   private void verifyXorOp1(Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5) {
465     // XOR, Region with rectangle
466     // exclusive-or the two regions
467     region = new Region();
468     // xor null rectangle
469     region.set(rect2);
470     assertTrue(region.op(rect1, Region.Op.XOR));
471 
472     // 1. xor rectangle inside this region
473     region.set(rect2);
474     assertTrue(region.contains(2, 2));
475     assertTrue(region.contains(6, 6));
476     assertTrue(region.op(rect3, Region.Op.XOR));
477     verifyPointsInsideRegion(XOR_WITH1);
478     verifyPointsOutsideRegion(XOR_WITHOUT1);
479 
480     // 2. xor rectangle overlap this region
481     region.set(rect2);
482     assertTrue(region.contains(2, 2));
483     assertTrue(region.contains(11, 11));
484     assertFalse(region.contains(21, 21));
485     assertTrue(region.op(rect4, Region.Op.XOR));
486     verifyPointsInsideRegion(XOR_WITH2);
487     verifyPointsOutsideRegion(XOR_WITHOUT2);
488 
489     // 3. xor rectangle out of this region
490     region.set(rect2);
491     assertTrue(region.contains(2, 2));
492     assertFalse(region.contains(41, 41));
493     assertTrue(region.op(rect5, Region.Op.XOR));
494     verifyPointsInsideRegion(XOR_WITH3);
495     verifyPointsOutsideRegion(XOR_WITHOUT3);
496   }
497 
verifyReverseDifferenceOp1( Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5)498   private void verifyReverseDifferenceOp1(
499       Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5) {
500     // REVERSE_DIFFERENCE, Region with rectangle
501     // reverse difference the first region from the op region
502     region = new Region();
503     region.set(rect2);
504     // reverse difference null rectangle
505     assertFalse(region.op(rect1, Region.Op.REVERSE_DIFFERENCE));
506 
507     // 1. reverse difference rectangle inside this region
508     region.set(rect2);
509     assertTrue(region.contains(2, 2));
510     assertTrue(region.contains(6, 6));
511     assertFalse(region.op(rect3, Region.Op.REVERSE_DIFFERENCE));
512 
513     // 2. reverse difference rectangle overlap this region
514     region.set(rect2);
515     assertTrue(region.contains(2, 2));
516     assertTrue(region.contains(11, 11));
517     assertFalse(region.contains(21, 21));
518     assertTrue(region.op(rect4, Region.Op.REVERSE_DIFFERENCE));
519     verifyPointsInsideRegion(REVERSE_DIFFERENCE_WITH2);
520     verifyPointsOutsideRegion(REVERSE_DIFFERENCE_WITHOUT2);
521 
522     // 3. reverse difference rectangle out of this region
523     region.set(rect2);
524     assertTrue(region.contains(2, 2));
525     assertFalse(region.contains(41, 41));
526     assertTrue(region.op(rect5, Region.Op.REVERSE_DIFFERENCE));
527     verifyPointsInsideRegion(REVERSE_DIFFERENCE_WITH3);
528     verifyPointsOutsideRegion(REVERSE_DIFFERENCE_WITHOUT3);
529   }
530 
verifyReplaceOp1(Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5)531   private void verifyReplaceOp1(Rect rect1, Rect rect2, Rect rect3, Rect rect4, Rect rect5) {
532     // REPLACE, Region with rectangle
533     // replace the dst region with the op region
534     region = new Region();
535     region.set(rect2);
536     // subtract null rectangle
537     assertFalse(region.op(rect1, Region.Op.REPLACE));
538     // subtract rectangle inside this region
539     region.set(rect2);
540     assertEquals(rect2, region.getBounds());
541     assertTrue(region.op(rect3, Region.Op.REPLACE));
542     assertNotSame(rect2, region.getBounds());
543     assertEquals(rect3, region.getBounds());
544     // subtract rectangle overlap this region
545     region.set(rect2);
546     assertEquals(rect2, region.getBounds());
547     assertTrue(region.op(rect4, Region.Op.REPLACE));
548     assertNotSame(rect2, region.getBounds());
549     assertEquals(rect4, region.getBounds());
550     // subtract rectangle out of this region
551     region.set(rect2);
552     assertEquals(rect2, region.getBounds());
553     assertTrue(region.op(rect5, Region.Op.REPLACE));
554     assertNotSame(rect2, region.getBounds());
555     assertEquals(rect5, region.getBounds());
556   }
557 
558   @Test
testOp2()559   public void testOp2() {
560     Rect rect2 = new Rect(0, 0, 20, 20);
561     Rect rect3 = new Rect(5, 5, 10, 10);
562     Rect rect4 = new Rect(10, 10, 30, 30);
563     Rect rect5 = new Rect(40, 40, 60, 60);
564 
565     verifyNullRegionOp2();
566     verifyDifferenceOp2(rect2);
567     verifyIntersectOp2(rect2);
568     verifyUnionOp2(rect2);
569     verifyXorOp2(rect2);
570     verifyReverseDifferenceOp2(rect2);
571     verifyReplaceOp2(rect2, rect3, rect4, rect5);
572   }
573 
verifyNullRegionOp2()574   private void verifyNullRegionOp2() {
575     // Region without rectangle
576     region = new Region();
577     assertFalse(region.op(0, 0, 0, 0, Region.Op.DIFFERENCE));
578     assertFalse(region.op(0, 0, 0, 0, Region.Op.INTERSECT));
579     assertFalse(region.op(0, 0, 0, 0, Region.Op.UNION));
580     assertFalse(region.op(0, 0, 0, 0, Region.Op.XOR));
581     assertFalse(region.op(0, 0, 0, 0, Region.Op.REVERSE_DIFFERENCE));
582     assertFalse(region.op(0, 0, 0, 0, Region.Op.REPLACE));
583   }
584 
verifyDifferenceOp2(Rect rect2)585   private void verifyDifferenceOp2(Rect rect2) {
586     // DIFFERENCE, Region with rectangle
587     // subtract the op region from the first region
588     region = new Region();
589     // subtract null rectangle
590     region.set(rect2);
591     assertTrue(region.op(0, 0, 0, 0, Region.Op.DIFFERENCE));
592 
593     // 1. subtract rectangle inside this region
594     region.set(rect2);
595     assertTrue(region.contains(6, 6));
596     assertTrue(region.op(5, 5, 10, 10, Region.Op.DIFFERENCE));
597     verifyPointsInsideRegion(DIFFERENCE_WITH1);
598     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT1);
599 
600     // 2. subtract rectangle overlap this region
601     region.set(rect2);
602     assertTrue(region.contains(11, 11));
603     assertTrue(region.op(10, 10, 30, 30, Region.Op.DIFFERENCE));
604     verifyPointsInsideRegion(DIFFERENCE_WITH2);
605     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT2);
606 
607     // 3. subtract rectangle out of this region
608     region.set(rect2);
609     assertTrue(region.op(40, 40, 60, 60, Region.Op.DIFFERENCE));
610     verifyPointsInsideRegion(DIFFERENCE_WITH3);
611     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT3);
612   }
613 
verifyIntersectOp2(Rect rect2)614   private void verifyIntersectOp2(Rect rect2) {
615     // INTERSECT, Region with rectangle
616     // intersect the two regions
617     region = new Region();
618     // intersect null rectangle
619     region.set(rect2);
620     assertFalse(region.op(0, 0, 0, 0, Region.Op.INTERSECT));
621 
622     // 1. intersect rectangle inside this region
623     region.set(rect2);
624     assertTrue(region.contains(2, 2));
625     assertTrue(region.op(5, 5, 10, 10, Region.Op.INTERSECT));
626     verifyPointsInsideRegion(INTERSECT_WITH1);
627     verifyPointsOutsideRegion(INTERSECT_WITHOUT1);
628 
629     // 2. intersect rectangle overlap this region
630     region.set(rect2);
631     assertTrue(region.contains(9, 9));
632     assertTrue(region.op(10, 10, 30, 30, Region.Op.INTERSECT));
633     verifyPointsInsideRegion(INTERSECT_WITH2);
634     verifyPointsOutsideRegion(INTERSECT_WITHOUT2);
635 
636     // 3. intersect rectangle out of this region
637     region.set(rect2);
638     assertFalse(region.op(40, 40, 60, 60, Region.Op.INTERSECT));
639   }
640 
verifyUnionOp2(Rect rect2)641   private void verifyUnionOp2(Rect rect2) {
642     // UNION, Region with rectangle
643     // union (inclusive-or) the two regions
644     region = new Region();
645     region.set(rect2);
646     // union null rectangle
647     assertTrue(region.contains(6, 6));
648     assertTrue(region.op(0, 0, 0, 0, Region.Op.UNION));
649     assertTrue(region.contains(6, 6));
650 
651     // 1. union rectangle inside this region
652     region.set(rect2);
653     assertTrue(region.contains(2, 2));
654     assertTrue(region.contains(6, 6));
655     assertTrue(region.op(5, 5, 10, 10, Region.Op.UNION));
656     verifyPointsInsideRegion(UNION_WITH1);
657     verifyPointsOutsideRegion(UNION_WITHOUT1);
658 
659     // 2. union rectangle overlap this region
660     region.set(rect2);
661     assertTrue(region.contains(2, 2));
662     assertFalse(region.contains(21, 21));
663     assertTrue(region.op(10, 10, 30, 30, Region.Op.UNION));
664     verifyPointsInsideRegion(UNION_WITH2);
665     verifyPointsOutsideRegion(UNION_WITHOUT2);
666 
667     // 3. union rectangle out of this region
668     region.set(rect2);
669     assertTrue(region.contains(2, 2));
670     assertFalse(region.contains(41, 41));
671     assertTrue(region.op(40, 40, 60, 60, Region.Op.UNION));
672     verifyPointsInsideRegion(UNION_WITH3);
673     verifyPointsOutsideRegion(UNION_WITHOUT3);
674   }
675 
verifyXorOp2(Rect rect2)676   private void verifyXorOp2(Rect rect2) {
677     // XOR, Region with rectangle
678     // exclusive-or the two regions
679     region = new Region();
680     region.set(rect2);
681     // xor null rectangle
682     assertTrue(region.op(0, 0, 0, 0, Region.Op.XOR));
683 
684     // 1. xor rectangle inside this region
685     region.set(rect2);
686     assertTrue(region.contains(2, 2));
687     assertTrue(region.contains(6, 6));
688     assertTrue(region.op(5, 5, 10, 10, Region.Op.XOR));
689     verifyPointsInsideRegion(XOR_WITH1);
690     verifyPointsOutsideRegion(XOR_WITHOUT1);
691 
692     // 2. xor rectangle overlap this region
693     region.set(rect2);
694     assertTrue(region.contains(2, 2));
695     assertTrue(region.contains(11, 11));
696     assertFalse(region.contains(21, 21));
697     assertTrue(region.op(10, 10, 30, 30, Region.Op.XOR));
698     verifyPointsInsideRegion(XOR_WITH2);
699     verifyPointsOutsideRegion(XOR_WITHOUT2);
700 
701     // 3. xor rectangle out of this region
702     region.set(rect2);
703     assertTrue(region.contains(2, 2));
704     assertFalse(region.contains(41, 41));
705     assertTrue(region.op(40, 40, 60, 60, Region.Op.XOR));
706     verifyPointsInsideRegion(XOR_WITH3);
707     verifyPointsOutsideRegion(XOR_WITHOUT3);
708   }
709 
verifyReverseDifferenceOp2(Rect rect2)710   private void verifyReverseDifferenceOp2(Rect rect2) {
711     // REVERSE_DIFFERENCE, Region with rectangle
712     // reverse difference the first region from the op region
713     region = new Region();
714     region.set(rect2);
715     // reverse difference null rectangle
716     assertFalse(region.op(0, 0, 0, 0, Region.Op.REVERSE_DIFFERENCE));
717     // reverse difference rectangle inside this region
718     region.set(rect2);
719     assertTrue(region.contains(2, 2));
720     assertTrue(region.contains(6, 6));
721     assertFalse(region.op(5, 5, 10, 10, Region.Op.REVERSE_DIFFERENCE));
722     // reverse difference rectangle overlap this region
723     region.set(rect2);
724     assertTrue(region.contains(2, 2));
725     assertTrue(region.contains(11, 11));
726     assertFalse(region.contains(21, 21));
727     assertTrue(region.op(10, 10, 30, 30, Region.Op.REVERSE_DIFFERENCE));
728     verifyPointsInsideRegion(REVERSE_DIFFERENCE_WITH2);
729     verifyPointsOutsideRegion(REVERSE_DIFFERENCE_WITHOUT2);
730     // reverse difference rectangle out of this region
731     region.set(rect2);
732     assertTrue(region.contains(2, 2));
733     assertFalse(region.contains(41, 41));
734     assertTrue(region.op(40, 40, 60, 60, Region.Op.REVERSE_DIFFERENCE));
735     verifyPointsInsideRegion(REVERSE_DIFFERENCE_WITH3);
736     verifyPointsOutsideRegion(REVERSE_DIFFERENCE_WITHOUT3);
737   }
738 
verifyReplaceOp2(Rect rect2, Rect rect3, Rect rect4, Rect rect5)739   private void verifyReplaceOp2(Rect rect2, Rect rect3, Rect rect4, Rect rect5) {
740     // REPLACE, Region w1ith rectangle
741     // replace the dst region with the op region
742     region = new Region();
743     region.set(rect2);
744     // subtract null rectangle
745     assertFalse(region.op(0, 0, 0, 0, Region.Op.REPLACE));
746     // subtract rectangle inside this region
747     region.set(rect2);
748     assertEquals(rect2, region.getBounds());
749     assertTrue(region.op(5, 5, 10, 10, Region.Op.REPLACE));
750     assertNotSame(rect2, region.getBounds());
751     assertEquals(rect3, region.getBounds());
752     // subtract rectangle overlap this region
753     region.set(rect2);
754     assertEquals(rect2, region.getBounds());
755     assertTrue(region.op(10, 10, 30, 30, Region.Op.REPLACE));
756     assertNotSame(rect2, region.getBounds());
757     assertEquals(rect4, region.getBounds());
758     // subtract rectangle out of this region
759     region.set(rect2);
760     assertEquals(rect2, region.getBounds());
761     assertTrue(region.op(40, 40, 60, 60, Region.Op.REPLACE));
762     assertNotSame(rect2, region.getBounds());
763     assertEquals(rect5, region.getBounds());
764   }
765 
766   @Test
testOp3()767   public void testOp3() {
768     Region region1 = new Region();
769     Region region2 = new Region(0, 0, 20, 20);
770     Region region3 = new Region(5, 5, 10, 10);
771     Region region4 = new Region(10, 10, 30, 30);
772     Region region5 = new Region(40, 40, 60, 60);
773 
774     verifyNullRegionOp3(region1);
775     verifyDifferenceOp3(region1, region2, region3, region4, region5);
776     verifyIntersectOp3(region1, region2, region3, region4, region5);
777     verifyUnionOp3(region1, region2, region3, region4, region5);
778     verifyXorOp3(region1, region2, region3, region4, region5);
779     verifyReverseDifferenceOp3(region1, region2, region3, region4, region5);
780     verifyReplaceOp3(region1, region2, region3, region4, region5);
781   }
782 
verifyNullRegionOp3(Region region1)783   private void verifyNullRegionOp3(Region region1) {
784     // Region without rectangle
785     region = new Region();
786     assertFalse(region.op(region1, Region.Op.DIFFERENCE));
787     assertFalse(region.op(region1, Region.Op.INTERSECT));
788     assertFalse(region.op(region1, Region.Op.UNION));
789     assertFalse(region.op(region1, Region.Op.XOR));
790     assertFalse(region.op(region1, Region.Op.REVERSE_DIFFERENCE));
791     assertFalse(region.op(region1, Region.Op.REPLACE));
792   }
793 
verifyDifferenceOp3( Region region1, Region region2, Region region3, Region region4, Region region5)794   private void verifyDifferenceOp3(
795       Region region1, Region region2, Region region3, Region region4, Region region5) {
796     // DIFFERENCE, Region with rectangle
797     // subtract the op region from the first region
798     region = new Region();
799     // subtract null rectangle
800     region.set(region2);
801     assertTrue(region.op(region1, Region.Op.DIFFERENCE));
802 
803     // 1. subtract rectangle inside this region
804     region.set(region2);
805     assertTrue(region.contains(6, 6));
806     assertTrue(region.op(region3, Region.Op.DIFFERENCE));
807     verifyPointsInsideRegion(DIFFERENCE_WITH1);
808     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT1);
809 
810     // 2. subtract rectangle overlap this region
811     region.set(region2);
812     assertTrue(region.contains(11, 11));
813     assertTrue(region.op(region4, Region.Op.DIFFERENCE));
814     verifyPointsInsideRegion(DIFFERENCE_WITH2);
815     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT2);
816 
817     // 3. subtract rectangle out of this region
818     region.set(region2);
819     assertTrue(region.op(region5, Region.Op.DIFFERENCE));
820     verifyPointsInsideRegion(DIFFERENCE_WITH3);
821     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT3);
822   }
823 
verifyIntersectOp3( Region region1, Region region2, Region region3, Region region4, Region region5)824   private void verifyIntersectOp3(
825       Region region1, Region region2, Region region3, Region region4, Region region5) {
826     // INTERSECT, Region with rectangle
827     // intersect the two regions
828     region = new Region();
829     region.set(region2);
830     // intersect null rectangle
831     assertFalse(region.op(region1, Region.Op.INTERSECT));
832 
833     // 1. intersect rectangle inside this region
834     region.set(region2);
835     assertTrue(region.contains(2, 2));
836     assertTrue(region.op(region3, Region.Op.INTERSECT));
837     verifyPointsInsideRegion(INTERSECT_WITH1);
838     verifyPointsOutsideRegion(INTERSECT_WITHOUT1);
839 
840     // 2. intersect rectangle overlap this region
841     region.set(region2);
842     assertTrue(region.contains(9, 9));
843     assertTrue(region.op(region4, Region.Op.INTERSECT));
844     verifyPointsInsideRegion(INTERSECT_WITH2);
845     verifyPointsOutsideRegion(INTERSECT_WITHOUT2);
846 
847     // 3. intersect rectangle out of this region
848     region.set(region2);
849     assertFalse(region.op(region5, Region.Op.INTERSECT));
850   }
851 
verifyUnionOp3( Region region1, Region region2, Region region3, Region region4, Region region5)852   private void verifyUnionOp3(
853       Region region1, Region region2, Region region3, Region region4, Region region5) {
854     // UNION, Region with rectangle
855     // union (inclusive-or) the two regions
856     region = new Region();
857     // union null rectangle
858     region.set(region2);
859     assertTrue(region.contains(6, 6));
860     assertTrue(region.op(region1, Region.Op.UNION));
861     assertTrue(region.contains(6, 6));
862 
863     // 1. union rectangle inside this region
864     region.set(region2);
865     assertTrue(region.contains(2, 2));
866     assertTrue(region.contains(6, 6));
867     assertTrue(region.op(region3, Region.Op.UNION));
868     verifyPointsInsideRegion(UNION_WITH1);
869     verifyPointsOutsideRegion(UNION_WITHOUT1);
870 
871     // 2. union rectangle overlap this region
872     region.set(region2);
873     assertTrue(region.contains(2, 2));
874     assertFalse(region.contains(21, 21));
875     assertTrue(region.op(region4, Region.Op.UNION));
876     verifyPointsInsideRegion(UNION_WITH2);
877     verifyPointsOutsideRegion(UNION_WITHOUT2);
878 
879     // 3. union rectangle out of this region
880     region.set(region2);
881     assertTrue(region.contains(2, 2));
882     assertFalse(region.contains(41, 41));
883     assertTrue(region.op(region5, Region.Op.UNION));
884     verifyPointsInsideRegion(UNION_WITH3);
885     verifyPointsOutsideRegion(UNION_WITHOUT3);
886   }
887 
verifyXorOp3( Region region1, Region region2, Region region3, Region region4, Region region5)888   private void verifyXorOp3(
889       Region region1, Region region2, Region region3, Region region4, Region region5) {
890     // XOR, Region with rectangle
891     // exclusive-or the two regions
892     region = new Region();
893     // xor null rectangle
894     region.set(region2);
895     assertTrue(region.op(region1, Region.Op.XOR));
896 
897     // 1. xor rectangle inside this region
898     region.set(region2);
899     assertTrue(region.contains(2, 2));
900     assertTrue(region.contains(6, 6));
901     assertTrue(region.op(region3, Region.Op.XOR));
902     verifyPointsInsideRegion(XOR_WITH1);
903     verifyPointsOutsideRegion(XOR_WITHOUT1);
904 
905     // 2. xor rectangle overlap this region
906     region.set(region2);
907     assertTrue(region.contains(2, 2));
908     assertTrue(region.contains(11, 11));
909     assertFalse(region.contains(21, 21));
910     assertTrue(region.op(region4, Region.Op.XOR));
911     verifyPointsInsideRegion(XOR_WITH2);
912     verifyPointsOutsideRegion(XOR_WITHOUT2);
913 
914     // 3. xor rectangle out of this region
915     region.set(region2);
916     assertTrue(region.contains(2, 2));
917     assertFalse(region.contains(41, 41));
918     assertTrue(region.op(region5, Region.Op.XOR));
919     verifyPointsInsideRegion(XOR_WITH3);
920     verifyPointsOutsideRegion(XOR_WITHOUT3);
921   }
922 
verifyReverseDifferenceOp3( Region region1, Region region2, Region region3, Region region4, Region region5)923   private void verifyReverseDifferenceOp3(
924       Region region1, Region region2, Region region3, Region region4, Region region5) {
925     // REVERSE_DIFFERENCE, Region with rectangle
926     // reverse difference the first region from the op region
927     region = new Region();
928     // reverse difference null rectangle
929     region.set(region2);
930     assertFalse(region.op(region1, Region.Op.REVERSE_DIFFERENCE));
931 
932     // 1. reverse difference rectangle inside this region
933     region.set(region2);
934     assertTrue(region.contains(2, 2));
935     assertTrue(region.contains(6, 6));
936     assertFalse(region.op(region3, Region.Op.REVERSE_DIFFERENCE));
937 
938     // 2. reverse difference rectangle overlap this region
939     region.set(region2);
940     assertTrue(region.contains(2, 2));
941     assertTrue(region.contains(11, 11));
942     assertFalse(region.contains(21, 21));
943     assertTrue(region.op(region4, Region.Op.REVERSE_DIFFERENCE));
944     verifyPointsInsideRegion(REVERSE_DIFFERENCE_WITH2);
945     verifyPointsOutsideRegion(REVERSE_DIFFERENCE_WITHOUT2);
946 
947     // 3. reverse difference rectangle out of this region
948     region.set(region2);
949     assertTrue(region.contains(2, 2));
950     assertFalse(region.contains(41, 41));
951     assertTrue(region.op(region5, Region.Op.REVERSE_DIFFERENCE));
952     verifyPointsInsideRegion(REVERSE_DIFFERENCE_WITH3);
953     verifyPointsOutsideRegion(REVERSE_DIFFERENCE_WITHOUT3);
954   }
955 
verifyReplaceOp3( Region region1, Region region2, Region region3, Region region4, Region region5)956   private void verifyReplaceOp3(
957       Region region1, Region region2, Region region3, Region region4, Region region5) {
958     // REPLACE, Region with rectangle
959     // replace the dst region with the op region
960     region = new Region();
961     region.set(region2);
962     // subtract null rectangle
963     assertFalse(region.op(region1, Region.Op.REPLACE));
964     // subtract rectangle inside this region
965     region.set(region2);
966     assertEquals(region2.getBounds(), region.getBounds());
967     assertTrue(region.op(region3, Region.Op.REPLACE));
968     assertNotSame(region2.getBounds(), region.getBounds());
969     assertEquals(region3.getBounds(), region.getBounds());
970     // subtract rectangle overlap this region
971     region.set(region2);
972     assertEquals(region2.getBounds(), region.getBounds());
973     assertTrue(region.op(region4, Region.Op.REPLACE));
974     assertNotSame(region2.getBounds(), region.getBounds());
975     assertEquals(region4.getBounds(), region.getBounds());
976     // subtract rectangle out of this region
977     region.set(region2);
978     assertEquals(region2.getBounds(), region.getBounds());
979     assertTrue(region.op(region5, Region.Op.REPLACE));
980     assertNotSame(region2.getBounds(), region.getBounds());
981     assertEquals(region5.getBounds(), region.getBounds());
982   }
983 
984   @Test
testOp4()985   public void testOp4() {
986     Rect rect1 = new Rect();
987     Rect rect2 = new Rect(0, 0, 20, 20);
988 
989     Region region1 = new Region();
990     Region region2 = new Region(0, 0, 20, 20);
991     Region region3 = new Region(5, 5, 10, 10);
992     Region region4 = new Region(10, 10, 30, 30);
993     Region region5 = new Region(40, 40, 60, 60);
994 
995     verifyNullRegionOp4(rect1, region1);
996     verifyDifferenceOp4(rect1, rect2, region1, region3, region4, region5);
997     verifyIntersectOp4(rect1, rect2, region1, region3, region4, region5);
998     verifyUnionOp4(rect1, rect2, region1, region3, region4, region5);
999     verifyXorOp4(rect1, rect2, region1, region3, region4, region5);
1000     verifyReverseDifferenceOp4(rect1, rect2, region1, region3, region4, region5);
1001     verifyReplaceOp4(rect1, rect2, region1, region2, region3, region4, region5);
1002   }
1003 
verifyNullRegionOp4(Rect rect1, Region region1)1004   private void verifyNullRegionOp4(Rect rect1, Region region1) {
1005     // Region without rectangle
1006     region = new Region();
1007     assertFalse(region.op(rect1, region1, Region.Op.DIFFERENCE));
1008     assertFalse(region.op(rect1, region1, Region.Op.INTERSECT));
1009     assertFalse(region.op(rect1, region1, Region.Op.UNION));
1010 
1011     assertFalse(region.op(rect1, region1, Region.Op.XOR));
1012     assertFalse(region.op(rect1, region1, Region.Op.REVERSE_DIFFERENCE));
1013     assertFalse(region.op(rect1, region1, Region.Op.REPLACE));
1014   }
1015 
verifyDifferenceOp4( Rect rect1, Rect rect2, Region region1, Region region3, Region region4, Region region5)1016   private void verifyDifferenceOp4(
1017       Rect rect1, Rect rect2, Region region1, Region region3, Region region4, Region region5) {
1018     // DIFFERENCE, Region with rectangle
1019     // subtract the op region from the first region
1020     region = new Region();
1021     // subtract null rectangle
1022     assertTrue(region.op(rect2, region1, Region.Op.DIFFERENCE));
1023 
1024     // 1. subtract rectangle inside this region
1025     region.set(rect1);
1026     assertTrue(region.op(rect2, region3, Region.Op.DIFFERENCE));
1027     verifyPointsInsideRegion(DIFFERENCE_WITH1);
1028     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT1);
1029 
1030     // 2. subtract rectangle overlap this region
1031     region.set(rect1);
1032     assertTrue(region.op(rect2, region4, Region.Op.DIFFERENCE));
1033     verifyPointsInsideRegion(DIFFERENCE_WITH2);
1034     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT2);
1035 
1036     // 3. subtract rectangle out of this region
1037     region.set(rect1);
1038     assertTrue(region.op(rect2, region5, Region.Op.DIFFERENCE));
1039     verifyPointsInsideRegion(DIFFERENCE_WITH3);
1040     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT3);
1041   }
1042 
verifyIntersectOp4( Rect rect1, Rect rect2, Region region1, Region region3, Region region4, Region region5)1043   private void verifyIntersectOp4(
1044       Rect rect1, Rect rect2, Region region1, Region region3, Region region4, Region region5) {
1045     // INTERSECT, Region with rectangle
1046     // intersect the two regions
1047     region = new Region();
1048     // intersect null rectangle
1049     region.set(rect1);
1050     assertFalse(region.op(rect2, region1, Region.Op.INTERSECT));
1051 
1052     // 1. intersect rectangle inside this region
1053     region.set(rect1);
1054     assertTrue(region.op(rect2, region3, Region.Op.INTERSECT));
1055     verifyPointsInsideRegion(INTERSECT_WITH1);
1056     verifyPointsOutsideRegion(INTERSECT_WITHOUT1);
1057 
1058     // 2. intersect rectangle overlap this region
1059     region.set(rect1);
1060     assertTrue(region.op(rect2, region4, Region.Op.INTERSECT));
1061     verifyPointsInsideRegion(INTERSECT_WITH2);
1062     verifyPointsOutsideRegion(INTERSECT_WITHOUT2);
1063 
1064     // 3. intersect rectangle out of this region
1065     region.set(rect1);
1066     assertFalse(region.op(rect2, region5, Region.Op.INTERSECT));
1067   }
1068 
verifyUnionOp4( Rect rect1, Rect rect2, Region region1, Region region3, Region region4, Region region5)1069   private void verifyUnionOp4(
1070       Rect rect1, Rect rect2, Region region1, Region region3, Region region4, Region region5) {
1071     // UNION, Region with rectangle
1072     // union (inclusive-or) the two regions
1073     region = new Region();
1074     // union null rectangle
1075     region.set(rect1);
1076     assertTrue(region.op(rect2, region1, Region.Op.UNION));
1077     assertTrue(region.contains(6, 6));
1078 
1079     // 1. union rectangle inside this region
1080     region.set(rect1);
1081     assertTrue(region.op(rect2, region3, Region.Op.UNION));
1082     verifyPointsInsideRegion(UNION_WITH1);
1083     verifyPointsOutsideRegion(UNION_WITHOUT1);
1084 
1085     // 2. union rectangle overlap this region
1086     region.set(rect1);
1087     assertTrue(region.op(rect2, region4, Region.Op.UNION));
1088     verifyPointsInsideRegion(UNION_WITH2);
1089     verifyPointsOutsideRegion(UNION_WITHOUT2);
1090 
1091     // 3. union rectangle out of this region
1092     region.set(rect1);
1093     assertTrue(region.op(rect2, region5, Region.Op.UNION));
1094     verifyPointsInsideRegion(UNION_WITH3);
1095     verifyPointsOutsideRegion(UNION_WITHOUT3);
1096   }
1097 
verifyXorOp4( Rect rect1, Rect rect2, Region region1, Region region3, Region region4, Region region5)1098   private void verifyXorOp4(
1099       Rect rect1, Rect rect2, Region region1, Region region3, Region region4, Region region5) {
1100     // XOR, Region with rectangle
1101     // exclusive-or the two regions
1102     region = new Region();
1103     // xor null rectangle
1104     region.set(rect1);
1105     assertTrue(region.op(rect2, region1, Region.Op.XOR));
1106 
1107     // 1. xor rectangle inside this region
1108     region.set(rect1);
1109     assertTrue(region.op(rect2, region3, Region.Op.XOR));
1110     verifyPointsInsideRegion(XOR_WITH1);
1111     verifyPointsOutsideRegion(XOR_WITHOUT1);
1112 
1113     // 2. xor rectangle overlap this region
1114     region.set(rect1);
1115     assertTrue(region.op(rect2, region4, Region.Op.XOR));
1116     verifyPointsInsideRegion(XOR_WITH2);
1117     verifyPointsOutsideRegion(XOR_WITHOUT2);
1118 
1119     // 3. xor rectangle out of this region
1120     region.set(rect1);
1121     assertTrue(region.op(rect2, region5, Region.Op.XOR));
1122     verifyPointsInsideRegion(XOR_WITH3);
1123     verifyPointsOutsideRegion(XOR_WITHOUT3);
1124   }
1125 
verifyReverseDifferenceOp4( Rect rect1, Rect rect2, Region region1, Region region3, Region region4, Region region5)1126   private void verifyReverseDifferenceOp4(
1127       Rect rect1, Rect rect2, Region region1, Region region3, Region region4, Region region5) {
1128     // REVERSE_DIFFERENCE, Region with rectangle
1129     // reverse difference the first region from the op region
1130     region = new Region();
1131     // reverse difference null rectangle
1132     region.set(rect1);
1133     assertFalse(region.op(rect2, region1, Region.Op.REVERSE_DIFFERENCE));
1134 
1135     // 1. reverse difference rectangle inside this region
1136     region.set(rect1);
1137     assertFalse(region.op(rect2, region3, Region.Op.REVERSE_DIFFERENCE));
1138 
1139     // 2. reverse difference rectangle overlap this region
1140     region.set(rect1);
1141     assertTrue(region.op(rect2, region4, Region.Op.REVERSE_DIFFERENCE));
1142     verifyPointsInsideRegion(REVERSE_DIFFERENCE_WITH2);
1143     verifyPointsOutsideRegion(REVERSE_DIFFERENCE_WITHOUT2);
1144 
1145     // 3. reverse difference rectangle out of this region
1146     region.set(rect1);
1147     assertTrue(region.op(rect2, region5, Region.Op.REVERSE_DIFFERENCE));
1148     verifyPointsInsideRegion(REVERSE_DIFFERENCE_WITH3);
1149     verifyPointsOutsideRegion(REVERSE_DIFFERENCE_WITHOUT3);
1150   }
1151 
verifyReplaceOp4( Rect rect1, Rect rect2, Region region1, Region region2, Region region3, Region region4, Region region5)1152   private void verifyReplaceOp4(
1153       Rect rect1,
1154       Rect rect2,
1155       Region region1,
1156       Region region2,
1157       Region region3,
1158       Region region4,
1159       Region region5) {
1160     // REPLACE, Region with rectangle
1161     // replace the dst region with the op region
1162     region = new Region();
1163     // subtract null rectangle
1164     region.set(rect1);
1165     assertFalse(region.op(rect2, region1, Region.Op.REPLACE));
1166     // subtract rectangle inside this region
1167     region.set(rect1);
1168     assertTrue(region.op(rect2, region3, Region.Op.REPLACE));
1169     assertNotSame(region2.getBounds(), region.getBounds());
1170     assertEquals(region3.getBounds(), region.getBounds());
1171     // subtract rectangle overlap this region
1172     region.set(rect1);
1173     assertTrue(region.op(rect2, region4, Region.Op.REPLACE));
1174     assertNotSame(region2.getBounds(), region.getBounds());
1175     assertEquals(region4.getBounds(), region.getBounds());
1176     // subtract rectangle out of this region
1177     region.set(rect1);
1178     assertTrue(region.op(rect2, region5, Region.Op.REPLACE));
1179     assertNotSame(region2.getBounds(), region.getBounds());
1180     assertEquals(region5.getBounds(), region.getBounds());
1181   }
1182 
1183   @Test
testOp5()1184   public void testOp5() {
1185     Region region1 = new Region();
1186     Region region2 = new Region(0, 0, 20, 20);
1187     Region region3 = new Region(5, 5, 10, 10);
1188     Region region4 = new Region(10, 10, 30, 30);
1189     Region region5 = new Region(40, 40, 60, 60);
1190 
1191     verifyNullRegionOp5(region1);
1192     verifyDifferenceOp5(region1, region2, region3, region4, region5);
1193     verifyIntersectOp5(region1, region2, region3, region4, region5);
1194     verifyUnionOp5(region1, region2, region3, region4, region5);
1195     verifyXorOp5(region1, region2, region3, region4, region5);
1196     verifyReverseDifferenceOp5(region1, region2, region3, region4, region5);
1197     verifyReplaceOp5(region1, region2, region3, region4, region5);
1198   }
1199 
verifyNullRegionOp5(Region region1)1200   private void verifyNullRegionOp5(Region region1) {
1201     // Region without rectangle
1202     region = new Region();
1203     assertFalse(region.op(region, region1, Region.Op.DIFFERENCE));
1204     assertFalse(region.op(region, region1, Region.Op.INTERSECT));
1205     assertFalse(region.op(region, region1, Region.Op.UNION));
1206     assertFalse(region.op(region, region1, Region.Op.XOR));
1207     assertFalse(region.op(region, region1, Region.Op.REVERSE_DIFFERENCE));
1208     assertFalse(region.op(region, region1, Region.Op.REPLACE));
1209   }
1210 
verifyDifferenceOp5( Region region1, Region region2, Region region3, Region region4, Region region5)1211   private void verifyDifferenceOp5(
1212       Region region1, Region region2, Region region3, Region region4, Region region5) {
1213     // DIFFERENCE, Region with rectangle
1214     // subtract the op region from the first region
1215     region = new Region();
1216     // subtract null rectangle
1217     region.set(region1);
1218     assertTrue(region.op(region2, region1, Region.Op.DIFFERENCE));
1219 
1220     // 1. subtract rectangle inside this region
1221     region.set(region1);
1222     assertTrue(region.op(region2, region3, Region.Op.DIFFERENCE));
1223     verifyPointsInsideRegion(DIFFERENCE_WITH1);
1224     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT1);
1225 
1226     // 2. subtract rectangle overlap this region
1227     region.set(region1);
1228     assertTrue(region.op(region2, region4, Region.Op.DIFFERENCE));
1229     verifyPointsInsideRegion(DIFFERENCE_WITH2);
1230     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT2);
1231 
1232     // 3. subtract rectangle out of this region
1233     region.set(region1);
1234     assertTrue(region.op(region2, region5, Region.Op.DIFFERENCE));
1235     verifyPointsInsideRegion(DIFFERENCE_WITH3);
1236     verifyPointsOutsideRegion(DIFFERENCE_WITHOUT3);
1237   }
1238 
verifyIntersectOp5( Region region1, Region region2, Region region3, Region region4, Region region5)1239   private void verifyIntersectOp5(
1240       Region region1, Region region2, Region region3, Region region4, Region region5) {
1241     // INTERSECT, Region with rectangle
1242     // intersect the two regions
1243     region = new Region();
1244     // intersect null rectangle
1245     region.set(region1);
1246     assertFalse(region.op(region2, region1, Region.Op.INTERSECT));
1247 
1248     // 1. intersect rectangle inside this region
1249     region.set(region1);
1250     assertTrue(region.op(region2, region3, Region.Op.INTERSECT));
1251     verifyPointsInsideRegion(INTERSECT_WITH1);
1252     verifyPointsOutsideRegion(INTERSECT_WITHOUT1);
1253 
1254     // 2. intersect rectangle overlap this region
1255     region.set(region1);
1256     assertTrue(region.op(region2, region4, Region.Op.INTERSECT));
1257     verifyPointsInsideRegion(INTERSECT_WITH2);
1258     verifyPointsOutsideRegion(INTERSECT_WITHOUT2);
1259 
1260     // 3. intersect rectangle out of this region
1261     region.set(region1);
1262     assertFalse(region.op(region2, region5, Region.Op.INTERSECT));
1263   }
1264 
verifyUnionOp5( Region region1, Region region2, Region region3, Region region4, Region region5)1265   private void verifyUnionOp5(
1266       Region region1, Region region2, Region region3, Region region4, Region region5) {
1267     // UNION, Region with rectangle
1268     // union (inclusive-or) the two regions
1269     region = new Region();
1270     // union null rectangle
1271     region.set(region1);
1272     assertTrue(region.op(region2, region1, Region.Op.UNION));
1273     assertTrue(region.contains(6, 6));
1274 
1275     // 1. union rectangle inside this region
1276     region.set(region1);
1277     assertTrue(region.op(region2, region3, Region.Op.UNION));
1278     verifyPointsInsideRegion(UNION_WITH1);
1279     verifyPointsOutsideRegion(UNION_WITHOUT1);
1280 
1281     // 2. union rectangle overlap this region
1282     region.set(region1);
1283     assertTrue(region.op(region2, region4, Region.Op.UNION));
1284     verifyPointsInsideRegion(UNION_WITH2);
1285     verifyPointsOutsideRegion(UNION_WITHOUT2);
1286 
1287     // 3. union rectangle out of this region
1288     region.set(region1);
1289     assertTrue(region.op(region2, region5, Region.Op.UNION));
1290     verifyPointsInsideRegion(UNION_WITH3);
1291     verifyPointsOutsideRegion(UNION_WITHOUT3);
1292   }
1293 
verifyXorOp5( Region region1, Region region2, Region region3, Region region4, Region region5)1294   private void verifyXorOp5(
1295       Region region1, Region region2, Region region3, Region region4, Region region5) {
1296     // XOR, Region with rectangle
1297     // exclusive-or the two regions
1298     region = new Region();
1299     // xor null rectangle
1300     region.set(region1);
1301     assertTrue(region.op(region2, region1, Region.Op.XOR));
1302 
1303     // 1. xor rectangle inside this region
1304     region.set(region1);
1305     assertTrue(region.op(region2, region3, Region.Op.XOR));
1306     verifyPointsInsideRegion(XOR_WITH1);
1307     verifyPointsOutsideRegion(XOR_WITHOUT1);
1308 
1309     // 2. xor rectangle overlap this region
1310     region.set(region1);
1311     assertTrue(region.op(region2, region4, Region.Op.XOR));
1312     verifyPointsInsideRegion(XOR_WITH2);
1313     verifyPointsOutsideRegion(XOR_WITHOUT2);
1314 
1315     // 3. xor rectangle out of this region
1316     region.set(region1);
1317     assertTrue(region.op(region2, region5, Region.Op.XOR));
1318     verifyPointsInsideRegion(XOR_WITH3);
1319     verifyPointsOutsideRegion(XOR_WITHOUT3);
1320   }
1321 
verifyReverseDifferenceOp5( Region region1, Region region2, Region region3, Region region4, Region region5)1322   private void verifyReverseDifferenceOp5(
1323       Region region1, Region region2, Region region3, Region region4, Region region5) {
1324     // REVERSE_DIFFERENCE, Region with rectangle
1325     // reverse difference the first region from the op region
1326     region = new Region();
1327     // reverse difference null rectangle
1328     region.set(region1);
1329     assertFalse(region.op(region2, region1, Region.Op.REVERSE_DIFFERENCE));
1330 
1331     // 1. reverse difference rectangle inside this region
1332     region.set(region1);
1333     assertFalse(region.op(region2, region3, Region.Op.REVERSE_DIFFERENCE));
1334 
1335     // 2. reverse difference rectangle overlap this region
1336     region.set(region1);
1337     assertTrue(region.op(region2, region4, Region.Op.REVERSE_DIFFERENCE));
1338     verifyPointsInsideRegion(REVERSE_DIFFERENCE_WITH2);
1339     verifyPointsOutsideRegion(REVERSE_DIFFERENCE_WITHOUT2);
1340 
1341     // 3. reverse difference rectangle out of this region
1342     region.set(region1);
1343     assertTrue(region.op(region2, region5, Region.Op.REVERSE_DIFFERENCE));
1344     verifyPointsInsideRegion(REVERSE_DIFFERENCE_WITH3);
1345     verifyPointsOutsideRegion(REVERSE_DIFFERENCE_WITHOUT3);
1346   }
1347 
verifyReplaceOp5( Region region1, Region region2, Region region3, Region region4, Region region5)1348   private void verifyReplaceOp5(
1349       Region region1, Region region2, Region region3, Region region4, Region region5) {
1350     // REPLACE, Region with rectangle
1351     // replace the dst region with the op region
1352     region = new Region();
1353     // subtract null rectangle
1354     region.set(region1);
1355     assertFalse(region.op(region2, region1, Region.Op.REPLACE));
1356     // subtract rectangle inside this region
1357     region.set(region1);
1358     assertTrue(region.op(region2, region3, Region.Op.REPLACE));
1359     assertNotSame(region2.getBounds(), region.getBounds());
1360     assertEquals(region3.getBounds(), region.getBounds());
1361     // subtract rectangle overlap this region
1362     region.set(region1);
1363     assertTrue(region.op(region2, region4, Region.Op.REPLACE));
1364     assertNotSame(region2.getBounds(), region.getBounds());
1365     assertEquals(region4.getBounds(), region.getBounds());
1366     // subtract rectangle out of this region
1367     region.set(region1);
1368     assertTrue(region.op(region2, region5, Region.Op.REPLACE));
1369     assertNotSame(region2.getBounds(), region.getBounds());
1370     assertEquals(region5.getBounds(), region.getBounds());
1371   }
1372 
1373   @Test
testGetBoundaryPath1()1374   public void testGetBoundaryPath1() {
1375     assertTrue(region.getBoundaryPath().isEmpty());
1376 
1377     // Both clip and path are non-null.
1378     Region clip = new Region(0, 0, 10, 10);
1379     Path path = new Path();
1380     path.addRect(0, 0, 10, 10, Path.Direction.CW);
1381     assertTrue(region.setPath(path, clip));
1382     assertFalse(region.getBoundaryPath().isEmpty());
1383   }
1384 
1385   @Test
testGetBoundaryPath2()1386   public void testGetBoundaryPath2() {
1387     Path path = new Path();
1388     assertFalse(region.getBoundaryPath(path));
1389 
1390     // path is null
1391     region = new Region(0, 0, 10, 10);
1392     path = new Path();
1393     assertTrue(region.getBoundaryPath(path));
1394 
1395     // region is null
1396     region = new Region();
1397     path = new Path();
1398     path.addRect(0, 0, 10, 10, Path.Direction.CW);
1399     assertFalse(region.getBoundaryPath(path));
1400 
1401     // both path and region are non-null
1402     region = new Region(0, 0, 10, 10);
1403     path = new Path();
1404     path.addRect(0, 0, 5, 5, Path.Direction.CW);
1405     assertTrue(region.getBoundaryPath(path));
1406   }
1407 
1408   @Test
testSetPath()1409   public void testSetPath() {
1410     // Both clip and path are null.
1411     Region clip = new Region();
1412     Path path = new Path();
1413     assertFalse(region.setPath(path, clip));
1414 
1415     // Only path is null.
1416     path = new Path();
1417     clip = new Region(0, 0, 10, 10);
1418     assertFalse(region.setPath(path, clip));
1419 
1420     // Only clip is null.
1421     clip = new Region();
1422     path = new Path();
1423     path.addRect(0, 0, 10, 10, Path.Direction.CW);
1424     assertFalse(region.setPath(path, clip));
1425 
1426     // Both clip and path are non-null.
1427     path = new Path();
1428     clip = new Region(0, 0, 10, 10);
1429     path.addRect(0, 0, 10, 10, Path.Direction.CW);
1430     assertTrue(region.setPath(path, clip));
1431 
1432     // Both clip and path are non-null.
1433     path = new Path();
1434     clip = new Region(0, 0, 5, 5);
1435     path.addRect(0, 0, 10, 10, Path.Direction.CW);
1436     assertTrue(region.setPath(path, clip));
1437     Rect expected = new Rect(0, 0, 5, 5);
1438     Rect unexpected = new Rect(0, 0, 10, 10);
1439     Rect actual = region.getBounds();
1440     assertEquals(expected.right, actual.right);
1441     assertNotSame(unexpected.right, actual.right);
1442 
1443     // Both clip and path are non-null.
1444     path = new Path();
1445     clip = new Region(0, 0, 10, 10);
1446     path.addRect(0, 0, 5, 5, Path.Direction.CW);
1447     assertTrue(region.setPath(path, clip));
1448     expected = new Rect(0, 0, 5, 5);
1449     unexpected = new Rect(0, 0, 10, 10);
1450     actual = region.getBounds();
1451     assertEquals(expected.right, actual.right);
1452     assertNotSame(unexpected.right, actual.right);
1453   }
1454 
1455   @Test
testTranslate1()1456   public void testTranslate1() {
1457     Rect rect1 = new Rect(0, 0, 20, 20);
1458     Rect rect2 = new Rect(10, 10, 30, 30);
1459     region = new Region(0, 0, 20, 20);
1460     region.translate(10, 10);
1461     assertNotSame(rect1, region.getBounds());
1462     assertEquals(rect2, region.getBounds());
1463   }
1464 
1465   @Test
testTranslate2()1466   public void testTranslate2() {
1467     Region dst = new Region();
1468     Rect rect1 = new Rect(0, 0, 20, 20);
1469     Rect rect2 = new Rect(10, 10, 30, 30);
1470     region = new Region(0, 0, 20, 20);
1471     region.translate(10, 10, dst);
1472     assertEquals(rect1, region.getBounds());
1473     assertNotSame(rect2, region.getBounds());
1474     assertNotSame(rect1, dst.getBounds());
1475     assertEquals(rect2, dst.getBounds());
1476   }
1477 
1478   @Test
testDescribeContents()1479   public void testDescribeContents() {
1480     int actual = region.describeContents();
1481     assertEquals(0, actual);
1482   }
1483 
1484   @Test
testQuickReject1()1485   public void testQuickReject1() {
1486     Rect oriRect = new Rect(0, 0, 20, 20);
1487     Rect rect1 = new Rect();
1488     Rect rect2 = new Rect(40, 40, 60, 60);
1489     Rect rect3 = new Rect(0, 0, 10, 10);
1490     Rect rect4 = new Rect(10, 10, 30, 30);
1491 
1492     // Return true if the region is empty
1493     assertTrue(region.quickReject(rect1));
1494     region.set(oriRect);
1495     assertTrue(region.quickReject(rect2));
1496     region.set(oriRect);
1497     assertFalse(region.quickReject(rect3));
1498     region.set(oriRect);
1499     assertFalse(region.quickReject(rect4));
1500   }
1501 
1502   @Test
testQuickReject2()1503   public void testQuickReject2() {
1504     // Return true if the region is empty
1505     assertTrue(region.quickReject(0, 0, 0, 0));
1506     region.set(0, 0, 20, 20);
1507     assertTrue(region.quickReject(40, 40, 60, 60));
1508     region.set(0, 0, 20, 20);
1509     assertFalse(region.quickReject(0, 0, 10, 10));
1510     region.set(0, 0, 20, 20);
1511     assertFalse(region.quickReject(10, 10, 30, 30));
1512   }
1513 
1514   @Test
testQuickReject3()1515   public void testQuickReject3() {
1516     Region oriRegion = new Region(0, 0, 20, 20);
1517     Region region1 = new Region();
1518     Region region2 = new Region(40, 40, 60, 60);
1519     Region region3 = new Region(0, 0, 10, 10);
1520     Region region4 = new Region(10, 10, 30, 30);
1521 
1522     // Return true if the region is empty
1523     assertTrue(region.quickReject(region1));
1524     region.set(oriRegion);
1525     assertTrue(region.quickReject(region2));
1526     region.set(oriRegion);
1527     assertFalse(region.quickReject(region3));
1528     region.set(oriRegion);
1529     assertFalse(region.quickReject(region4));
1530   }
1531 }
1532