jdk/test/sun/java2d/pipe/RegionOps.java
changeset 2451 597df8e1d786
child 8368 e05f09b8db21
equal deleted inserted replaced
1978:8b981ce05cd0 2451:597df8e1d786
       
     1 /*
       
     2  * @test %W% %E%
       
     3  * @bug 6504874
       
     4  * @summary This test verifies the operation (and performance) of the
       
     5  *          various CAG operations on the internal Region class.
       
     6  * @run main RegionOps
       
     7  */
       
     8 
       
     9 import java.awt.Rectangle;
       
    10 import java.awt.geom.Area;
       
    11 import java.awt.geom.AffineTransform;
       
    12 import java.awt.image.BufferedImage;
       
    13 import java.util.Random;
       
    14 import sun.java2d.pipe.Region;
       
    15 
       
    16 public class RegionOps {
       
    17     public static final int DEFAULT_NUMREGIONS = 50;
       
    18     public static final int DEFAULT_MINSUBRECTS = 1;
       
    19     public static final int DEFAULT_MAXSUBRECTS = 10;
       
    20 
       
    21     public static final int MINCOORD = -20;
       
    22     public static final int MAXCOORD = 20;
       
    23 
       
    24     public static boolean useArea;
       
    25 
       
    26     static int numops;
       
    27     static int numErrors;
       
    28     static Random rand = new Random();
       
    29     static boolean skipCheck;
       
    30     static boolean countErrors;
       
    31 
       
    32     static {
       
    33         // Instantiating BufferedImage initializes sun.java2d
       
    34         BufferedImage bimg =
       
    35             new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
       
    36     }
       
    37 
       
    38     public static void usage(String error) {
       
    39         if (error != null) {
       
    40             System.err.println("Error: "+error);
       
    41         }
       
    42         System.err.println("Usage: java RegionOps "+
       
    43                            "[-regions N] [-rects M] "+
       
    44                            "[-[min|max]rects M] [-area]");
       
    45         System.err.println("                      "+
       
    46                            "[-add|union] [-sub|diff] "+
       
    47                            "[-int[ersect]] [-xor]");
       
    48         System.err.println("                      "+
       
    49                            "[-seed S] [-nocheck] [-count[errors]] [-help]");
       
    50         System.exit((error != null) ? 1 : 0);
       
    51     }
       
    52 
       
    53     public static void error(RectListImpl a, RectListImpl b, String problem) {
       
    54         System.err.println("Operating on:  "+a);
       
    55         if (b != null) {
       
    56             System.err.println("and:  "+b);
       
    57         }
       
    58         if (countErrors) {
       
    59             System.err.println(problem);
       
    60             numErrors++;
       
    61         } else {
       
    62             throw new RuntimeException(problem);
       
    63         }
       
    64     }
       
    65 
       
    66     public static void main(String argv[]) {
       
    67         int numregions = DEFAULT_NUMREGIONS;
       
    68         int minsubrects = DEFAULT_MINSUBRECTS;
       
    69         int maxsubrects = DEFAULT_MAXSUBRECTS;
       
    70         boolean doUnion = false;
       
    71         boolean doIntersect = false;
       
    72         boolean doSubtract = false;
       
    73         boolean doXor = false;
       
    74 
       
    75         for (int i = 0; i < argv.length; i++) {
       
    76             String arg = argv[i];
       
    77             if (arg.equalsIgnoreCase("-regions")) {
       
    78                 if (i+1 >= argv.length) {
       
    79                     usage("missing arg for -regions");
       
    80                 }
       
    81                 numregions = Integer.parseInt(argv[++i]);
       
    82             } else if (arg.equalsIgnoreCase("-rects")) {
       
    83                 if (i+1 >= argv.length) {
       
    84                     usage("missing arg for -rects");
       
    85                 }
       
    86                 minsubrects = maxsubrects = Integer.parseInt(argv[++i]);
       
    87             } else if (arg.equalsIgnoreCase("-minrects")) {
       
    88                 if (i+1 >= argv.length) {
       
    89                     usage("missing arg for -minrects");
       
    90                 }
       
    91                 minsubrects = Integer.parseInt(argv[++i]);
       
    92             } else if (arg.equalsIgnoreCase("-maxrects")) {
       
    93                 if (i+1 >= argv.length) {
       
    94                     usage("missing arg for -maxrects");
       
    95                 }
       
    96                 maxsubrects = Integer.parseInt(argv[++i]);
       
    97             } else if (arg.equalsIgnoreCase("-area")) {
       
    98                 useArea = true;
       
    99             } else if (arg.equalsIgnoreCase("-add") ||
       
   100                        arg.equalsIgnoreCase("-union"))
       
   101             {
       
   102                 doUnion = true;
       
   103             } else if (arg.equalsIgnoreCase("-sub") ||
       
   104                        arg.equalsIgnoreCase("-diff"))
       
   105             {
       
   106                 doSubtract = true;
       
   107             } else if (arg.equalsIgnoreCase("-int") ||
       
   108                        arg.equalsIgnoreCase("-intersect"))
       
   109             {
       
   110                 doIntersect = true;
       
   111             } else if (arg.equalsIgnoreCase("-xor")) {
       
   112                 doXor = true;
       
   113             } else if (arg.equalsIgnoreCase("-seed")) {
       
   114                 if (i+1 >= argv.length) {
       
   115                     usage("missing arg for -seed");
       
   116                 }
       
   117                 rand.setSeed(Long.decode(argv[++i]).longValue());
       
   118             } else if (arg.equalsIgnoreCase("-nocheck")) {
       
   119                 skipCheck = true;
       
   120             } else if (arg.equalsIgnoreCase("-count") ||
       
   121                        arg.equalsIgnoreCase("-counterrors"))
       
   122             {
       
   123                 countErrors = true;
       
   124             } else if (arg.equalsIgnoreCase("-help")) {
       
   125                 usage(null);
       
   126             } else {
       
   127                 usage("Unknown argument: "+arg);
       
   128             }
       
   129         }
       
   130 
       
   131         if (maxsubrects < minsubrects) {
       
   132             usage("maximum number of subrectangles less than minimum");
       
   133         }
       
   134 
       
   135         if (minsubrects <= 0) {
       
   136             usage("minimum number of subrectangles must be positive");
       
   137         }
       
   138 
       
   139         if (!doUnion && !doSubtract && !doIntersect && !doXor) {
       
   140             doUnion = doSubtract = doIntersect = doXor = true;
       
   141         }
       
   142 
       
   143         long start = System.currentTimeMillis();
       
   144         RectListImpl rlist[] = new RectListImpl[numregions];
       
   145         int totalrects = 0;
       
   146         for (int i = 0; i < rlist.length; i++) {
       
   147             RectListImpl rli = RectListImpl.getInstance();
       
   148             int numsubrects =
       
   149                 minsubrects + rand.nextInt(maxsubrects - minsubrects + 1);
       
   150             for (int j = 0; j < numsubrects; j++) {
       
   151                 addRectTo(rli);
       
   152                 totalrects++;
       
   153             }
       
   154             rlist[i] = rli;
       
   155         }
       
   156         long end = System.currentTimeMillis();
       
   157         System.out.println((end-start)+"ms to create "+
       
   158                            rlist.length+" regions containing "+
       
   159                            totalrects+" subrectangles");
       
   160 
       
   161         start = System.currentTimeMillis();
       
   162         for (int i = 0; i < rlist.length; i++) {
       
   163             RectListImpl a = rlist[i];
       
   164             testTranslate(a);
       
   165             for (int j = i; j < rlist.length; j++) {
       
   166                 RectListImpl b = rlist[j];
       
   167                 if (doUnion) testUnion(a, b);
       
   168                 if (doSubtract) testDifference(a, b);
       
   169                 if (doIntersect) testIntersection(a, b);
       
   170                 if (doXor) testExclusiveOr(a, b);
       
   171             }
       
   172         }
       
   173         end = System.currentTimeMillis();
       
   174         System.out.println(numops+" ops took "+(end-start)+"ms");
       
   175 
       
   176         if (numErrors > 0) {
       
   177             throw new RuntimeException(numErrors+" errors encountered");
       
   178         }
       
   179     }
       
   180 
       
   181     public static void addRectTo(RectListImpl rli) {
       
   182         int lox = MINCOORD + rand.nextInt(MAXCOORD - MINCOORD + 1);
       
   183         int hix = MINCOORD + rand.nextInt(MAXCOORD - MINCOORD + 1);
       
   184         int loy = MINCOORD + rand.nextInt(MAXCOORD - MINCOORD + 1);
       
   185         int hiy = MINCOORD + rand.nextInt(MAXCOORD - MINCOORD + 1);
       
   186         rli.addRect(lox, loy, hix, hiy);
       
   187     }
       
   188 
       
   189     public static void checkEqual(RectListImpl a, RectListImpl b,
       
   190                                   String optype)
       
   191     {
       
   192         if (a.hashCode() != b.hashCode()) {
       
   193             error(a, b, "hashcode failed for "+optype);
       
   194         }
       
   195         if (!a.equals(b)) {
       
   196             error(a, b, "equals failed for "+optype);
       
   197         }
       
   198     }
       
   199 
       
   200     public static void testTranslate(RectListImpl a) {
       
   201         RectListImpl maxTrans =
       
   202             a.getTranslation(Integer.MAX_VALUE, Integer.MAX_VALUE)
       
   203             .getTranslation(Integer.MAX_VALUE, Integer.MAX_VALUE)
       
   204             .getTranslation(Integer.MAX_VALUE, Integer.MAX_VALUE);
       
   205         if (!maxTrans.checkTransEmpty()) {
       
   206             error(maxTrans, null, "overflow translated RectList not empty");
       
   207         }
       
   208         RectListImpl minTrans =
       
   209             a.getTranslation(Integer.MIN_VALUE, Integer.MIN_VALUE)
       
   210             .getTranslation(Integer.MIN_VALUE, Integer.MIN_VALUE)
       
   211             .getTranslation(Integer.MIN_VALUE, Integer.MIN_VALUE);
       
   212         if (!minTrans.checkTransEmpty()) {
       
   213             error(minTrans, null, "overflow translated RectList not empty");
       
   214         }
       
   215         testTranslate(a, Integer.MAX_VALUE, Integer.MAX_VALUE, false,
       
   216                       MINCOORD, 0, MINCOORD, 0);
       
   217         testTranslate(a, Integer.MAX_VALUE, Integer.MIN_VALUE, false,
       
   218                       MINCOORD, 0, 0, MAXCOORD);
       
   219         testTranslate(a, Integer.MIN_VALUE, Integer.MAX_VALUE, false,
       
   220                       0, MAXCOORD, MINCOORD, 0);
       
   221         testTranslate(a, Integer.MIN_VALUE, Integer.MIN_VALUE, false,
       
   222                       0, MAXCOORD, 0, MAXCOORD);
       
   223         for (int dy = -100; dy <= 100; dy += 50) {
       
   224             for (int dx = -100; dx <= 100; dx += 50) {
       
   225                 testTranslate(a, dx, dy, true,
       
   226                               MINCOORD, MAXCOORD,
       
   227                               MINCOORD, MAXCOORD);
       
   228             }
       
   229         }
       
   230     }
       
   231 
       
   232     public static void testTranslate(RectListImpl a, int dx, int dy,
       
   233                                      boolean isNonDestructive,
       
   234                                      int xmin, int xmax,
       
   235                                      int ymin, int ymax)
       
   236     {
       
   237         RectListImpl theTrans = a.getTranslation(dx, dy); numops++;
       
   238         if (skipCheck) return;
       
   239         RectListImpl unTrans = theTrans.getTranslation(-dx, -dy);
       
   240         if (isNonDestructive) checkEqual(a, unTrans, "Translate");
       
   241         for (int x = xmin; x < xmax; x++) {
       
   242             for (int y = ymin; y < ymax; y++) {
       
   243                 boolean inside = a.contains(x, y);
       
   244                 if (theTrans.contains(x+dx, y+dy) != inside) {
       
   245                     error(a, null, "translation failed for "+
       
   246                           dx+", "+dy+" at "+x+", "+y);
       
   247                 }
       
   248             }
       
   249         }
       
   250     }
       
   251 
       
   252     public static void testUnion(RectListImpl a, RectListImpl b) {
       
   253         RectListImpl aUb = a.getUnion(b); numops++;
       
   254         RectListImpl bUa = b.getUnion(a); numops++;
       
   255         if (skipCheck) return;
       
   256         checkEqual(aUb, bUa, "Union");
       
   257         testUnion(a, b, aUb);
       
   258         testUnion(a, b, bUa);
       
   259     }
       
   260 
       
   261     public static void testUnion(RectListImpl a, RectListImpl b,
       
   262                                  RectListImpl theUnion)
       
   263     {
       
   264         for (int x = MINCOORD; x < MAXCOORD; x++) {
       
   265             for (int y = MINCOORD; y < MAXCOORD; y++) {
       
   266                 boolean inside = (a.contains(x, y) || b.contains(x, y));
       
   267                 if (theUnion.contains(x, y) != inside) {
       
   268                     error(a, b, "union failed at "+x+", "+y);
       
   269                 }
       
   270             }
       
   271         }
       
   272     }
       
   273 
       
   274     public static void testDifference(RectListImpl a, RectListImpl b) {
       
   275         RectListImpl aDb = a.getDifference(b); numops++;
       
   276         RectListImpl bDa = b.getDifference(a); numops++;
       
   277         if (skipCheck) return;
       
   278         // Note that difference is not commutative so we cannot check equals
       
   279         // checkEqual(a, b, "Difference");
       
   280         testDifference(a, b, aDb);
       
   281         testDifference(b, a, bDa);
       
   282     }
       
   283 
       
   284     public static void testDifference(RectListImpl a, RectListImpl b,
       
   285                                       RectListImpl theDifference)
       
   286     {
       
   287         for (int x = MINCOORD; x < MAXCOORD; x++) {
       
   288             for (int y = MINCOORD; y < MAXCOORD; y++) {
       
   289                 boolean inside = (a.contains(x, y) && !b.contains(x, y));
       
   290                 if (theDifference.contains(x, y) != inside) {
       
   291                     error(a, b, "difference failed at "+x+", "+y);
       
   292                 }
       
   293             }
       
   294         }
       
   295     }
       
   296 
       
   297     public static void testIntersection(RectListImpl a, RectListImpl b) {
       
   298         RectListImpl aIb = a.getIntersection(b); numops++;
       
   299         RectListImpl bIa = b.getIntersection(a); numops++;
       
   300         if (skipCheck) return;
       
   301         checkEqual(aIb, bIa, "Intersection");
       
   302         testIntersection(a, b, aIb);
       
   303         testIntersection(a, b, bIa);
       
   304     }
       
   305 
       
   306     public static void testIntersection(RectListImpl a, RectListImpl b,
       
   307                                         RectListImpl theIntersection)
       
   308     {
       
   309         for (int x = MINCOORD; x < MAXCOORD; x++) {
       
   310             for (int y = MINCOORD; y < MAXCOORD; y++) {
       
   311                 boolean inside = (a.contains(x, y) && b.contains(x, y));
       
   312                 if (theIntersection.contains(x, y) != inside) {
       
   313                     error(a, b, "intersection failed at "+x+", "+y);
       
   314                 }
       
   315             }
       
   316         }
       
   317     }
       
   318 
       
   319     public static void testExclusiveOr(RectListImpl a, RectListImpl b) {
       
   320         RectListImpl aXb = a.getExclusiveOr(b); numops++;
       
   321         RectListImpl bXa = b.getExclusiveOr(a); numops++;
       
   322         if (skipCheck) return;
       
   323         checkEqual(aXb, bXa, "ExclusiveOr");
       
   324         testExclusiveOr(a, b, aXb);
       
   325         testExclusiveOr(a, b, bXa);
       
   326     }
       
   327 
       
   328     public static void testExclusiveOr(RectListImpl a, RectListImpl b,
       
   329                                        RectListImpl theExclusiveOr)
       
   330     {
       
   331         for (int x = MINCOORD; x < MAXCOORD; x++) {
       
   332             for (int y = MINCOORD; y < MAXCOORD; y++) {
       
   333                 boolean inside = (a.contains(x, y) != b.contains(x, y));
       
   334                 if (theExclusiveOr.contains(x, y) != inside) {
       
   335                     error(a, b, "xor failed at "+x+", "+y);
       
   336                 }
       
   337             }
       
   338         }
       
   339     }
       
   340 
       
   341     public abstract static class RectListImpl {
       
   342         public static RectListImpl getInstance() {
       
   343             if (useArea) {
       
   344                 return new AreaImpl();
       
   345             } else {
       
   346                 return new RegionImpl();
       
   347             }
       
   348         }
       
   349 
       
   350         public abstract void addRect(int lox, int loy, int hix, int hiy);
       
   351 
       
   352         public abstract RectListImpl getTranslation(int dx, int dy);
       
   353 
       
   354         public abstract RectListImpl getIntersection(RectListImpl rli);
       
   355         public abstract RectListImpl getExclusiveOr(RectListImpl rli);
       
   356         public abstract RectListImpl getDifference(RectListImpl rli);
       
   357         public abstract RectListImpl getUnion(RectListImpl rli);
       
   358 
       
   359         // Used for making sure that 3xMAX translates yields an empty region
       
   360         public abstract boolean checkTransEmpty();
       
   361 
       
   362         public abstract boolean contains(int x, int y);
       
   363 
       
   364         public abstract int hashCode();
       
   365         public abstract boolean equals(RectListImpl other);
       
   366     }
       
   367 
       
   368     public static class AreaImpl extends RectListImpl {
       
   369         Area theArea;
       
   370 
       
   371         public AreaImpl() {
       
   372         }
       
   373 
       
   374         public AreaImpl(Area a) {
       
   375             theArea = a;
       
   376         }
       
   377 
       
   378         public void addRect(int lox, int loy, int hix, int hiy) {
       
   379             Area a2 = new Area(new Rectangle(lox, loy, hix-lox, hiy-loy));
       
   380             if (theArea == null) {
       
   381                 theArea = a2;
       
   382             } else {
       
   383                 theArea.add(a2);
       
   384             }
       
   385         }
       
   386 
       
   387         public RectListImpl getTranslation(int dx, int dy) {
       
   388             AffineTransform at = AffineTransform.getTranslateInstance(dx, dy);
       
   389             return new AreaImpl(theArea.createTransformedArea(at));
       
   390         }
       
   391 
       
   392         public RectListImpl getIntersection(RectListImpl rli) {
       
   393             Area a2 = new Area(theArea);
       
   394             a2.intersect(((AreaImpl) rli).theArea);
       
   395             return new AreaImpl(a2);
       
   396         }
       
   397 
       
   398         public RectListImpl getExclusiveOr(RectListImpl rli) {
       
   399             Area a2 = new Area(theArea);
       
   400             a2.exclusiveOr(((AreaImpl) rli).theArea);
       
   401             return new AreaImpl(a2);
       
   402         }
       
   403 
       
   404         public RectListImpl getDifference(RectListImpl rli) {
       
   405             Area a2 = new Area(theArea);
       
   406             a2.subtract(((AreaImpl) rli).theArea);
       
   407             return new AreaImpl(a2);
       
   408         }
       
   409 
       
   410         public RectListImpl getUnion(RectListImpl rli) {
       
   411             Area a2 = new Area(theArea);
       
   412             a2.add(((AreaImpl) rli).theArea);
       
   413             return new AreaImpl(a2);
       
   414         }
       
   415 
       
   416         // Used for making sure that 3xMAX translates yields an empty region
       
   417         public boolean checkTransEmpty() {
       
   418             // Area objects will actually survive 3 MAX translates so just
       
   419             // pretend that it had the intended effect...
       
   420             return true;
       
   421         }
       
   422 
       
   423         public boolean contains(int x, int y) {
       
   424             return theArea.contains(x, y);
       
   425         }
       
   426 
       
   427         public int hashCode() {
       
   428             // Area does not override hashCode...
       
   429             return 0;
       
   430         }
       
   431 
       
   432         public boolean equals(RectListImpl other) {
       
   433             return theArea.equals(((AreaImpl) other).theArea);
       
   434         }
       
   435 
       
   436         public String toString() {
       
   437             return theArea.toString();
       
   438         }
       
   439     }
       
   440 
       
   441     public static class RegionImpl extends RectListImpl {
       
   442         Region theRegion;
       
   443 
       
   444         public RegionImpl() {
       
   445         }
       
   446 
       
   447         public RegionImpl(Region r) {
       
   448             theRegion = r;
       
   449         }
       
   450 
       
   451         public void addRect(int lox, int loy, int hix, int hiy) {
       
   452             Region r2 = Region.getInstanceXYXY(lox, loy, hix, hiy);
       
   453             if (theRegion == null) {
       
   454                 theRegion = r2;
       
   455             } else {
       
   456                 theRegion = theRegion.getUnion(r2);
       
   457             }
       
   458         }
       
   459 
       
   460         public RectListImpl getTranslation(int dx, int dy) {
       
   461             return new RegionImpl(theRegion.getTranslatedRegion(dx, dy));
       
   462         }
       
   463 
       
   464         public RectListImpl getIntersection(RectListImpl rli) {
       
   465             Region r2 = ((RegionImpl) rli).theRegion;
       
   466             r2 = theRegion.getIntersection(r2);
       
   467             return new RegionImpl(r2);
       
   468         }
       
   469 
       
   470         public RectListImpl getExclusiveOr(RectListImpl rli) {
       
   471             Region r2 = ((RegionImpl) rli).theRegion;
       
   472             r2 = theRegion.getExclusiveOr(r2);
       
   473             return new RegionImpl(r2);
       
   474         }
       
   475 
       
   476         public RectListImpl getDifference(RectListImpl rli) {
       
   477             Region r2 = ((RegionImpl) rli).theRegion;
       
   478             r2 = theRegion.getDifference(r2);
       
   479             return new RegionImpl(r2);
       
   480         }
       
   481 
       
   482         public RectListImpl getUnion(RectListImpl rli) {
       
   483             Region r2 = ((RegionImpl) rli).theRegion;
       
   484             r2 = theRegion.getUnion(r2);
       
   485             return new RegionImpl(r2);
       
   486         }
       
   487 
       
   488         // Used for making sure that 3xMAX translates yields an empty region
       
   489         public boolean checkTransEmpty() {
       
   490             // Region objects should be empty after 3 MAX translates...
       
   491             return theRegion.isEmpty();
       
   492         }
       
   493 
       
   494         public boolean contains(int x, int y) {
       
   495             return theRegion.contains(x, y);
       
   496         }
       
   497 
       
   498         public int hashCode() {
       
   499             return theRegion.hashCode();
       
   500         }
       
   501 
       
   502         public boolean equals(RectListImpl other) {
       
   503             return theRegion.equals(((RegionImpl) other).theRegion);
       
   504         }
       
   505 
       
   506         public String toString() {
       
   507             return theRegion.toString();
       
   508         }
       
   509     }
       
   510 }