1 7 8 package java.awt.geom; 9 10 import java.awt.Shape ; 11 import sun.awt.geom.Curve; 12 import sun.awt.geom.Crossings; 13 14 38 public final class GeneralPath implements Shape , Cloneable { 39 43 public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD; 44 45 49 public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO; 50 51 private static final byte SEG_MOVETO = (byte) PathIterator.SEG_MOVETO; 54 private static final byte SEG_LINETO = (byte) PathIterator.SEG_LINETO; 55 private static final byte SEG_QUADTO = (byte) PathIterator.SEG_QUADTO; 56 private static final byte SEG_CUBICTO = (byte) PathIterator.SEG_CUBICTO; 57 private static final byte SEG_CLOSE = (byte) PathIterator.SEG_CLOSE; 58 59 byte[] pointTypes; 60 float[] pointCoords; 61 int numTypes; 62 int numCoords; 63 int windingRule; 64 65 static final int INIT_SIZE = 20; 66 static final int EXPAND_MAX = 500; 67 68 75 public GeneralPath() { 76 this(WIND_NON_ZERO, INIT_SIZE, INIT_SIZE); 77 } 78 79 87 public GeneralPath(int rule) { 88 this(rule, INIT_SIZE, INIT_SIZE); 89 } 90 91 103 public GeneralPath(int rule, int initialCapacity) { 104 this(rule, initialCapacity, initialCapacity); 105 } 106 107 122 GeneralPath(int rule, int initialTypes, int initialCoords) { 123 setWindingRule(rule); 124 pointTypes = new byte[initialTypes]; 125 pointCoords = new float[initialCoords * 2]; 126 } 127 128 135 public GeneralPath(Shape s) { 136 this(WIND_NON_ZERO, INIT_SIZE, INIT_SIZE); 137 PathIterator pi = s.getPathIterator(null); 138 setWindingRule(pi.getWindingRule()); 139 append(pi, false); 140 } 141 142 private void needRoom(int newTypes, int newCoords, boolean needMove) { 143 if (needMove && numTypes == 0) { 144 throw new IllegalPathStateException ("missing initial moveto "+ 145 "in path definition"); 146 } 147 int size = pointCoords.length; 148 if (numCoords + newCoords > size) { 149 int grow = size; 150 if (grow > EXPAND_MAX * 2) { 151 grow = EXPAND_MAX * 2; 152 } 153 if (grow < newCoords) { 154 grow = newCoords; 155 } 156 float[] arr = new float[size + grow]; 157 System.arraycopy(pointCoords, 0, arr, 0, numCoords); 158 pointCoords = arr; 159 } 160 size = pointTypes.length; 161 if (numTypes + newTypes > size) { 162 int grow = size; 163 if (grow > EXPAND_MAX) { 164 grow = EXPAND_MAX; 165 } 166 if (grow < newTypes) { 167 grow = newTypes; 168 } 169 byte[] arr = new byte[size + grow]; 170 System.arraycopy(pointTypes, 0, arr, 0, numTypes); 171 pointTypes = arr; 172 } 173 } 174 175 180 public synchronized void moveTo(float x, float y) { 181 if (numTypes > 0 && pointTypes[numTypes - 1] == SEG_MOVETO) { 182 pointCoords[numCoords - 2] = x; 183 pointCoords[numCoords - 1] = y; 184 } else { 185 needRoom(1, 2, false); 186 pointTypes[numTypes++] = SEG_MOVETO; 187 pointCoords[numCoords++] = x; 188 pointCoords[numCoords++] = y; 189 } 190 } 191 192 197 public synchronized void lineTo(float x, float y) { 198 needRoom(1, 2, true); 199 pointTypes[numTypes++] = SEG_LINETO; 200 pointCoords[numCoords++] = x; 201 pointCoords[numCoords++] = y; 202 } 203 204 214 public synchronized void quadTo(float x1, float y1, float x2, float y2) { 215 needRoom(1, 4, true); 216 pointTypes[numTypes++] = SEG_QUADTO; 217 pointCoords[numCoords++] = x1; 218 pointCoords[numCoords++] = y1; 219 pointCoords[numCoords++] = x2; 220 pointCoords[numCoords++] = y2; 221 } 222 223 235 public synchronized void curveTo(float x1, float y1, 236 float x2, float y2, 237 float x3, float y3) { 238 needRoom(1, 6, true); 239 pointTypes[numTypes++] = SEG_CUBICTO; 240 pointCoords[numCoords++] = x1; 241 pointCoords[numCoords++] = y1; 242 pointCoords[numCoords++] = x2; 243 pointCoords[numCoords++] = y2; 244 pointCoords[numCoords++] = x3; 245 pointCoords[numCoords++] = y3; 246 } 247 248 253 public synchronized void closePath() { 254 if (numTypes == 0 || pointTypes[numTypes - 1] != SEG_CLOSE) { 255 needRoom(1, 0, true); 256 pointTypes[numTypes++] = SEG_CLOSE; 257 } 258 } 259 260 280 public void append(Shape s, boolean connect) { 281 PathIterator pi = s.getPathIterator(null); 282 append(pi,connect); 283 } 284 285 306 public void append(PathIterator pi, boolean connect) { 307 float coords[] = new float[6]; 308 while (!pi.isDone()) { 309 switch (pi.currentSegment(coords)) { 310 case SEG_MOVETO: 311 if (!connect || numTypes < 1 || numCoords < 2) { 312 moveTo(coords[0], coords[1]); 313 break; 314 } 315 if (pointTypes[numTypes - 1] != SEG_CLOSE && 316 pointCoords[numCoords - 2] == coords[0] && 317 pointCoords[numCoords - 1] == coords[1]) 318 { 319 break; 321 } 322 case SEG_LINETO: 324 lineTo(coords[0], coords[1]); 325 break; 326 case SEG_QUADTO: 327 quadTo(coords[0], coords[1], 328 coords[2], coords[3]); 329 break; 330 case SEG_CUBICTO: 331 curveTo(coords[0], coords[1], 332 coords[2], coords[3], 333 coords[4], coords[5]); 334 break; 335 case SEG_CLOSE: 336 closePath(); 337 break; 338 } 339 pi.next(); 340 connect = false; 341 } 342 } 343 344 351 public synchronized int getWindingRule() { 352 return windingRule; 353 } 354 355 367 public void setWindingRule(int rule) { 368 if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) { 369 throw new IllegalArgumentException ("winding rule must be "+ 370 "WIND_EVEN_ODD or "+ 371 "WIND_NON_ZERO"); 372 } 373 windingRule = rule; 374 } 375 376 383 public synchronized Point2D getCurrentPoint() { 384 if (numTypes < 1 || numCoords < 2) { 385 return null; 386 } 387 int index = numCoords; 388 if (pointTypes[numTypes - 1] == SEG_CLOSE) { 389 loop: 390 for (int i = numTypes - 2; i > 0; i--) { 391 switch (pointTypes[i]) { 392 case SEG_MOVETO: 393 break loop; 394 case SEG_LINETO: 395 index -= 2; 396 break; 397 case SEG_QUADTO: 398 index -= 4; 399 break; 400 case SEG_CUBICTO: 401 index -= 6; 402 break; 403 case SEG_CLOSE: 404 break; 405 } 406 } 407 } 408 return new Point2D.Float (pointCoords[index - 2], 409 pointCoords[index - 1]); 410 } 411 412 417 public synchronized void reset() { 418 numTypes = numCoords = 0; 419 } 420 421 428 public void transform(AffineTransform at) { 429 at.transform(pointCoords, 0, pointCoords, 0, numCoords / 2); 430 } 431 432 439 public synchronized Shape createTransformedShape(AffineTransform at) { 440 GeneralPath gp = (GeneralPath ) clone(); 441 if (at != null) { 442 gp.transform(at); 443 } 444 return gp; 445 } 446 447 452 public java.awt.Rectangle getBounds() { 453 return getBounds2D().getBounds(); 454 } 455 456 461 public synchronized Rectangle2D getBounds2D() { 462 float x1, y1, x2, y2; 463 int i = numCoords; 464 if (i > 0) { 465 y1 = y2 = pointCoords[--i]; 466 x1 = x2 = pointCoords[--i]; 467 while (i > 0) { 468 float y = pointCoords[--i]; 469 float x = pointCoords[--i]; 470 if (x < x1) x1 = x; 471 if (y < y1) y1 = y; 472 if (x > x2) x2 = x; 473 if (y > y2) y2 = y; 474 } 475 } else { 476 x1 = y1 = x2 = y2 = 0.0f; 477 } 478 return new Rectangle2D.Float (x1, y1, x2 - x1, y2 - y1); 479 } 480 481 488 public boolean contains(double x, double y) { 489 if (numTypes < 2) { 490 return false; 491 } 492 int cross = Curve.crossingsForPath(getPathIterator(null), x, y); 493 if (windingRule == WIND_NON_ZERO) { 494 return (cross != 0); 495 } else { 496 return ((cross & 1) != 0); 497 } 498 } 499 500 507 public boolean contains(Point2D p) { 508 return contains(p.getX(), p.getY()); 509 } 510 511 520 public boolean contains(double x, double y, double w, double h) { 521 Crossings c = Crossings.findCrossings(getPathIterator(null), 522 x, y, x+w, y+h); 523 return (c != null && c.covers(y, y+h)); 524 } 525 526 533 public boolean contains(Rectangle2D r) { 534 return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); 535 } 536 537 547 public boolean intersects(double x, double y, double w, double h) { 548 Crossings c = Crossings.findCrossings(getPathIterator(null), 549 x, y, x+w, y+h); 550 return (c == null || !c.isEmpty()); 551 } 552 553 561 public boolean intersects(Rectangle2D r) { 562 return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); 563 } 564 565 579 public PathIterator getPathIterator(AffineTransform at) { 580 return new GeneralPathIterator (this, at); 581 } 582 583 599 public PathIterator getPathIterator(AffineTransform at, double flatness) { 600 return new FlatteningPathIterator (getPathIterator(at), flatness); 601 } 602 603 611 public Object clone() { 612 try { 613 GeneralPath copy = (GeneralPath ) super.clone(); 614 copy.pointTypes = (byte[]) pointTypes.clone(); 615 copy.pointCoords = (float[]) pointCoords.clone(); 616 return copy; 617 } catch (CloneNotSupportedException e) { 618 throw new InternalError (); 620 } 621 } 622 623 GeneralPath(int windingRule, 624 byte[] pointTypes, 625 int numTypes, 626 float[] pointCoords, 627 int numCoords) { 628 629 631 this.windingRule = windingRule; 632 this.pointTypes = pointTypes; 633 this.numTypes = numTypes; 634 this.pointCoords = pointCoords; 635 this.numCoords = numCoords; 636 } 637 } 638 | Popular Tags |