Path.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.graphics; 18 19/** 20 * The Path class encapsulates compound (multiple contour) geometric paths 21 * consisting of straight line segments, quadratic curves, and cubic curves. 22 * It can be drawn with canvas.drawPath(path, paint), either filled or stroked 23 * (based on the paint's Style), or it can be used for clipping or to draw 24 * text on a path. 25 */ 26public class Path { 27 28 /** 29 * Create an empty path 30 */ 31 public Path() { 32 mNativePath = init1(); 33 } 34 35 /** 36 * Create a new path, copying the contents from the src path. 37 * 38 * @param src The path to copy from when initializing the new path 39 */ 40 public Path(Path src) { 41 int valNative = 0; 42 if (src != null) { 43 valNative = src.mNativePath; 44 } 45 mNativePath = init2(valNative); 46 } 47 48 /** 49 * Clear any lines and curves from the path, making it empty. 50 * This does NOT change the fill-type setting. 51 */ 52 public void reset() { 53 native_reset(mNativePath); 54 } 55 56 /** 57 * Rewinds the path: clears any lines and curves from the path but 58 * keeps the internal data structure for faster reuse. 59 */ 60 public void rewind() { 61 native_rewind(mNativePath); 62 } 63 64 /** Replace the contents of this with the contents of src. 65 */ 66 public void set(Path src) { 67 if (this != src) { 68 native_set(mNativePath, src.mNativePath); 69 } 70 } 71 72 /** Enum for the ways a path may be filled 73 */ 74 public enum FillType { 75 // these must match the values in SkPath.h 76 WINDING (0), 77 EVEN_ODD (1), 78 INVERSE_WINDING (2), 79 INVERSE_EVEN_ODD(3); 80 81 FillType(int ni) { 82 nativeInt = ni; 83 } 84 final int nativeInt; 85 } 86 87 // these must be in the same order as their native values 88 private static final FillType[] sFillTypeArray = { 89 FillType.WINDING, 90 FillType.EVEN_ODD, 91 FillType.INVERSE_WINDING, 92 FillType.INVERSE_EVEN_ODD 93 }; 94 95 /** 96 * Return the path's fill type. This defines how "inside" is 97 * computed. The default value is WINDING. 98 * 99 * @return the path's fill type 100 */ 101 public FillType getFillType() { 102 return sFillTypeArray[native_getFillType(mNativePath)]; 103 } 104 105 /** 106 * Set the path's fill type. This defines how "inside" is computed. 107 * 108 * @param ft The new fill type for this path 109 */ 110 public void setFillType(FillType ft) { 111 native_setFillType(mNativePath, ft.nativeInt); 112 } 113 114 /** 115 * Returns true if the filltype is one of the INVERSE variants 116 * 117 * @return true if the filltype is one of the INVERSE variants 118 */ 119 public boolean isInverseFillType() { 120 final int ft = native_getFillType(mNativePath); 121 return (ft & 2) != 0; 122 } 123 124 /** 125 * Toggles the INVERSE state of the filltype 126 */ 127 public void toggleInverseFillType() { 128 int ft = native_getFillType(mNativePath); 129 ft ^= 2; 130 native_setFillType(mNativePath, ft); 131 } 132 133 /** 134 * Returns true if the path is empty (contains no lines or curves) 135 * 136 * @return true if the path is empty (contains no lines or curves) 137 */ 138 public boolean isEmpty() { 139 return native_isEmpty(mNativePath); 140 } 141 142 /** 143 * Returns true if the path specifies a rectangle. If so, and if rect is 144 * not null, set rect to the bounds of the path. If the path does not 145 * specify a rectangle, return false and ignore rect. 146 * 147 * @param rect If not null, returns the bounds of the path if it specifies 148 * a rectangle 149 * @return true if the path specifies a rectangle 150 */ 151 public boolean isRect(RectF rect) { 152 return native_isRect(mNativePath, rect); 153 } 154 155 /** 156 * Compute the bounds of the path, and write the answer into bounds. If the 157 * path contains 0 or 1 points, the bounds is set to (0,0,0,0) 158 * 159 * @param bounds Returns the computed bounds of the path 160 * @param exact If true, return the exact (but slower) bounds, else return 161 * just the bounds of all control points 162 */ 163 public void computeBounds(RectF bounds, boolean exact) { 164 // 1-exact, 0-fast correspond to the values in SkPath.h 165 native_computeBounds(mNativePath, bounds, exact ? 1 : 0); 166 } 167 168 /** 169 * Hint to the path to prepare for adding more points. This can allow the 170 * path to more efficiently allocate its storage. 171 * 172 * @param extraPtCount The number of extra points that may be added to this 173 * path 174 */ 175 public void incReserve(int extraPtCount) { 176 native_incReserve(mNativePath, extraPtCount); 177 } 178 179 /** 180 * Set the beginning of the next contour to the point (x,y). 181 * 182 * @param x The x-coordinate of the start of a new contour 183 * @param y The y-coordinate of the start of a new contour 184 */ 185 public void moveTo(float x, float y) { 186 native_moveTo(mNativePath, x, y); 187 } 188 189 /** 190 * Set the beginning of the next contour relative to the last point on the 191 * previous contour. If there is no previous contour, this is treated the 192 * same as moveTo(). 193 * 194 * @param dx The amount to add to the x-coordinate of the end of the 195 * previous contour, to specify the start of a new contour 196 * @param dy The amount to add to the y-coordinate of the end of the 197 * previous contour, to specify the start of a new contour 198 */ 199 public void rMoveTo(float dx, float dy) { 200 native_rMoveTo(mNativePath, dx, dy); 201 } 202 203 /** 204 * Add a line from the last point to the specified point (x,y). 205 * If no moveTo() call has been made for this contour, the first point is 206 * automatically set to (0,0). 207 * 208 * @param x The x-coordinate of the end of a line 209 * @param y The y-coordinate of the end of a line 210 */ 211 public void lineTo(float x, float y) { 212 native_lineTo(mNativePath, x, y); 213 } 214 215 /** 216 * Same as lineTo, but the coordinates are considered relative to the last 217 * point on this contour. If there is no previous point, then a moveTo(0,0) 218 * is inserted automatically. 219 * 220 * @param dx The amount to add to the x-coordinate of the previous point on 221 * this contour, to specify a line 222 * @param dy The amount to add to the y-coordinate of the previous point on 223 * this contour, to specify a line 224 */ 225 public void rLineTo(float dx, float dy) { 226 native_rLineTo(mNativePath, dx, dy); 227 } 228 229 /** 230 * Add a quadratic bezier from the last point, approaching control point 231 * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for 232 * this contour, the first point is automatically set to (0,0). 233 * 234 * @param x1 The x-coordinate of the control point on a quadratic curve 235 * @param y1 The y-coordinate of the control point on a quadratic curve 236 * @param x2 The x-coordinate of the end point on a quadratic curve 237 * @param y2 The y-coordinate of the end point on a quadratic curve 238 */ 239 public void quadTo(float x1, float y1, float x2, float y2) { 240 native_quadTo(mNativePath, x1, y1, x2, y2); 241 } 242 243 /** 244 * Same as quadTo, but the coordinates are considered relative to the last 245 * point on this contour. If there is no previous point, then a moveTo(0,0) 246 * is inserted automatically. 247 * 248 * @param dx1 The amount to add to the x-coordinate of the last point on 249 * this contour, for the control point of a quadratic curve 250 * @param dy1 The amount to add to the y-coordinate of the last point on 251 * this contour, for the control point of a quadratic curve 252 * @param dx2 The amount to add to the x-coordinate of the last point on 253 * this contour, for the end point of a quadratic curve 254 * @param dy2 The amount to add to the y-coordinate of the last point on 255 * this contour, for the end point of a quadratic curve 256 */ 257 public void rQuadTo(float dx1, float dy1, float dx2, float dy2) { 258 native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2); 259 } 260 261 /** 262 * Add a cubic bezier from the last point, approaching control points 263 * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been 264 * made for this contour, the first point is automatically set to (0,0). 265 * 266 * @param x1 The x-coordinate of the 1st control point on a cubic curve 267 * @param y1 The y-coordinate of the 1st control point on a cubic curve 268 * @param x2 The x-coordinate of the 2nd control point on a cubic curve 269 * @param y2 The y-coordinate of the 2nd control point on a cubic curve 270 * @param x3 The x-coordinate of the end point on a cubic curve 271 * @param y3 The y-coordinate of the end point on a cubic curve 272 */ 273 public void cubicTo(float x1, float y1, float x2, float y2, 274 float x3, float y3) { 275 native_cubicTo(mNativePath, x1, y1, x2, y2, x3, y3); 276 } 277 278 /** 279 * Same as cubicTo, but the coordinates are considered relative to the 280 * current point on this contour. If there is no previous point, then a 281 * moveTo(0,0) is inserted automatically. 282 */ 283 public void rCubicTo(float x1, float y1, float x2, float y2, 284 float x3, float y3) { 285 native_rCubicTo(mNativePath, x1, y1, x2, y2, x3, y3); 286 } 287 288 /** 289 * Append the specified arc to the path as a new contour. If the start of 290 * the path is different from the path's current last point, then an 291 * automatic lineTo() is added to connect the current contour to the 292 * start of the arc. However, if the path is empty, then we call moveTo() 293 * with the first point of the arc. The sweep angle is tread mod 360. 294 * 295 * @param oval The bounds of oval defining shape and size of the arc 296 * @param startAngle Starting angle (in degrees) where the arc begins 297 * @param sweepAngle Sweep angle (in degrees) measured clockwise, treated 298 * mod 360. 299 * @param forceMoveTo If true, always begin a new contour with the arc 300 */ 301 public void arcTo(RectF oval, float startAngle, float sweepAngle, 302 boolean forceMoveTo) { 303 native_arcTo(mNativePath, oval, startAngle, sweepAngle, forceMoveTo); 304 } 305 306 /** 307 * Append the specified arc to the path as a new contour. If the start of 308 * the path is different from the path's current last point, then an 309 * automatic lineTo() is added to connect the current contour to the 310 * start of the arc. However, if the path is empty, then we call moveTo() 311 * with the first point of the arc. 312 * 313 * @param oval The bounds of oval defining shape and size of the arc 314 * @param startAngle Starting angle (in degrees) where the arc begins 315 * @param sweepAngle Sweep angle (in degrees) measured clockwise 316 */ 317 public void arcTo(RectF oval, float startAngle, float sweepAngle) { 318 native_arcTo(mNativePath, oval, startAngle, sweepAngle, false); 319 } 320 321 /** 322 * Close the current contour. If the current point is not equal to the 323 * first point of the contour, a line segment is automatically added. 324 */ 325 public void close() { 326 native_close(mNativePath); 327 } 328 329 /** 330 * Specifies how closed shapes (e.g. rects, ovals) are oriented when they 331 * are added to a path. 332 */ 333 public enum Direction { 334 /** clockwise */ 335 CW (0), // must match enum in SkPath.h 336 /** counter-clockwise */ 337 CCW (1); // must match enum in SkPath.h 338 339 Direction(int ni) { 340 nativeInt = ni; 341 } 342 final int nativeInt; 343 } 344 345 /** 346 * Add a closed rectangle contour to the path 347 * 348 * @param rect The rectangle to add as a closed contour to the path 349 * @param dir The direction to wind the rectangle's contour 350 */ 351 public void addRect(RectF rect, Direction dir) { 352 if (rect == null) { 353 throw new NullPointerException("need rect parameter"); 354 } 355 native_addRect(mNativePath, rect, dir.nativeInt); 356 } 357 358 /** 359 * Add a closed rectangle contour to the path 360 * 361 * @param left The left side of a rectangle to add to the path 362 * @param top The top of a rectangle to add to the path 363 * @param right The right side of a rectangle to add to the path 364 * @param bottom The bottom of a rectangle to add to the path 365 * @param dir The direction to wind the rectangle's contour 366 */ 367 public void addRect(float left, float top, float right, float bottom, 368 Direction dir) { 369 native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt); 370 } 371 372 /** 373 * Add a closed oval contour to the path 374 * 375 * @param oval The bounds of the oval to add as a closed contour to the path 376 * @param dir The direction to wind the oval's contour 377 */ 378 public void addOval(RectF oval, Direction dir) { 379 if (oval == null) { 380 throw new NullPointerException("need oval parameter"); 381 } 382 native_addOval(mNativePath, oval, dir.nativeInt); 383 } 384 385 /** 386 * Add a closed circle contour to the path 387 * 388 * @param x The x-coordinate of the center of a circle to add to the path 389 * @param y The y-coordinate of the center of a circle to add to the path 390 * @param radius The radius of a circle to add to the path 391 * @param dir The direction to wind the circle's contour 392 */ 393 public void addCircle(float x, float y, float radius, Direction dir) { 394 native_addCircle(mNativePath, x, y, radius, dir.nativeInt); 395 } 396 397 /** 398 * Add the specified arc to the path as a new contour. 399 * 400 * @param oval The bounds of oval defining the shape and size of the arc 401 * @param startAngle Starting angle (in degrees) where the arc begins 402 * @param sweepAngle Sweep angle (in degrees) measured clockwise 403 */ 404 public void addArc(RectF oval, float startAngle, float sweepAngle) { 405 if (oval == null) { 406 throw new NullPointerException("need oval parameter"); 407 } 408 native_addArc(mNativePath, oval, startAngle, sweepAngle); 409 } 410 411 /** 412 * Add a closed round-rectangle contour to the path 413 * 414 * @param rect The bounds of a round-rectangle to add to the path 415 * @param rx The x-radius of the rounded corners on the round-rectangle 416 * @param ry The y-radius of the rounded corners on the round-rectangle 417 * @param dir The direction to wind the round-rectangle's contour 418 */ 419 public void addRoundRect(RectF rect, float rx, float ry, Direction dir) { 420 if (rect == null) { 421 throw new NullPointerException("need rect parameter"); 422 } 423 native_addRoundRect(mNativePath, rect, rx, ry, dir.nativeInt); 424 } 425 426 /** 427 * Add a closed round-rectangle contour to the path. Each corner receives 428 * two radius values [X, Y]. The corners are ordered top-left, top-right, 429 * bottom-right, bottom-left 430 * 431 * @param rect The bounds of a round-rectangle to add to the path 432 * @param radii Array of 8 values, 4 pairs of [X,Y] radii 433 * @param dir The direction to wind the round-rectangle's contour 434 */ 435 public void addRoundRect(RectF rect, float[] radii, Direction dir) { 436 if (rect == null) { 437 throw new NullPointerException("need rect parameter"); 438 } 439 if (radii.length < 8) { 440 throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values"); 441 } 442 native_addRoundRect(mNativePath, rect, radii, dir.nativeInt); 443 } 444 445 /** 446 * Add a copy of src to the path, offset by (dx,dy) 447 * 448 * @param src The path to add as a new contour 449 * @param dx The amount to translate the path in X as it is added 450 */ 451 public void addPath(Path src, float dx, float dy) { 452 native_addPath(mNativePath, src.mNativePath, dx, dy); 453 } 454 455 /** 456 * Add a copy of src to the path 457 * 458 * @param src The path that is appended to the current path 459 */ 460 public void addPath(Path src) { 461 native_addPath(mNativePath, src.mNativePath); 462 } 463 464 /** 465 * Add a copy of src to the path, transformed by matrix 466 * 467 * @param src The path to add as a new contour 468 */ 469 public void addPath(Path src, Matrix matrix) { 470 native_addPath(mNativePath, src.mNativePath, matrix.native_instance); 471 } 472 473 /** 474 * Offset the path by (dx,dy), returning true on success 475 * 476 * @param dx The amount in the X direction to offset the entire path 477 * @param dy The amount in the Y direction to offset the entire path 478 * @param dst The translated path is written here. If this is null, then 479 * the original path is modified. 480 */ 481 public void offset(float dx, float dy, Path dst) { 482 int dstNative = 0; 483 if (dst != null) { 484 dstNative = dst.mNativePath; 485 } 486 native_offset(mNativePath, dx, dy, dstNative); 487 } 488 489 /** 490 * Offset the path by (dx,dy), returning true on success 491 * 492 * @param dx The amount in the X direction to offset the entire path 493 * @param dy The amount in the Y direction to offset the entire path 494 */ 495 public void offset(float dx, float dy) { 496 native_offset(mNativePath, dx, dy); 497 } 498 499 /** 500 * Sets the last point of the path. 501 * 502 * @param dx The new X coordinate for the last point 503 * @param dy The new Y coordinate for the last point 504 */ 505 public void setLastPoint(float dx, float dy) { 506 native_setLastPoint(mNativePath, dx, dy); 507 } 508 509 /** 510 * Transform the points in this path by matrix, and write the answer 511 * into dst. If dst is null, then the the original path is modified. 512 * 513 * @param matrix The matrix to apply to the path 514 * @param dst The transformed path is written here. If dst is null, 515 * then the the original path is modified 516 */ 517 public void transform(Matrix matrix, Path dst) { 518 int dstNative = 0; 519 if (dst != null) { 520 dstNative = dst.mNativePath; 521 } 522 native_transform(mNativePath, matrix.native_instance, dstNative); 523 } 524 525 /** 526 * Transform the points in this path by matrix. 527 * 528 * @param matrix The matrix to apply to the path 529 */ 530 public void transform(Matrix matrix) { 531 native_transform(mNativePath, matrix.native_instance); 532 } 533 534 protected void finalize() throws Throwable { 535 try { 536 finalizer(mNativePath); 537 } finally { 538 super.finalize(); 539 } 540 } 541 542 /*package*/ final int ni() { 543 return mNativePath; 544 } 545 546 private static native int init1(); 547 private static native int init2(int nPath); 548 private static native void native_reset(int nPath); 549 private static native void native_rewind(int nPath); 550 private static native void native_set(int native_dst, int native_src); 551 private static native int native_getFillType(int nPath); 552 private static native void native_setFillType(int nPath, int ft); 553 private static native boolean native_isEmpty(int nPath); 554 private static native boolean native_isRect(int nPath, RectF rect); 555 private static native void native_computeBounds(int nPath, RectF bounds, 556 int btype); 557 private static native void native_incReserve(int nPath, int extraPtCount); 558 private static native void native_moveTo(int nPath, float x, float y); 559 private static native void native_rMoveTo(int nPath, float dx, float dy); 560 private static native void native_lineTo(int nPath, float x, float y); 561 private static native void native_rLineTo(int nPath, float dx, float dy); 562 private static native void native_quadTo(int nPath, float x1, float y1, 563 float x2, float y2); 564 private static native void native_rQuadTo(int nPath, float dx1, float dy1, 565 float dx2, float dy2); 566 private static native void native_cubicTo(int nPath, float x1, float y1, 567 float x2, float y2, float x3, float y3); 568 private static native void native_rCubicTo(int nPath, float x1, float y1, 569 float x2, float y2, float x3, float y3); 570 private static native void native_arcTo(int nPath, RectF oval, 571 float startAngle, float sweepAngle, boolean forceMoveTo); 572 private static native void native_close(int nPath); 573 private static native void native_addRect(int nPath, RectF rect, int dir); 574 private static native void native_addRect(int nPath, float left, float top, 575 float right, float bottom, int dir); 576 private static native void native_addOval(int nPath, RectF oval, int dir); 577 private static native void native_addCircle(int nPath, float x, float y, 578 float radius, int dir); 579 private static native void native_addArc(int nPath, RectF oval, 580 float startAngle, float sweepAngle); 581 private static native void native_addRoundRect(int nPath, RectF rect, 582 float rx, float ry, int dir); 583 private static native void native_addRoundRect(int nPath, RectF r, 584 float[] radii, int dir); 585 private static native void native_addPath(int nPath, int src, float dx, 586 float dy); 587 private static native void native_addPath(int nPath, int src); 588 private static native void native_addPath(int nPath, int src, int matrix); 589 private static native void native_offset(int nPath, float dx, float dy, 590 int dst_path); 591 private static native void native_offset(int nPath, float dx, float dy); 592 private static native void native_setLastPoint(int nPath, float dx, float dy); 593 private static native void native_transform(int nPath, int matrix, 594 int dst_path); 595 private static native void native_transform(int nPath, int matrix); 596 private static native void finalizer(int nPath); 597 598 private final int mNativePath; 599} 600