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