Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/java2d/pipe/RegionOps.java
38840 views
/*1* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test %W% %E%25* @bug 650487426* @summary This test verifies the operation (and performance) of the27* various CAG operations on the internal Region class.28* @run main RegionOps29*/3031import java.awt.Rectangle;32import java.awt.geom.Area;33import java.awt.geom.AffineTransform;34import java.awt.image.BufferedImage;35import java.util.Random;36import sun.java2d.pipe.Region;3738public class RegionOps {39public static final int DEFAULT_NUMREGIONS = 50;40public static final int DEFAULT_MINSUBRECTS = 1;41public static final int DEFAULT_MAXSUBRECTS = 10;4243public static final int MINCOORD = -20;44public static final int MAXCOORD = 20;4546public static boolean useArea;4748static int numops;49static int numErrors;50static Random rand = new Random();51static boolean skipCheck;52static boolean countErrors;5354static {55// Instantiating BufferedImage initializes sun.java2d56BufferedImage bimg =57new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);58}5960public static void usage(String error) {61if (error != null) {62System.err.println("Error: "+error);63}64System.err.println("Usage: java RegionOps "+65"[-regions N] [-rects M] "+66"[-[min|max]rects M] [-area]");67System.err.println(" "+68"[-add|union] [-sub|diff] "+69"[-int[ersect]] [-xor]");70System.err.println(" "+71"[-seed S] [-nocheck] [-count[errors]] [-help]");72System.exit((error != null) ? 1 : 0);73}7475public static void error(RectListImpl a, RectListImpl b, String problem) {76System.err.println("Operating on: "+a);77if (b != null) {78System.err.println("and: "+b);79}80if (countErrors) {81System.err.println(problem);82numErrors++;83} else {84throw new RuntimeException(problem);85}86}8788public static void main(String argv[]) {89int numregions = DEFAULT_NUMREGIONS;90int minsubrects = DEFAULT_MINSUBRECTS;91int maxsubrects = DEFAULT_MAXSUBRECTS;92boolean doUnion = false;93boolean doIntersect = false;94boolean doSubtract = false;95boolean doXor = false;9697for (int i = 0; i < argv.length; i++) {98String arg = argv[i];99if (arg.equalsIgnoreCase("-regions")) {100if (i+1 >= argv.length) {101usage("missing arg for -regions");102}103numregions = Integer.parseInt(argv[++i]);104} else if (arg.equalsIgnoreCase("-rects")) {105if (i+1 >= argv.length) {106usage("missing arg for -rects");107}108minsubrects = maxsubrects = Integer.parseInt(argv[++i]);109} else if (arg.equalsIgnoreCase("-minrects")) {110if (i+1 >= argv.length) {111usage("missing arg for -minrects");112}113minsubrects = Integer.parseInt(argv[++i]);114} else if (arg.equalsIgnoreCase("-maxrects")) {115if (i+1 >= argv.length) {116usage("missing arg for -maxrects");117}118maxsubrects = Integer.parseInt(argv[++i]);119} else if (arg.equalsIgnoreCase("-area")) {120useArea = true;121} else if (arg.equalsIgnoreCase("-add") ||122arg.equalsIgnoreCase("-union"))123{124doUnion = true;125} else if (arg.equalsIgnoreCase("-sub") ||126arg.equalsIgnoreCase("-diff"))127{128doSubtract = true;129} else if (arg.equalsIgnoreCase("-int") ||130arg.equalsIgnoreCase("-intersect"))131{132doIntersect = true;133} else if (arg.equalsIgnoreCase("-xor")) {134doXor = true;135} else if (arg.equalsIgnoreCase("-seed")) {136if (i+1 >= argv.length) {137usage("missing arg for -seed");138}139rand.setSeed(Long.decode(argv[++i]).longValue());140} else if (arg.equalsIgnoreCase("-nocheck")) {141skipCheck = true;142} else if (arg.equalsIgnoreCase("-count") ||143arg.equalsIgnoreCase("-counterrors"))144{145countErrors = true;146} else if (arg.equalsIgnoreCase("-help")) {147usage(null);148} else {149usage("Unknown argument: "+arg);150}151}152153if (maxsubrects < minsubrects) {154usage("maximum number of subrectangles less than minimum");155}156157if (minsubrects <= 0) {158usage("minimum number of subrectangles must be positive");159}160161if (!doUnion && !doSubtract && !doIntersect && !doXor) {162doUnion = doSubtract = doIntersect = doXor = true;163}164165long start = System.currentTimeMillis();166RectListImpl rlist[] = new RectListImpl[numregions];167int totalrects = 0;168for (int i = 0; i < rlist.length; i++) {169RectListImpl rli = RectListImpl.getInstance();170int numsubrects =171minsubrects + rand.nextInt(maxsubrects - minsubrects + 1);172for (int j = 0; j < numsubrects; j++) {173addRectTo(rli);174totalrects++;175}176rlist[i] = rli;177}178long end = System.currentTimeMillis();179System.out.println((end-start)+"ms to create "+180rlist.length+" regions containing "+181totalrects+" subrectangles");182183start = System.currentTimeMillis();184for (int i = 0; i < rlist.length; i++) {185RectListImpl a = rlist[i];186testTranslate(a);187for (int j = i; j < rlist.length; j++) {188RectListImpl b = rlist[j];189if (doUnion) testUnion(a, b);190if (doSubtract) testDifference(a, b);191if (doIntersect) testIntersection(a, b);192if (doXor) testExclusiveOr(a, b);193}194}195end = System.currentTimeMillis();196System.out.println(numops+" ops took "+(end-start)+"ms");197198if (numErrors > 0) {199throw new RuntimeException(numErrors+" errors encountered");200}201}202203public static void addRectTo(RectListImpl rli) {204int lox = MINCOORD + rand.nextInt(MAXCOORD - MINCOORD + 1);205int hix = MINCOORD + rand.nextInt(MAXCOORD - MINCOORD + 1);206int loy = MINCOORD + rand.nextInt(MAXCOORD - MINCOORD + 1);207int hiy = MINCOORD + rand.nextInt(MAXCOORD - MINCOORD + 1);208rli.addRect(lox, loy, hix, hiy);209}210211public static void checkEqual(RectListImpl a, RectListImpl b,212String optype)213{214if (a.hashCode() != b.hashCode()) {215error(a, b, "hashcode failed for "+optype);216}217if (!a.equals(b)) {218error(a, b, "equals failed for "+optype);219}220}221222public static void testTranslate(RectListImpl a) {223RectListImpl maxTrans =224a.getTranslation(Integer.MAX_VALUE, Integer.MAX_VALUE)225.getTranslation(Integer.MAX_VALUE, Integer.MAX_VALUE)226.getTranslation(Integer.MAX_VALUE, Integer.MAX_VALUE);227if (!maxTrans.checkTransEmpty()) {228error(maxTrans, null, "overflow translated RectList not empty");229}230RectListImpl minTrans =231a.getTranslation(Integer.MIN_VALUE, Integer.MIN_VALUE)232.getTranslation(Integer.MIN_VALUE, Integer.MIN_VALUE)233.getTranslation(Integer.MIN_VALUE, Integer.MIN_VALUE);234if (!minTrans.checkTransEmpty()) {235error(minTrans, null, "overflow translated RectList not empty");236}237testTranslate(a, Integer.MAX_VALUE, Integer.MAX_VALUE, false,238MINCOORD, 0, MINCOORD, 0);239testTranslate(a, Integer.MAX_VALUE, Integer.MIN_VALUE, false,240MINCOORD, 0, 0, MAXCOORD);241testTranslate(a, Integer.MIN_VALUE, Integer.MAX_VALUE, false,2420, MAXCOORD, MINCOORD, 0);243testTranslate(a, Integer.MIN_VALUE, Integer.MIN_VALUE, false,2440, MAXCOORD, 0, MAXCOORD);245for (int dy = -100; dy <= 100; dy += 50) {246for (int dx = -100; dx <= 100; dx += 50) {247testTranslate(a, dx, dy, true,248MINCOORD, MAXCOORD,249MINCOORD, MAXCOORD);250}251}252}253254public static void testTranslate(RectListImpl a, int dx, int dy,255boolean isNonDestructive,256int xmin, int xmax,257int ymin, int ymax)258{259RectListImpl theTrans = a.getTranslation(dx, dy); numops++;260if (skipCheck) return;261RectListImpl unTrans = theTrans.getTranslation(-dx, -dy);262if (isNonDestructive) checkEqual(a, unTrans, "Translate");263for (int x = xmin; x < xmax; x++) {264for (int y = ymin; y < ymax; y++) {265boolean inside = a.contains(x, y);266if (theTrans.contains(x+dx, y+dy) != inside) {267error(a, null, "translation failed for "+268dx+", "+dy+" at "+x+", "+y);269}270}271}272}273274public static void testUnion(RectListImpl a, RectListImpl b) {275RectListImpl aUb = a.getUnion(b); numops++;276RectListImpl bUa = b.getUnion(a); numops++;277if (skipCheck) return;278checkEqual(aUb, bUa, "Union");279testUnion(a, b, aUb);280testUnion(a, b, bUa);281}282283public static void testUnion(RectListImpl a, RectListImpl b,284RectListImpl theUnion)285{286for (int x = MINCOORD; x < MAXCOORD; x++) {287for (int y = MINCOORD; y < MAXCOORD; y++) {288boolean inside = (a.contains(x, y) || b.contains(x, y));289if (theUnion.contains(x, y) != inside) {290error(a, b, "union failed at "+x+", "+y);291}292}293}294}295296public static void testDifference(RectListImpl a, RectListImpl b) {297RectListImpl aDb = a.getDifference(b); numops++;298RectListImpl bDa = b.getDifference(a); numops++;299if (skipCheck) return;300// Note that difference is not commutative so we cannot check equals301// checkEqual(a, b, "Difference");302testDifference(a, b, aDb);303testDifference(b, a, bDa);304}305306public static void testDifference(RectListImpl a, RectListImpl b,307RectListImpl theDifference)308{309for (int x = MINCOORD; x < MAXCOORD; x++) {310for (int y = MINCOORD; y < MAXCOORD; y++) {311boolean inside = (a.contains(x, y) && !b.contains(x, y));312if (theDifference.contains(x, y) != inside) {313error(a, b, "difference failed at "+x+", "+y);314}315}316}317}318319public static void testIntersection(RectListImpl a, RectListImpl b) {320RectListImpl aIb = a.getIntersection(b); numops++;321RectListImpl bIa = b.getIntersection(a); numops++;322if (skipCheck) return;323checkEqual(aIb, bIa, "Intersection");324testIntersection(a, b, aIb);325testIntersection(a, b, bIa);326}327328public static void testIntersection(RectListImpl a, RectListImpl b,329RectListImpl theIntersection)330{331for (int x = MINCOORD; x < MAXCOORD; x++) {332for (int y = MINCOORD; y < MAXCOORD; y++) {333boolean inside = (a.contains(x, y) && b.contains(x, y));334if (theIntersection.contains(x, y) != inside) {335error(a, b, "intersection failed at "+x+", "+y);336}337}338}339}340341public static void testExclusiveOr(RectListImpl a, RectListImpl b) {342RectListImpl aXb = a.getExclusiveOr(b); numops++;343RectListImpl bXa = b.getExclusiveOr(a); numops++;344if (skipCheck) return;345checkEqual(aXb, bXa, "ExclusiveOr");346testExclusiveOr(a, b, aXb);347testExclusiveOr(a, b, bXa);348}349350public static void testExclusiveOr(RectListImpl a, RectListImpl b,351RectListImpl theExclusiveOr)352{353for (int x = MINCOORD; x < MAXCOORD; x++) {354for (int y = MINCOORD; y < MAXCOORD; y++) {355boolean inside = (a.contains(x, y) != b.contains(x, y));356if (theExclusiveOr.contains(x, y) != inside) {357error(a, b, "xor failed at "+x+", "+y);358}359}360}361}362363public abstract static class RectListImpl {364public static RectListImpl getInstance() {365if (useArea) {366return new AreaImpl();367} else {368return new RegionImpl();369}370}371372public abstract void addRect(int lox, int loy, int hix, int hiy);373374public abstract RectListImpl getTranslation(int dx, int dy);375376public abstract RectListImpl getIntersection(RectListImpl rli);377public abstract RectListImpl getExclusiveOr(RectListImpl rli);378public abstract RectListImpl getDifference(RectListImpl rli);379public abstract RectListImpl getUnion(RectListImpl rli);380381// Used for making sure that 3xMAX translates yields an empty region382public abstract boolean checkTransEmpty();383384public abstract boolean contains(int x, int y);385386public abstract int hashCode();387public abstract boolean equals(RectListImpl other);388}389390public static class AreaImpl extends RectListImpl {391Area theArea;392393public AreaImpl() {394}395396public AreaImpl(Area a) {397theArea = a;398}399400public void addRect(int lox, int loy, int hix, int hiy) {401Area a2 = new Area(new Rectangle(lox, loy, hix-lox, hiy-loy));402if (theArea == null) {403theArea = a2;404} else {405theArea.add(a2);406}407}408409public RectListImpl getTranslation(int dx, int dy) {410AffineTransform at = AffineTransform.getTranslateInstance(dx, dy);411return new AreaImpl(theArea.createTransformedArea(at));412}413414public RectListImpl getIntersection(RectListImpl rli) {415Area a2 = new Area(theArea);416a2.intersect(((AreaImpl) rli).theArea);417return new AreaImpl(a2);418}419420public RectListImpl getExclusiveOr(RectListImpl rli) {421Area a2 = new Area(theArea);422a2.exclusiveOr(((AreaImpl) rli).theArea);423return new AreaImpl(a2);424}425426public RectListImpl getDifference(RectListImpl rli) {427Area a2 = new Area(theArea);428a2.subtract(((AreaImpl) rli).theArea);429return new AreaImpl(a2);430}431432public RectListImpl getUnion(RectListImpl rli) {433Area a2 = new Area(theArea);434a2.add(((AreaImpl) rli).theArea);435return new AreaImpl(a2);436}437438// Used for making sure that 3xMAX translates yields an empty region439public boolean checkTransEmpty() {440// Area objects will actually survive 3 MAX translates so just441// pretend that it had the intended effect...442return true;443}444445public boolean contains(int x, int y) {446return theArea.contains(x, y);447}448449public int hashCode() {450// Area does not override hashCode...451return 0;452}453454public boolean equals(RectListImpl other) {455return theArea.equals(((AreaImpl) other).theArea);456}457458public String toString() {459return theArea.toString();460}461}462463public static class RegionImpl extends RectListImpl {464Region theRegion;465466public RegionImpl() {467}468469public RegionImpl(Region r) {470theRegion = r;471}472473public void addRect(int lox, int loy, int hix, int hiy) {474Region r2 = Region.getInstanceXYXY(lox, loy, hix, hiy);475if (theRegion == null) {476theRegion = r2;477} else {478theRegion = theRegion.getUnion(r2);479}480}481482public RectListImpl getTranslation(int dx, int dy) {483return new RegionImpl(theRegion.getTranslatedRegion(dx, dy));484}485486public RectListImpl getIntersection(RectListImpl rli) {487Region r2 = ((RegionImpl) rli).theRegion;488r2 = theRegion.getIntersection(r2);489return new RegionImpl(r2);490}491492public RectListImpl getExclusiveOr(RectListImpl rli) {493Region r2 = ((RegionImpl) rli).theRegion;494r2 = theRegion.getExclusiveOr(r2);495return new RegionImpl(r2);496}497498public RectListImpl getDifference(RectListImpl rli) {499Region r2 = ((RegionImpl) rli).theRegion;500r2 = theRegion.getDifference(r2);501return new RegionImpl(r2);502}503504public RectListImpl getUnion(RectListImpl rli) {505Region r2 = ((RegionImpl) rli).theRegion;506r2 = theRegion.getUnion(r2);507return new RegionImpl(r2);508}509510// Used for making sure that 3xMAX translates yields an empty region511public boolean checkTransEmpty() {512// Region objects should be empty after 3 MAX translates...513return theRegion.isEmpty();514}515516public boolean contains(int x, int y) {517return theRegion.contains(x, y);518}519520public int hashCode() {521return theRegion.hashCode();522}523524public boolean equals(RectListImpl other) {525return theRegion.equals(((RegionImpl) other).theRegion);526}527528public String toString() {529return theRegion.toString();530}531}532}533534535