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 17 package 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 */ 26 public class Path { 27 /** 28 * @hide 29 */ 30 public final long mNativePath; 31 32 /** 33 * @hide 34 */ 35 public boolean isSimplePath = true; 36 /** 37 * @hide 38 */ 39 public Region rects; 40 private Direction mLastDirection = null; 41 42 /** 43 * Create an empty path 44 */ Path()45 public Path() { 46 mNativePath = init1(); 47 } 48 49 /** 50 * Create a new path, copying the contents from the src path. 51 * 52 * @param src The path to copy from when initializing the new path 53 */ Path(Path src)54 public Path(Path src) { 55 long valNative = 0; 56 if (src != null) { 57 valNative = src.mNativePath; 58 isSimplePath = src.isSimplePath; 59 if (src.rects != null) { 60 rects = new Region(src.rects); 61 } 62 } 63 mNativePath = init2(valNative); 64 } 65 66 /** 67 * Clear any lines and curves from the path, making it empty. 68 * This does NOT change the fill-type setting. 69 */ reset()70 public void reset() { 71 isSimplePath = true; 72 mLastDirection = null; 73 if (rects != null) rects.setEmpty(); 74 // We promised not to change this, so preserve it around the native 75 // call, which does now reset fill type. 76 final FillType fillType = getFillType(); 77 native_reset(mNativePath); 78 setFillType(fillType); 79 } 80 81 /** 82 * Rewinds the path: clears any lines and curves from the path but 83 * keeps the internal data structure for faster reuse. 84 */ rewind()85 public void rewind() { 86 isSimplePath = true; 87 mLastDirection = null; 88 if (rects != null) rects.setEmpty(); 89 native_rewind(mNativePath); 90 } 91 92 /** Replace the contents of this with the contents of src. 93 */ set(Path src)94 public void set(Path src) { 95 if (this != src) { 96 isSimplePath = src.isSimplePath; 97 native_set(mNativePath, src.mNativePath); 98 } 99 } 100 101 /** 102 * The logical operations that can be performed when combining two paths. 103 * 104 * @see #op(Path, android.graphics.Path.Op) 105 * @see #op(Path, Path, android.graphics.Path.Op) 106 */ 107 public enum Op { 108 /** 109 * Subtract the second path from the first path. 110 */ 111 DIFFERENCE, 112 /** 113 * Intersect the two paths. 114 */ 115 INTERSECT, 116 /** 117 * Union (inclusive-or) the two paths. 118 */ 119 UNION, 120 /** 121 * Exclusive-or the two paths. 122 */ 123 XOR, 124 /** 125 * Subtract the first path from the second path. 126 */ 127 REVERSE_DIFFERENCE 128 } 129 130 /** 131 * Set this path to the result of applying the Op to this path and the specified path. 132 * The resulting path will be constructed from non-overlapping contours. 133 * The curve order is reduced where possible so that cubics may be turned 134 * into quadratics, and quadratics maybe turned into lines. 135 * 136 * @param path The second operand (for difference, the subtrahend) 137 * 138 * @return True if operation succeeded, false otherwise and this path remains unmodified. 139 * 140 * @see Op 141 * @see #op(Path, Path, android.graphics.Path.Op) 142 */ op(Path path, Op op)143 public boolean op(Path path, Op op) { 144 return op(this, path, op); 145 } 146 147 /** 148 * Set this path to the result of applying the Op to the two specified paths. 149 * The resulting path will be constructed from non-overlapping contours. 150 * The curve order is reduced where possible so that cubics may be turned 151 * into quadratics, and quadratics maybe turned into lines. 152 * 153 * @param path1 The first operand (for difference, the minuend) 154 * @param path2 The second operand (for difference, the subtrahend) 155 * 156 * @return True if operation succeeded, false otherwise and this path remains unmodified. 157 * 158 * @see Op 159 * @see #op(Path, android.graphics.Path.Op) 160 */ op(Path path1, Path path2, Op op)161 public boolean op(Path path1, Path path2, Op op) { 162 if (native_op(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath)) { 163 isSimplePath = false; 164 rects = null; 165 return true; 166 } 167 return false; 168 } 169 170 /** 171 * Returns the path's convexity, as defined by the content of the path. 172 * <p> 173 * A path is convex if it has a single contour, and only ever curves in a 174 * single direction. 175 * <p> 176 * This function will calculate the convexity of the path from its control 177 * points, and cache the result. 178 * 179 * @return True if the path is convex. 180 */ isConvex()181 public boolean isConvex() { 182 return native_isConvex(mNativePath); 183 } 184 185 /** 186 * Enum for the ways a path may be filled. 187 */ 188 public enum FillType { 189 // these must match the values in SkPath.h 190 /** 191 * Specifies that "inside" is computed by a non-zero sum of signed 192 * edge crossings. 193 */ 194 WINDING (0), 195 /** 196 * Specifies that "inside" is computed by an odd number of edge 197 * crossings. 198 */ 199 EVEN_ODD (1), 200 /** 201 * Same as {@link #WINDING}, but draws outside of the path, rather than inside. 202 */ 203 INVERSE_WINDING (2), 204 /** 205 * Same as {@link #EVEN_ODD}, but draws outside of the path, rather than inside. 206 */ 207 INVERSE_EVEN_ODD(3); 208 FillType(int ni)209 FillType(int ni) { 210 nativeInt = ni; 211 } 212 213 final int nativeInt; 214 } 215 216 // these must be in the same order as their native values 217 static final FillType[] sFillTypeArray = { 218 FillType.WINDING, 219 FillType.EVEN_ODD, 220 FillType.INVERSE_WINDING, 221 FillType.INVERSE_EVEN_ODD 222 }; 223 224 /** 225 * Return the path's fill type. This defines how "inside" is 226 * computed. The default value is WINDING. 227 * 228 * @return the path's fill type 229 */ getFillType()230 public FillType getFillType() { 231 return sFillTypeArray[native_getFillType(mNativePath)]; 232 } 233 234 /** 235 * Set the path's fill type. This defines how "inside" is computed. 236 * 237 * @param ft The new fill type for this path 238 */ setFillType(FillType ft)239 public void setFillType(FillType ft) { 240 native_setFillType(mNativePath, ft.nativeInt); 241 } 242 243 /** 244 * Returns true if the filltype is one of the INVERSE variants 245 * 246 * @return true if the filltype is one of the INVERSE variants 247 */ isInverseFillType()248 public boolean isInverseFillType() { 249 final int ft = native_getFillType(mNativePath); 250 return (ft & FillType.INVERSE_WINDING.nativeInt) != 0; 251 } 252 253 /** 254 * Toggles the INVERSE state of the filltype 255 */ toggleInverseFillType()256 public void toggleInverseFillType() { 257 int ft = native_getFillType(mNativePath); 258 ft ^= FillType.INVERSE_WINDING.nativeInt; 259 native_setFillType(mNativePath, ft); 260 } 261 262 /** 263 * Returns true if the path is empty (contains no lines or curves) 264 * 265 * @return true if the path is empty (contains no lines or curves) 266 */ isEmpty()267 public boolean isEmpty() { 268 return native_isEmpty(mNativePath); 269 } 270 271 /** 272 * Returns true if the path specifies a rectangle. If so, and if rect is 273 * not null, set rect to the bounds of the path. If the path does not 274 * specify a rectangle, return false and ignore rect. 275 * 276 * @param rect If not null, returns the bounds of the path if it specifies 277 * a rectangle 278 * @return true if the path specifies a rectangle 279 */ isRect(RectF rect)280 public boolean isRect(RectF rect) { 281 return native_isRect(mNativePath, rect); 282 } 283 284 /** 285 * Compute the bounds of the control points of the path, and write the 286 * answer into bounds. If the path contains 0 or 1 points, the bounds is 287 * set to (0,0,0,0) 288 * 289 * @param bounds Returns the computed bounds of the path's control points. 290 * @param exact This parameter is no longer used. 291 */ 292 @SuppressWarnings({"UnusedDeclaration"}) computeBounds(RectF bounds, boolean exact)293 public void computeBounds(RectF bounds, boolean exact) { 294 native_computeBounds(mNativePath, bounds); 295 } 296 297 /** 298 * Hint to the path to prepare for adding more points. This can allow the 299 * path to more efficiently allocate its storage. 300 * 301 * @param extraPtCount The number of extra points that may be added to this 302 * path 303 */ incReserve(int extraPtCount)304 public void incReserve(int extraPtCount) { 305 native_incReserve(mNativePath, extraPtCount); 306 } 307 308 /** 309 * Set the beginning of the next contour to the point (x,y). 310 * 311 * @param x The x-coordinate of the start of a new contour 312 * @param y The y-coordinate of the start of a new contour 313 */ moveTo(float x, float y)314 public void moveTo(float x, float y) { 315 native_moveTo(mNativePath, x, y); 316 } 317 318 /** 319 * Set the beginning of the next contour relative to the last point on the 320 * previous contour. If there is no previous contour, this is treated the 321 * same as moveTo(). 322 * 323 * @param dx The amount to add to the x-coordinate of the end of the 324 * previous contour, to specify the start of a new contour 325 * @param dy The amount to add to the y-coordinate of the end of the 326 * previous contour, to specify the start of a new contour 327 */ rMoveTo(float dx, float dy)328 public void rMoveTo(float dx, float dy) { 329 native_rMoveTo(mNativePath, dx, dy); 330 } 331 332 /** 333 * Add a line from the last point to the specified point (x,y). 334 * If no moveTo() call has been made for this contour, the first point is 335 * automatically set to (0,0). 336 * 337 * @param x The x-coordinate of the end of a line 338 * @param y The y-coordinate of the end of a line 339 */ lineTo(float x, float y)340 public void lineTo(float x, float y) { 341 isSimplePath = false; 342 native_lineTo(mNativePath, x, y); 343 } 344 345 /** 346 * Same as lineTo, but the coordinates are considered relative to the last 347 * point on this contour. If there is no previous point, then a moveTo(0,0) 348 * is inserted automatically. 349 * 350 * @param dx The amount to add to the x-coordinate of the previous point on 351 * this contour, to specify a line 352 * @param dy The amount to add to the y-coordinate of the previous point on 353 * this contour, to specify a line 354 */ rLineTo(float dx, float dy)355 public void rLineTo(float dx, float dy) { 356 isSimplePath = false; 357 native_rLineTo(mNativePath, dx, dy); 358 } 359 360 /** 361 * Add a quadratic bezier from the last point, approaching control point 362 * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for 363 * this contour, the first point is automatically set to (0,0). 364 * 365 * @param x1 The x-coordinate of the control point on a quadratic curve 366 * @param y1 The y-coordinate of the control point on a quadratic curve 367 * @param x2 The x-coordinate of the end point on a quadratic curve 368 * @param y2 The y-coordinate of the end point on a quadratic curve 369 */ quadTo(float x1, float y1, float x2, float y2)370 public void quadTo(float x1, float y1, float x2, float y2) { 371 isSimplePath = false; 372 native_quadTo(mNativePath, x1, y1, x2, y2); 373 } 374 375 /** 376 * Same as quadTo, but the coordinates are considered relative to the last 377 * point on this contour. If there is no previous point, then a moveTo(0,0) 378 * is inserted automatically. 379 * 380 * @param dx1 The amount to add to the x-coordinate of the last point on 381 * this contour, for the control point of a quadratic curve 382 * @param dy1 The amount to add to the y-coordinate of the last point on 383 * this contour, for the control point of a quadratic curve 384 * @param dx2 The amount to add to the x-coordinate of the last point on 385 * this contour, for the end point of a quadratic curve 386 * @param dy2 The amount to add to the y-coordinate of the last point on 387 * this contour, for the end point of a quadratic curve 388 */ rQuadTo(float dx1, float dy1, float dx2, float dy2)389 public void rQuadTo(float dx1, float dy1, float dx2, float dy2) { 390 isSimplePath = false; 391 native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2); 392 } 393 394 /** 395 * Add a cubic bezier from the last point, approaching control points 396 * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been 397 * made for this contour, the first point is automatically set to (0,0). 398 * 399 * @param x1 The x-coordinate of the 1st control point on a cubic curve 400 * @param y1 The y-coordinate of the 1st control point on a cubic curve 401 * @param x2 The x-coordinate of the 2nd control point on a cubic curve 402 * @param y2 The y-coordinate of the 2nd control point on a cubic curve 403 * @param x3 The x-coordinate of the end point on a cubic curve 404 * @param y3 The y-coordinate of the end point on a cubic curve 405 */ cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)406 public void cubicTo(float x1, float y1, float x2, float y2, 407 float x3, float y3) { 408 isSimplePath = false; 409 native_cubicTo(mNativePath, x1, y1, x2, y2, x3, y3); 410 } 411 412 /** 413 * Same as cubicTo, but the coordinates are considered relative to the 414 * current point on this contour. If there is no previous point, then a 415 * moveTo(0,0) is inserted automatically. 416 */ rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)417 public void rCubicTo(float x1, float y1, float x2, float y2, 418 float x3, float y3) { 419 isSimplePath = false; 420 native_rCubicTo(mNativePath, x1, y1, x2, y2, x3, y3); 421 } 422 423 /** 424 * Append the specified arc to the path as a new contour. If the start of 425 * the path is different from the path's current last point, then an 426 * automatic lineTo() is added to connect the current contour to the 427 * start of the arc. However, if the path is empty, then we call moveTo() 428 * with the first point of the arc. 429 * 430 * @param oval The bounds of oval defining shape and size of the arc 431 * @param startAngle Starting angle (in degrees) where the arc begins 432 * @param sweepAngle Sweep angle (in degrees) measured clockwise, treated 433 * mod 360. 434 * @param forceMoveTo If true, always begin a new contour with the arc 435 */ arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)436 public void arcTo(RectF oval, float startAngle, float sweepAngle, 437 boolean forceMoveTo) { 438 arcTo(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, forceMoveTo); 439 } 440 441 /** 442 * Append the specified arc to the path as a new contour. If the start of 443 * the path is different from the path's current last point, then an 444 * automatic lineTo() is added to connect the current contour to the 445 * start of the arc. However, if the path is empty, then we call moveTo() 446 * with the first point of the arc. 447 * 448 * @param oval The bounds of oval defining shape and size of the arc 449 * @param startAngle Starting angle (in degrees) where the arc begins 450 * @param sweepAngle Sweep angle (in degrees) measured clockwise 451 */ arcTo(RectF oval, float startAngle, float sweepAngle)452 public void arcTo(RectF oval, float startAngle, float sweepAngle) { 453 arcTo(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, false); 454 } 455 456 /** 457 * Append the specified arc to the path as a new contour. If the start of 458 * the path is different from the path's current last point, then an 459 * automatic lineTo() is added to connect the current contour to the 460 * start of the arc. However, if the path is empty, then we call moveTo() 461 * with the first point of the arc. 462 * 463 * @param startAngle Starting angle (in degrees) where the arc begins 464 * @param sweepAngle Sweep angle (in degrees) measured clockwise, treated 465 * mod 360. 466 * @param forceMoveTo If true, always begin a new contour with the arc 467 */ arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo)468 public void arcTo(float left, float top, float right, float bottom, float startAngle, 469 float sweepAngle, boolean forceMoveTo) { 470 isSimplePath = false; 471 native_arcTo(mNativePath, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo); 472 } 473 474 /** 475 * Close the current contour. If the current point is not equal to the 476 * first point of the contour, a line segment is automatically added. 477 */ close()478 public void close() { 479 isSimplePath = false; 480 native_close(mNativePath); 481 } 482 483 /** 484 * Specifies how closed shapes (e.g. rects, ovals) are oriented when they 485 * are added to a path. 486 */ 487 public enum Direction { 488 /** clockwise */ 489 CW (1), // must match enum in SkPath.h 490 /** counter-clockwise */ 491 CCW (2); // must match enum in SkPath.h 492 Direction(int ni)493 Direction(int ni) { 494 nativeInt = ni; 495 } 496 final int nativeInt; 497 } 498 detectSimplePath(float left, float top, float right, float bottom, Direction dir)499 private void detectSimplePath(float left, float top, float right, float bottom, Direction dir) { 500 if (mLastDirection == null) { 501 mLastDirection = dir; 502 } 503 if (mLastDirection != dir) { 504 isSimplePath = false; 505 } else { 506 if (rects == null) rects = new Region(); 507 rects.op((int) left, (int) top, (int) right, (int) bottom, Region.Op.UNION); 508 } 509 } 510 511 /** 512 * Add a closed rectangle contour to the path 513 * 514 * @param rect The rectangle to add as a closed contour to the path 515 * @param dir The direction to wind the rectangle's contour 516 */ addRect(RectF rect, Direction dir)517 public void addRect(RectF rect, Direction dir) { 518 addRect(rect.left, rect.top, rect.right, rect.bottom, dir); 519 } 520 521 /** 522 * Add a closed rectangle contour to the path 523 * 524 * @param left The left side of a rectangle to add to the path 525 * @param top The top of a rectangle to add to the path 526 * @param right The right side of a rectangle to add to the path 527 * @param bottom The bottom of a rectangle to add to the path 528 * @param dir The direction to wind the rectangle's contour 529 */ addRect(float left, float top, float right, float bottom, Direction dir)530 public void addRect(float left, float top, float right, float bottom, Direction dir) { 531 detectSimplePath(left, top, right, bottom, dir); 532 native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt); 533 } 534 535 /** 536 * Add a closed oval contour to the path 537 * 538 * @param oval The bounds of the oval to add as a closed contour to the path 539 * @param dir The direction to wind the oval's contour 540 */ addOval(RectF oval, Direction dir)541 public void addOval(RectF oval, Direction dir) { 542 addOval(oval.left, oval.top, oval.right, oval.bottom, dir); 543 } 544 545 /** 546 * Add a closed oval contour to the path 547 * 548 * @param dir The direction to wind the oval's contour 549 */ addOval(float left, float top, float right, float bottom, Direction dir)550 public void addOval(float left, float top, float right, float bottom, Direction dir) { 551 isSimplePath = false; 552 native_addOval(mNativePath, left, top, right, bottom, dir.nativeInt); 553 } 554 555 /** 556 * Add a closed circle contour to the path 557 * 558 * @param x The x-coordinate of the center of a circle to add to the path 559 * @param y The y-coordinate of the center of a circle to add to the path 560 * @param radius The radius of a circle to add to the path 561 * @param dir The direction to wind the circle's contour 562 */ addCircle(float x, float y, float radius, Direction dir)563 public void addCircle(float x, float y, float radius, Direction dir) { 564 isSimplePath = false; 565 native_addCircle(mNativePath, x, y, radius, dir.nativeInt); 566 } 567 568 /** 569 * Add the specified arc to the path as a new contour. 570 * 571 * @param oval The bounds of oval defining the shape and size of the arc 572 * @param startAngle Starting angle (in degrees) where the arc begins 573 * @param sweepAngle Sweep angle (in degrees) measured clockwise 574 */ addArc(RectF oval, float startAngle, float sweepAngle)575 public void addArc(RectF oval, float startAngle, float sweepAngle) { 576 addArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle); 577 } 578 579 /** 580 * Add the specified arc to the path as a new contour. 581 * 582 * @param startAngle Starting angle (in degrees) where the arc begins 583 * @param sweepAngle Sweep angle (in degrees) measured clockwise 584 */ addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)585 public void addArc(float left, float top, float right, float bottom, float startAngle, 586 float sweepAngle) { 587 isSimplePath = false; 588 native_addArc(mNativePath, left, top, right, bottom, startAngle, sweepAngle); 589 } 590 591 /** 592 * Add a closed round-rectangle contour to the path 593 * 594 * @param rect The bounds of a round-rectangle to add to the path 595 * @param rx The x-radius of the rounded corners on the round-rectangle 596 * @param ry The y-radius of the rounded corners on the round-rectangle 597 * @param dir The direction to wind the round-rectangle's contour 598 */ addRoundRect(RectF rect, float rx, float ry, Direction dir)599 public void addRoundRect(RectF rect, float rx, float ry, Direction dir) { 600 addRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, dir); 601 } 602 603 /** 604 * Add a closed round-rectangle contour to the path 605 * 606 * @param rx The x-radius of the rounded corners on the round-rectangle 607 * @param ry The y-radius of the rounded corners on the round-rectangle 608 * @param dir The direction to wind the round-rectangle's contour 609 */ addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Direction dir)610 public void addRoundRect(float left, float top, float right, float bottom, float rx, float ry, 611 Direction dir) { 612 isSimplePath = false; 613 native_addRoundRect(mNativePath, left, top, right, bottom, rx, ry, dir.nativeInt); 614 } 615 616 /** 617 * Add a closed round-rectangle contour to the path. Each corner receives 618 * two radius values [X, Y]. The corners are ordered top-left, top-right, 619 * bottom-right, bottom-left 620 * 621 * @param rect The bounds of a round-rectangle to add to the path 622 * @param radii Array of 8 values, 4 pairs of [X,Y] radii 623 * @param dir The direction to wind the round-rectangle's contour 624 */ addRoundRect(RectF rect, float[] radii, Direction dir)625 public void addRoundRect(RectF rect, float[] radii, Direction dir) { 626 if (rect == null) { 627 throw new NullPointerException("need rect parameter"); 628 } 629 addRoundRect(rect.left, rect.top, rect.right, rect.bottom, radii, dir); 630 } 631 632 /** 633 * Add a closed round-rectangle contour to the path. Each corner receives 634 * two radius values [X, Y]. The corners are ordered top-left, top-right, 635 * bottom-right, bottom-left 636 * 637 * @param radii Array of 8 values, 4 pairs of [X,Y] radii 638 * @param dir The direction to wind the round-rectangle's contour 639 */ addRoundRect(float left, float top, float right, float bottom, float[] radii, Direction dir)640 public void addRoundRect(float left, float top, float right, float bottom, float[] radii, 641 Direction dir) { 642 if (radii.length < 8) { 643 throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values"); 644 } 645 isSimplePath = false; 646 native_addRoundRect(mNativePath, left, top, right, bottom, radii, dir.nativeInt); 647 } 648 649 /** 650 * Add a copy of src to the path, offset by (dx,dy) 651 * 652 * @param src The path to add as a new contour 653 * @param dx The amount to translate the path in X as it is added 654 */ addPath(Path src, float dx, float dy)655 public void addPath(Path src, float dx, float dy) { 656 isSimplePath = false; 657 native_addPath(mNativePath, src.mNativePath, dx, dy); 658 } 659 660 /** 661 * Add a copy of src to the path 662 * 663 * @param src The path that is appended to the current path 664 */ addPath(Path src)665 public void addPath(Path src) { 666 isSimplePath = false; 667 native_addPath(mNativePath, src.mNativePath); 668 } 669 670 /** 671 * Add a copy of src to the path, transformed by matrix 672 * 673 * @param src The path to add as a new contour 674 */ addPath(Path src, Matrix matrix)675 public void addPath(Path src, Matrix matrix) { 676 if (!src.isSimplePath) isSimplePath = false; 677 native_addPath(mNativePath, src.mNativePath, matrix.native_instance); 678 } 679 680 /** 681 * Offset the path by (dx,dy), returning true on success 682 * 683 * @param dx The amount in the X direction to offset the entire path 684 * @param dy The amount in the Y direction to offset the entire path 685 * @param dst The translated path is written here. If this is null, then 686 * the original path is modified. 687 */ offset(float dx, float dy, Path dst)688 public void offset(float dx, float dy, Path dst) { 689 long dstNative = 0; 690 if (dst != null) { 691 dstNative = dst.mNativePath; 692 dst.isSimplePath = false; 693 } 694 native_offset(mNativePath, dx, dy, dstNative); 695 } 696 697 /** 698 * Offset the path by (dx,dy), returning true on success 699 * 700 * @param dx The amount in the X direction to offset the entire path 701 * @param dy The amount in the Y direction to offset the entire path 702 */ offset(float dx, float dy)703 public void offset(float dx, float dy) { 704 isSimplePath = false; 705 native_offset(mNativePath, dx, dy); 706 } 707 708 /** 709 * Sets the last point of the path. 710 * 711 * @param dx The new X coordinate for the last point 712 * @param dy The new Y coordinate for the last point 713 */ setLastPoint(float dx, float dy)714 public void setLastPoint(float dx, float dy) { 715 isSimplePath = false; 716 native_setLastPoint(mNativePath, dx, dy); 717 } 718 719 /** 720 * Transform the points in this path by matrix, and write the answer 721 * into dst. If dst is null, then the the original path is modified. 722 * 723 * @param matrix The matrix to apply to the path 724 * @param dst The transformed path is written here. If dst is null, 725 * then the the original path is modified 726 */ transform(Matrix matrix, Path dst)727 public void transform(Matrix matrix, Path dst) { 728 long dstNative = 0; 729 if (dst != null) { 730 dst.isSimplePath = false; 731 dstNative = dst.mNativePath; 732 } 733 native_transform(mNativePath, matrix.native_instance, dstNative); 734 } 735 736 /** 737 * Transform the points in this path by matrix. 738 * 739 * @param matrix The matrix to apply to the path 740 */ transform(Matrix matrix)741 public void transform(Matrix matrix) { 742 isSimplePath = false; 743 native_transform(mNativePath, matrix.native_instance); 744 } 745 finalize()746 protected void finalize() throws Throwable { 747 try { 748 finalizer(mNativePath); 749 } finally { 750 super.finalize(); 751 } 752 } 753 ni()754 final long ni() { 755 return mNativePath; 756 } 757 758 /** 759 * Approximate the <code>Path</code> with a series of line segments. 760 * This returns float[] with the array containing point components. 761 * There are three components for each point, in order: 762 * <ul> 763 * <li>Fraction along the length of the path that the point resides</li> 764 * <li>The x coordinate of the point</li> 765 * <li>The y coordinate of the point</li> 766 * </ul> 767 * <p>Two points may share the same fraction along its length when there is 768 * a move action within the Path.</p> 769 * 770 * @param acceptableError The acceptable error for a line on the 771 * Path. Typically this would be 0.5 so that 772 * the error is less than half a pixel. 773 * @return An array of components for points approximating the Path. 774 * @hide 775 */ approximate(float acceptableError)776 public float[] approximate(float acceptableError) { 777 return native_approximate(mNativePath, acceptableError); 778 } 779 init1()780 private static native long init1(); init2(long nPath)781 private static native long init2(long nPath); native_reset(long nPath)782 private static native void native_reset(long nPath); native_rewind(long nPath)783 private static native void native_rewind(long nPath); native_set(long native_dst, long native_src)784 private static native void native_set(long native_dst, long native_src); native_isConvex(long nPath)785 private static native boolean native_isConvex(long nPath); native_getFillType(long nPath)786 private static native int native_getFillType(long nPath); native_setFillType(long nPath, int ft)787 private static native void native_setFillType(long nPath, int ft); native_isEmpty(long nPath)788 private static native boolean native_isEmpty(long nPath); native_isRect(long nPath, RectF rect)789 private static native boolean native_isRect(long nPath, RectF rect); native_computeBounds(long nPath, RectF bounds)790 private static native void native_computeBounds(long nPath, RectF bounds); native_incReserve(long nPath, int extraPtCount)791 private static native void native_incReserve(long nPath, int extraPtCount); native_moveTo(long nPath, float x, float y)792 private static native void native_moveTo(long nPath, float x, float y); native_rMoveTo(long nPath, float dx, float dy)793 private static native void native_rMoveTo(long nPath, float dx, float dy); native_lineTo(long nPath, float x, float y)794 private static native void native_lineTo(long nPath, float x, float y); native_rLineTo(long nPath, float dx, float dy)795 private static native void native_rLineTo(long nPath, float dx, float dy); native_quadTo(long nPath, float x1, float y1, float x2, float y2)796 private static native void native_quadTo(long nPath, float x1, float y1, 797 float x2, float y2); native_rQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2)798 private static native void native_rQuadTo(long nPath, float dx1, float dy1, 799 float dx2, float dy2); native_cubicTo(long nPath, float x1, float y1, float x2, float y2, float x3, float y3)800 private static native void native_cubicTo(long nPath, float x1, float y1, 801 float x2, float y2, float x3, float y3); native_rCubicTo(long nPath, float x1, float y1, float x2, float y2, float x3, float y3)802 private static native void native_rCubicTo(long nPath, float x1, float y1, 803 float x2, float y2, float x3, float y3); native_arcTo(long nPath, float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo)804 private static native void native_arcTo(long nPath, float left, float top, 805 float right, float bottom, float startAngle, 806 float sweepAngle, boolean forceMoveTo); native_close(long nPath)807 private static native void native_close(long nPath); native_addRect(long nPath, float left, float top, float right, float bottom, int dir)808 private static native void native_addRect(long nPath, float left, float top, 809 float right, float bottom, int dir); native_addOval(long nPath, float left, float top, float right, float bottom, int dir)810 private static native void native_addOval(long nPath, float left, float top, 811 float right, float bottom, int dir); native_addCircle(long nPath, float x, float y, float radius, int dir)812 private static native void native_addCircle(long nPath, float x, float y, float radius, int dir); native_addArc(long nPath, float left, float top, float right, float bottom, float startAngle, float sweepAngle)813 private static native void native_addArc(long nPath, float left, float top, 814 float right, float bottom, 815 float startAngle, float sweepAngle); native_addRoundRect(long nPath, float left, float top, float right, float bottom, float rx, float ry, int dir)816 private static native void native_addRoundRect(long nPath, float left, float top, 817 float right, float bottom, 818 float rx, float ry, int dir); native_addRoundRect(long nPath, float left, float top, float right, float bottom, float[] radii, int dir)819 private static native void native_addRoundRect(long nPath, float left, float top, 820 float right, float bottom, 821 float[] radii, int dir); native_addPath(long nPath, long src, float dx, float dy)822 private static native void native_addPath(long nPath, long src, float dx, float dy); native_addPath(long nPath, long src)823 private static native void native_addPath(long nPath, long src); native_addPath(long nPath, long src, long matrix)824 private static native void native_addPath(long nPath, long src, long matrix); native_offset(long nPath, float dx, float dy, long dst_path)825 private static native void native_offset(long nPath, float dx, float dy, long dst_path); native_offset(long nPath, float dx, float dy)826 private static native void native_offset(long nPath, float dx, float dy); native_setLastPoint(long nPath, float dx, float dy)827 private static native void native_setLastPoint(long nPath, float dx, float dy); native_transform(long nPath, long matrix, long dst_path)828 private static native void native_transform(long nPath, long matrix, long dst_path); native_transform(long nPath, long matrix)829 private static native void native_transform(long nPath, long matrix); native_op(long path1, long path2, int op, long result)830 private static native boolean native_op(long path1, long path2, int op, long result); finalizer(long nPath)831 private static native void finalizer(long nPath); native_approximate(long nPath, float error)832 private static native float[] native_approximate(long nPath, float error); 833 } 834