114 return dim; 115 } 116 117 /** 118 * Adds the delta {@code dv} to the value {@code v} with 119 * appropriate clipping to the bounds of Integer resolution. 120 * If the answer would be greater than {@code Integer.MAX_VALUE} 121 * then {@code Integer.MAX_VALUE} is returned. 122 * If the answer would be less than {@code Integer.MIN_VALUE} 123 * then {@code Integer.MIN_VALUE} is returned. 124 * Otherwise the sum is returned. 125 */ 126 public static int clipAdd(int v, int dv) { 127 int newv = v + dv; 128 if ((newv > v) != (dv > 0)) { 129 newv = (dv < 0) ? Integer.MIN_VALUE : Integer.MAX_VALUE; 130 } 131 return newv; 132 } 133 134 protected Region(int lox, int loy, int hix, int hiy) { 135 this.lox = lox; 136 this.loy = loy; 137 this.hix = hix; 138 this.hiy = hiy; 139 } 140 141 /** 142 * Returns a Region object covering the pixels which would be 143 * touched by a fill or clip operation on a Graphics implementation 144 * on the specified Shape object under the optionally specified 145 * AffineTransform object. 146 * 147 * @param s a non-null Shape object specifying the geometry enclosing 148 * the pixels of interest 149 * @param at an optional <code>AffineTransform</code> to be applied to the 150 * coordinates as they are returned in the iteration, or 151 * <code>null</code> if untransformed coordinates are desired 152 */ 153 public static Region getInstance(Shape s, AffineTransform at) { 330 this.hiy = hiy; 331 } 332 333 /** 334 * Appends the list of spans returned from the indicated 335 * SpanIterator. Each span must be at a higher starting 336 * Y coordinate than the previous data or it must have a 337 * Y range equal to the highest Y band in the region and a 338 * higher X coordinate than any of the spans in that band. 339 */ 340 public void appendSpans(SpanIterator si) { 341 int[] box = new int[6]; 342 343 while (si.nextSpan(box)) { 344 appendSpan(box); 345 } 346 347 endRow(box); 348 calcBBox(); 349 } 350 351 /** 352 * Returns a Region object that represents the same list of 353 * rectangles as the current Region object, translated by 354 * the specified dx, dy translation factors. 355 */ 356 public Region getTranslatedRegion(int dx, int dy) { 357 if ((dx | dy) == 0) { 358 return this; 359 } 360 int tlox = lox + dx; 361 int tloy = loy + dy; 362 int thix = hix + dx; 363 int thiy = hiy + dy; 364 if ((tlox > lox) != (dx > 0) || 365 (tloy > loy) != (dy > 0) || 366 (thix > hix) != (dx > 0) || 367 (thiy > hiy) != (dy > 0)) 368 { 369 return getSafeTranslatedRegion(dx, dy); | 114 return dim; 115 } 116 117 /** 118 * Adds the delta {@code dv} to the value {@code v} with 119 * appropriate clipping to the bounds of Integer resolution. 120 * If the answer would be greater than {@code Integer.MAX_VALUE} 121 * then {@code Integer.MAX_VALUE} is returned. 122 * If the answer would be less than {@code Integer.MIN_VALUE} 123 * then {@code Integer.MIN_VALUE} is returned. 124 * Otherwise the sum is returned. 125 */ 126 public static int clipAdd(int v, int dv) { 127 int newv = v + dv; 128 if ((newv > v) != (dv > 0)) { 129 newv = (dv < 0) ? Integer.MIN_VALUE : Integer.MAX_VALUE; 130 } 131 return newv; 132 } 133 134 /** 135 * Multiply the scale factor {@code sv} and the value {@code v} with 136 * appropriate clipping to the bounds of Integer resolution. If the answer 137 * would be greater than {@code Integer.MAX_VALUE} then {@code 138 * Integer.MAX_VALUE} is returned. If the answer would be less than {@code 139 * Integer.MIN_VALUE} then {@code Integer.MIN_VALUE} is returned. Otherwise 140 * the multiplication is returned. 141 */ 142 public static int clipScale(final int v, final double sv) { 143 if (sv == 1.0) { 144 return v; 145 } 146 final double newv = v * sv; 147 if (newv < Integer.MIN_VALUE) { 148 return Integer.MIN_VALUE; 149 } 150 if (newv > Integer.MAX_VALUE) { 151 return Integer.MAX_VALUE; 152 } 153 return (int) Math.round(newv); 154 } 155 156 protected Region(int lox, int loy, int hix, int hiy) { 157 this.lox = lox; 158 this.loy = loy; 159 this.hix = hix; 160 this.hiy = hiy; 161 } 162 163 /** 164 * Returns a Region object covering the pixels which would be 165 * touched by a fill or clip operation on a Graphics implementation 166 * on the specified Shape object under the optionally specified 167 * AffineTransform object. 168 * 169 * @param s a non-null Shape object specifying the geometry enclosing 170 * the pixels of interest 171 * @param at an optional <code>AffineTransform</code> to be applied to the 172 * coordinates as they are returned in the iteration, or 173 * <code>null</code> if untransformed coordinates are desired 174 */ 175 public static Region getInstance(Shape s, AffineTransform at) { 352 this.hiy = hiy; 353 } 354 355 /** 356 * Appends the list of spans returned from the indicated 357 * SpanIterator. Each span must be at a higher starting 358 * Y coordinate than the previous data or it must have a 359 * Y range equal to the highest Y band in the region and a 360 * higher X coordinate than any of the spans in that band. 361 */ 362 public void appendSpans(SpanIterator si) { 363 int[] box = new int[6]; 364 365 while (si.nextSpan(box)) { 366 appendSpan(box); 367 } 368 369 endRow(box); 370 calcBBox(); 371 } 372 373 /** 374 * Returns a Region object that represents the same list of rectangles as 375 * the current Region object, scaled by the specified sx, sy factors. 376 */ 377 public Region getScaledRegion(final double sx, final double sy) { 378 if (sx == 0 || sy == 0 || this == EMPTY_REGION) { 379 return EMPTY_REGION; 380 } 381 if ((sx == 1.0 && sy == 1.0) || (this == WHOLE_REGION)) { 382 return this; 383 } 384 385 int tlox = clipScale(lox, sx); 386 int tloy = clipScale(loy, sy); 387 int thix = clipScale(hix, sx); 388 int thiy = clipScale(hiy, sy); 389 Region ret = new Region(tlox, tloy, thix, thiy); 390 int bands[] = this.bands; 391 if (bands != null) { 392 int end = endIndex; 393 int newbands[] = new int[end]; 394 int i = 0; // index for source bands 395 int j = 0; // index for translated newbands 396 int ncol; 397 while (i < end) { 398 int y1, y2; 399 newbands[j++] = y1 = clipScale(bands[i++], sy); 400 newbands[j++] = y2 = clipScale(bands[i++], sy); 401 newbands[j++] = ncol = bands[i++]; 402 int savej = j; 403 if (y1 < y2) { 404 while (--ncol >= 0) { 405 int x1 = clipScale(bands[i++], sx); 406 int x2 = clipScale(bands[i++], sx); 407 if (x1 < x2) { 408 newbands[j++] = x1; 409 newbands[j++] = x2; 410 } 411 } 412 } else { 413 i += ncol * 2; 414 } 415 // Did we get any non-empty bands in this row? 416 if (j > savej) { 417 newbands[savej-1] = (j - savej) / 2; 418 } else { 419 j = savej - 3; 420 } 421 } 422 if (j <= 5) { 423 if (j < 5) { 424 // No rows or bands were generated... 425 ret.lox = ret.loy = ret.hix = ret.hiy = 0; 426 } else { 427 // Only generated one single rect in the end... 428 ret.loy = newbands[0]; 429 ret.hiy = newbands[1]; 430 ret.lox = newbands[3]; 431 ret.hix = newbands[4]; 432 } 433 // ret.endIndex and ret.bands were never initialized... 434 // ret.endIndex = 0; 435 // ret.newbands = null; 436 } else { 437 // Generated multiple bands and/or multiple rows... 438 ret.endIndex = j; 439 ret.bands = newbands; 440 } 441 } 442 return ret; 443 } 444 445 446 /** 447 * Returns a Region object that represents the same list of 448 * rectangles as the current Region object, translated by 449 * the specified dx, dy translation factors. 450 */ 451 public Region getTranslatedRegion(int dx, int dy) { 452 if ((dx | dy) == 0) { 453 return this; 454 } 455 int tlox = lox + dx; 456 int tloy = loy + dy; 457 int thix = hix + dx; 458 int thiy = hiy + dy; 459 if ((tlox > lox) != (dx > 0) || 460 (tloy > loy) != (dy > 0) || 461 (thix > hix) != (dx > 0) || 462 (thiy > hiy) != (dy > 0)) 463 { 464 return getSafeTranslatedRegion(dx, dy); |