< prev index next >

src/java.desktop/share/classes/sun/java2d/pipe/Region.java

Print this page




  87             Integer.MIN_VALUE,
  88             Integer.MIN_VALUE,
  89             Integer.MAX_VALUE,
  90             Integer.MAX_VALUE);
  91 
  92     int lox;
  93     int loy;
  94     int hix;
  95     int hiy;
  96 
  97     int endIndex;
  98     int[] bands;
  99 
 100     private static native void initIDs();
 101 
 102     static {
 103         initIDs();
 104     }
 105 
 106     /**
 107      * Adds the dimension <code>dim</code> to the coordinate
 108      * <code>start</code> with appropriate clipping.  If
 109      * <code>dim</code> is non-positive then the method returns
 110      * the start coordinate.  If the sum overflows an integer
 111      * data type then the method returns <code>Integer.MAX_VALUE</code>.
 112      */
 113     public static int dimAdd(int start, int dim) {
 114         if (dim <= 0) return start;
 115         if ((dim += start) < start) return Integer.MAX_VALUE;
 116         return dim;
 117     }
 118 
 119     /**
 120      * Adds the delta {@code dv} to the value {@code v} with
 121      * appropriate clipping to the bounds of Integer resolution.
 122      * If the answer would be greater than {@code Integer.MAX_VALUE}
 123      * then {@code Integer.MAX_VALUE} is returned.
 124      * If the answer would be less than {@code Integer.MIN_VALUE}
 125      * then {@code Integer.MIN_VALUE} is returned.
 126      * Otherwise the sum is returned.
 127      */
 128     public static int clipAdd(int v, int dv) {
 129         int newv = v + dv;
 130         if ((newv > v) != (dv > 0)) {
 131             newv = (dv < 0) ? Integer.MIN_VALUE : Integer.MAX_VALUE;


 162         this.hiy = hiy;
 163     }
 164 
 165     private Region(int lox, int loy, int hix, int hiy, int[] bands, int end) {
 166         this.lox = lox;
 167         this.loy = loy;
 168         this.hix = hix;
 169         this.hiy = hiy;
 170         this.bands = bands;
 171         this.endIndex = end;
 172     }
 173 
 174     /**
 175      * Returns a Region object covering the pixels which would be
 176      * touched by a fill or clip operation on a Graphics implementation
 177      * on the specified Shape object under the optionally specified
 178      * AffineTransform object.
 179      *
 180      * @param s a non-null Shape object specifying the geometry enclosing
 181      *          the pixels of interest
 182      * @param at an optional <code>AffineTransform</code> to be applied to the
 183      *          coordinates as they are returned in the iteration, or
 184      *          <code>null</code> if untransformed coordinates are desired
 185      */
 186     public static Region getInstance(Shape s, AffineTransform at) {
 187         return getInstance(WHOLE_REGION, false, s, at);
 188     }
 189 
 190     /**
 191      * Returns a Region object covering the pixels which would be
 192      * touched by a fill or clip operation on a Graphics implementation
 193      * on the specified Shape object under the optionally specified
 194      * AffineTransform object further restricted by the specified
 195      * device bounds.
 196      * <p>
 197      * Note that only the bounds of the specified Region are used to
 198      * restrict the resulting Region.
 199      * If devBounds is non-rectangular and clipping to the specific
 200      * bands of devBounds is needed, then an intersection of the
 201      * resulting Region with devBounds must be performed in a
 202      * subsequent step.
 203      *
 204      * @param devBounds a non-null Region specifying some bounds to
 205      *          clip the geometry to
 206      * @param s a non-null Shape object specifying the geometry enclosing
 207      *          the pixels of interest
 208      * @param at an optional <code>AffineTransform</code> to be applied to the
 209      *          coordinates as they are returned in the iteration, or
 210      *          <code>null</code> if untransformed coordinates are desired
 211      */
 212     public static Region getInstance(Region devBounds,
 213                                      Shape s, AffineTransform at)
 214     {
 215         return getInstance(devBounds, false, s, at);
 216     }
 217 
 218     /**
 219      * Returns a Region object covering the pixels which would be
 220      * touched by a fill or clip operation on a Graphics implementation
 221      * on the specified Shape object under the optionally specified
 222      * AffineTransform object further restricted by the specified
 223      * device bounds.
 224      * If the normalize parameter is true then coordinate normalization
 225      * is performed as per the 2D Graphics non-antialiasing implementation
 226      * of the VALUE_STROKE_NORMALIZE hint.
 227      * <p>
 228      * Note that only the bounds of the specified Region are used to
 229      * restrict the resulting Region.
 230      * If devBounds is non-rectangular and clipping to the specific
 231      * bands of devBounds is needed, then an intersection of the
 232      * resulting Region with devBounds must be performed in a
 233      * subsequent step.
 234      *
 235      * @param devBounds a non-null Region specifying some bounds to
 236      *          clip the geometry to
 237      * @param normalize a boolean indicating whether or not to apply
 238      *          normalization
 239      * @param s a non-null Shape object specifying the geometry enclosing
 240      *          the pixels of interest
 241      * @param at an optional <code>AffineTransform</code> to be applied to the
 242      *          coordinates as they are returned in the iteration, or
 243      *          <code>null</code> if untransformed coordinates are desired
 244      */
 245     public static Region getInstance(Region devBounds, boolean normalize,
 246                                      Shape s, AffineTransform at)
 247     {
 248         // Optimize for empty shapes to avoid involving the SpanIterator
 249         if (s instanceof RectangularShape &&
 250                 ((RectangularShape)s).isEmpty())
 251         {
 252             return EMPTY_REGION;
 253         }
 254 
 255         int box[] = new int[4];
 256         ShapeSpanIterator sr = new ShapeSpanIterator(normalize);
 257         try {
 258             sr.setOutputArea(devBounds);
 259             sr.appendPath(s.getPathIterator(at));
 260             sr.getPathBox(box);
 261             Region r = Region.getInstance(box);
 262             r.appendSpans(sr);
 263             return r;


 346      */
 347     public static Region getInstanceXYXY(int lox, int loy, int hix, int hiy) {
 348         return new Region(lox, loy, hix, hiy);
 349     }
 350 
 351     /**
 352      * Sets the rectangle of interest for storing and returning
 353      * region bands.
 354      * <p>
 355      * This method can also be used to initialize a simple rectangular
 356      * region.
 357      */
 358     public void setOutputArea(Rectangle r) {
 359         setOutputAreaXYWH(r.x, r.y, r.width, r.height);
 360     }
 361 
 362     /**
 363      * Sets the rectangle of interest for storing and returning
 364      * region bands.  The rectangle is specified in x, y, width, height
 365      * format and appropriate clipping is performed as per the method
 366      * <code>dimAdd</code>.
 367      * <p>
 368      * This method can also be used to initialize a simple rectangular
 369      * region.
 370      */
 371     public void setOutputAreaXYWH(int x, int y, int w, int h) {
 372         setOutputAreaXYXY(x, y, dimAdd(x, w), dimAdd(y, h));
 373     }
 374 
 375     /**
 376      * Sets the rectangle of interest for storing and returning
 377      * region bands.  The rectangle is specified as a span array.
 378      * <p>
 379      * This method can also be used to initialize a simple rectangular
 380      * region.
 381      */
 382     public void setOutputArea(int box[]) {
 383         this.lox = box[0];
 384         this.loy = box[1];
 385         this.hix = box[2];
 386         this.hiy = box[3];


 620      */
 621     public Region getIntersectionXYXY(int lox, int loy, int hix, int hiy) {
 622         if (isInsideXYXY(lox, loy, hix, hiy)) {
 623             return this;
 624         }
 625         Region ret = new Region((lox < this.lox) ? this.lox : lox,
 626                                 (loy < this.loy) ? this.loy : loy,
 627                                 (hix > this.hix) ? this.hix : hix,
 628                                 (hiy > this.hiy) ? this.hiy : hiy);
 629         if (bands != null) {
 630             ret.appendSpans(this.getSpanIterator());
 631         }
 632         return ret;
 633     }
 634 
 635     /**
 636      * Returns a Region object that represents the intersection of this
 637      * object with the specified Region object.
 638      * <p>
 639      * If {@code A} and {@code B} are both Region Objects and
 640      * <code>C = A.getIntersection(B);</code> then a point will
 641      * be contained in {@code C} iff it is contained in both
 642      * {@code A} and {@code B}.
 643      * <p>
 644      * The return value may be this same object or the argument
 645      * Region object if no clipping occurs.
 646      */
 647     public Region getIntersection(Region r) {
 648         if (this.isInsideQuickCheck(r)) {
 649             return this;
 650         }
 651         if (r.isInsideQuickCheck(this)) {
 652             return r;
 653         }
 654         Region ret = new Region((r.lox < this.lox) ? this.lox : r.lox,
 655                                 (r.loy < this.loy) ? this.loy : r.loy,
 656                                 (r.hix > this.hix) ? this.hix : r.hix,
 657                                 (r.hiy > this.hiy) ? this.hiy : r.hiy);
 658         if (!ret.isEmpty()) {
 659             ret.filterSpans(this, r, INCLUDE_COMMON);
 660         }
 661         return ret;
 662     }
 663 
 664     /**
 665      * Returns a Region object that represents the union of this
 666      * object with the specified Region object.
 667      * <p>
 668      * If {@code A} and {@code B} are both Region Objects and
 669      * <code>C = A.getUnion(B);</code> then a point will
 670      * be contained in {@code C} iff it is contained in either
 671      * {@code A} or {@code B}.
 672      * <p>
 673      * The return value may be this same object or the argument
 674      * Region object if no augmentation occurs.
 675      */
 676     public Region getUnion(Region r) {
 677         if (r.isEmpty() || r.isInsideQuickCheck(this)) {
 678             return this;
 679         }
 680         if (this.isEmpty() || this.isInsideQuickCheck(r)) {
 681             return r;
 682         }
 683         Region ret = new Region((r.lox > this.lox) ? this.lox : r.lox,
 684                                 (r.loy > this.loy) ? this.loy : r.loy,
 685                                 (r.hix < this.hix) ? this.hix : r.hix,
 686                                 (r.hiy < this.hiy) ? this.hiy : r.hiy);
 687         ret.filterSpans(this, r, INCLUDE_A | INCLUDE_B | INCLUDE_COMMON);
 688         return ret;
 689     }
 690 
 691     /**
 692      * Returns a Region object that represents the difference of the
 693      * specified Region object subtracted from this object.
 694      * <p>
 695      * If {@code A} and {@code B} are both Region Objects and
 696      * <code>C = A.getDifference(B);</code> then a point will
 697      * be contained in {@code C} iff it is contained in
 698      * {@code A} but not contained in {@code B}.
 699      * <p>
 700      * The return value may be this same object or the argument
 701      * Region object if no clipping occurs.
 702      */
 703     public Region getDifference(Region r) {
 704         if (!r.intersectsQuickCheck(this)) {
 705             return this;
 706         }
 707         if (this.isInsideQuickCheck(r)) {
 708             return EMPTY_REGION;
 709         }
 710         Region ret = new Region(this.lox, this.loy, this.hix, this.hiy);
 711         ret.filterSpans(this, r, INCLUDE_A);
 712         return ret;
 713     }
 714 
 715     /**
 716      * Returns a Region object that represents the exclusive or of this
 717      * object with the specified Region object.
 718      * <p>
 719      * If {@code A} and {@code B} are both Region Objects and
 720      * <code>C = A.getExclusiveOr(B);</code> then a point will
 721      * be contained in {@code C} iff it is contained in either
 722      * {@code A} or {@code B}, but not if it is contained in both.
 723      * <p>
 724      * The return value may be this same object or the argument
 725      * Region object if either is empty.
 726      */
 727     public Region getExclusiveOr(Region r) {
 728         if (r.isEmpty()) {
 729             return this;
 730         }
 731         if (this.isEmpty()) {
 732             return r;
 733         }
 734         Region ret = new Region((r.lox > this.lox) ? this.lox : r.lox,
 735                                 (r.loy > this.loy) ? this.loy : r.loy,
 736                                 (r.hix < this.hix) ? this.hix : r.hix,
 737                                 (r.hiy < this.hiy) ? this.hiy : r.hiy);
 738         ret.filterSpans(this, r, INCLUDE_A | INCLUDE_B);
 739         return ret;
 740     }




  87             Integer.MIN_VALUE,
  88             Integer.MIN_VALUE,
  89             Integer.MAX_VALUE,
  90             Integer.MAX_VALUE);
  91 
  92     int lox;
  93     int loy;
  94     int hix;
  95     int hiy;
  96 
  97     int endIndex;
  98     int[] bands;
  99 
 100     private static native void initIDs();
 101 
 102     static {
 103         initIDs();
 104     }
 105 
 106     /**
 107      * Adds the dimension {@code dim} to the coordinate
 108      * {@code start} with appropriate clipping.  If
 109      * {@code dim} is non-positive then the method returns
 110      * the start coordinate.  If the sum overflows an integer
 111      * data type then the method returns {@code Integer.MAX_VALUE}.
 112      */
 113     public static int dimAdd(int start, int dim) {
 114         if (dim <= 0) return start;
 115         if ((dim += start) < start) return Integer.MAX_VALUE;
 116         return dim;
 117     }
 118 
 119     /**
 120      * Adds the delta {@code dv} to the value {@code v} with
 121      * appropriate clipping to the bounds of Integer resolution.
 122      * If the answer would be greater than {@code Integer.MAX_VALUE}
 123      * then {@code Integer.MAX_VALUE} is returned.
 124      * If the answer would be less than {@code Integer.MIN_VALUE}
 125      * then {@code Integer.MIN_VALUE} is returned.
 126      * Otherwise the sum is returned.
 127      */
 128     public static int clipAdd(int v, int dv) {
 129         int newv = v + dv;
 130         if ((newv > v) != (dv > 0)) {
 131             newv = (dv < 0) ? Integer.MIN_VALUE : Integer.MAX_VALUE;


 162         this.hiy = hiy;
 163     }
 164 
 165     private Region(int lox, int loy, int hix, int hiy, int[] bands, int end) {
 166         this.lox = lox;
 167         this.loy = loy;
 168         this.hix = hix;
 169         this.hiy = hiy;
 170         this.bands = bands;
 171         this.endIndex = end;
 172     }
 173 
 174     /**
 175      * Returns a Region object covering the pixels which would be
 176      * touched by a fill or clip operation on a Graphics implementation
 177      * on the specified Shape object under the optionally specified
 178      * AffineTransform object.
 179      *
 180      * @param s a non-null Shape object specifying the geometry enclosing
 181      *          the pixels of interest
 182      * @param at an optional {@code AffineTransform} to be applied to the
 183      *          coordinates as they are returned in the iteration, or
 184      *          {@code null} if untransformed coordinates are desired
 185      */
 186     public static Region getInstance(Shape s, AffineTransform at) {
 187         return getInstance(WHOLE_REGION, false, s, at);
 188     }
 189 
 190     /**
 191      * Returns a Region object covering the pixels which would be
 192      * touched by a fill or clip operation on a Graphics implementation
 193      * on the specified Shape object under the optionally specified
 194      * AffineTransform object further restricted by the specified
 195      * device bounds.
 196      * <p>
 197      * Note that only the bounds of the specified Region are used to
 198      * restrict the resulting Region.
 199      * If devBounds is non-rectangular and clipping to the specific
 200      * bands of devBounds is needed, then an intersection of the
 201      * resulting Region with devBounds must be performed in a
 202      * subsequent step.
 203      *
 204      * @param devBounds a non-null Region specifying some bounds to
 205      *          clip the geometry to
 206      * @param s a non-null Shape object specifying the geometry enclosing
 207      *          the pixels of interest
 208      * @param at an optional {@code AffineTransform} to be applied to the
 209      *          coordinates as they are returned in the iteration, or
 210      *          {@code null} if untransformed coordinates are desired
 211      */
 212     public static Region getInstance(Region devBounds,
 213                                      Shape s, AffineTransform at)
 214     {
 215         return getInstance(devBounds, false, s, at);
 216     }
 217 
 218     /**
 219      * Returns a Region object covering the pixels which would be
 220      * touched by a fill or clip operation on a Graphics implementation
 221      * on the specified Shape object under the optionally specified
 222      * AffineTransform object further restricted by the specified
 223      * device bounds.
 224      * If the normalize parameter is true then coordinate normalization
 225      * is performed as per the 2D Graphics non-antialiasing implementation
 226      * of the VALUE_STROKE_NORMALIZE hint.
 227      * <p>
 228      * Note that only the bounds of the specified Region are used to
 229      * restrict the resulting Region.
 230      * If devBounds is non-rectangular and clipping to the specific
 231      * bands of devBounds is needed, then an intersection of the
 232      * resulting Region with devBounds must be performed in a
 233      * subsequent step.
 234      *
 235      * @param devBounds a non-null Region specifying some bounds to
 236      *          clip the geometry to
 237      * @param normalize a boolean indicating whether or not to apply
 238      *          normalization
 239      * @param s a non-null Shape object specifying the geometry enclosing
 240      *          the pixels of interest
 241      * @param at an optional {@code AffineTransform} to be applied to the
 242      *          coordinates as they are returned in the iteration, or
 243      *          {@code null} if untransformed coordinates are desired
 244      */
 245     public static Region getInstance(Region devBounds, boolean normalize,
 246                                      Shape s, AffineTransform at)
 247     {
 248         // Optimize for empty shapes to avoid involving the SpanIterator
 249         if (s instanceof RectangularShape &&
 250                 ((RectangularShape)s).isEmpty())
 251         {
 252             return EMPTY_REGION;
 253         }
 254 
 255         int box[] = new int[4];
 256         ShapeSpanIterator sr = new ShapeSpanIterator(normalize);
 257         try {
 258             sr.setOutputArea(devBounds);
 259             sr.appendPath(s.getPathIterator(at));
 260             sr.getPathBox(box);
 261             Region r = Region.getInstance(box);
 262             r.appendSpans(sr);
 263             return r;


 346      */
 347     public static Region getInstanceXYXY(int lox, int loy, int hix, int hiy) {
 348         return new Region(lox, loy, hix, hiy);
 349     }
 350 
 351     /**
 352      * Sets the rectangle of interest for storing and returning
 353      * region bands.
 354      * <p>
 355      * This method can also be used to initialize a simple rectangular
 356      * region.
 357      */
 358     public void setOutputArea(Rectangle r) {
 359         setOutputAreaXYWH(r.x, r.y, r.width, r.height);
 360     }
 361 
 362     /**
 363      * Sets the rectangle of interest for storing and returning
 364      * region bands.  The rectangle is specified in x, y, width, height
 365      * format and appropriate clipping is performed as per the method
 366      * {@code dimAdd}.
 367      * <p>
 368      * This method can also be used to initialize a simple rectangular
 369      * region.
 370      */
 371     public void setOutputAreaXYWH(int x, int y, int w, int h) {
 372         setOutputAreaXYXY(x, y, dimAdd(x, w), dimAdd(y, h));
 373     }
 374 
 375     /**
 376      * Sets the rectangle of interest for storing and returning
 377      * region bands.  The rectangle is specified as a span array.
 378      * <p>
 379      * This method can also be used to initialize a simple rectangular
 380      * region.
 381      */
 382     public void setOutputArea(int box[]) {
 383         this.lox = box[0];
 384         this.loy = box[1];
 385         this.hix = box[2];
 386         this.hiy = box[3];


 620      */
 621     public Region getIntersectionXYXY(int lox, int loy, int hix, int hiy) {
 622         if (isInsideXYXY(lox, loy, hix, hiy)) {
 623             return this;
 624         }
 625         Region ret = new Region((lox < this.lox) ? this.lox : lox,
 626                                 (loy < this.loy) ? this.loy : loy,
 627                                 (hix > this.hix) ? this.hix : hix,
 628                                 (hiy > this.hiy) ? this.hiy : hiy);
 629         if (bands != null) {
 630             ret.appendSpans(this.getSpanIterator());
 631         }
 632         return ret;
 633     }
 634 
 635     /**
 636      * Returns a Region object that represents the intersection of this
 637      * object with the specified Region object.
 638      * <p>
 639      * If {@code A} and {@code B} are both Region Objects and
 640      * {@code C = A.getIntersection(B);} then a point will
 641      * be contained in {@code C} iff it is contained in both
 642      * {@code A} and {@code B}.
 643      * <p>
 644      * The return value may be this same object or the argument
 645      * Region object if no clipping occurs.
 646      */
 647     public Region getIntersection(Region r) {
 648         if (this.isInsideQuickCheck(r)) {
 649             return this;
 650         }
 651         if (r.isInsideQuickCheck(this)) {
 652             return r;
 653         }
 654         Region ret = new Region((r.lox < this.lox) ? this.lox : r.lox,
 655                                 (r.loy < this.loy) ? this.loy : r.loy,
 656                                 (r.hix > this.hix) ? this.hix : r.hix,
 657                                 (r.hiy > this.hiy) ? this.hiy : r.hiy);
 658         if (!ret.isEmpty()) {
 659             ret.filterSpans(this, r, INCLUDE_COMMON);
 660         }
 661         return ret;
 662     }
 663 
 664     /**
 665      * Returns a Region object that represents the union of this
 666      * object with the specified Region object.
 667      * <p>
 668      * If {@code A} and {@code B} are both Region Objects and
 669      * {@code C = A.getUnion(B);} then a point will
 670      * be contained in {@code C} iff it is contained in either
 671      * {@code A} or {@code B}.
 672      * <p>
 673      * The return value may be this same object or the argument
 674      * Region object if no augmentation occurs.
 675      */
 676     public Region getUnion(Region r) {
 677         if (r.isEmpty() || r.isInsideQuickCheck(this)) {
 678             return this;
 679         }
 680         if (this.isEmpty() || this.isInsideQuickCheck(r)) {
 681             return r;
 682         }
 683         Region ret = new Region((r.lox > this.lox) ? this.lox : r.lox,
 684                                 (r.loy > this.loy) ? this.loy : r.loy,
 685                                 (r.hix < this.hix) ? this.hix : r.hix,
 686                                 (r.hiy < this.hiy) ? this.hiy : r.hiy);
 687         ret.filterSpans(this, r, INCLUDE_A | INCLUDE_B | INCLUDE_COMMON);
 688         return ret;
 689     }
 690 
 691     /**
 692      * Returns a Region object that represents the difference of the
 693      * specified Region object subtracted from this object.
 694      * <p>
 695      * If {@code A} and {@code B} are both Region Objects and
 696      * {@code C = A.getDifference(B);} then a point will
 697      * be contained in {@code C} iff it is contained in
 698      * {@code A} but not contained in {@code B}.
 699      * <p>
 700      * The return value may be this same object or the argument
 701      * Region object if no clipping occurs.
 702      */
 703     public Region getDifference(Region r) {
 704         if (!r.intersectsQuickCheck(this)) {
 705             return this;
 706         }
 707         if (this.isInsideQuickCheck(r)) {
 708             return EMPTY_REGION;
 709         }
 710         Region ret = new Region(this.lox, this.loy, this.hix, this.hiy);
 711         ret.filterSpans(this, r, INCLUDE_A);
 712         return ret;
 713     }
 714 
 715     /**
 716      * Returns a Region object that represents the exclusive or of this
 717      * object with the specified Region object.
 718      * <p>
 719      * If {@code A} and {@code B} are both Region Objects and
 720      * {@code C = A.getExclusiveOr(B);} then a point will
 721      * be contained in {@code C} iff it is contained in either
 722      * {@code A} or {@code B}, but not if it is contained in both.
 723      * <p>
 724      * The return value may be this same object or the argument
 725      * Region object if either is empty.
 726      */
 727     public Region getExclusiveOr(Region r) {
 728         if (r.isEmpty()) {
 729             return this;
 730         }
 731         if (this.isEmpty()) {
 732             return r;
 733         }
 734         Region ret = new Region((r.lox > this.lox) ? this.lox : r.lox,
 735                                 (r.loy > this.loy) ? this.loy : r.loy,
 736                                 (r.hix < this.hix) ? this.hix : r.hix,
 737                                 (r.hiy < this.hiy) ? this.hiy : r.hiy);
 738         ret.filterSpans(this, r, INCLUDE_A | INCLUDE_B);
 739         return ret;
 740     }


< prev index next >