Path.java revision 34d8519de44f301ce0b7196e248e58345d3cd35a
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     * @hide
29     */
30    public final int 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     */
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     */
54    public Path(Path src) {
55        int 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     */
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     */
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    */
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     */
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     */
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     * Enum for the ways a path may be filled.
172     */
173    public enum FillType {
174        // these must match the values in SkPath.h
175        /**
176         * Specifies that "inside" is computed by a non-zero sum of signed
177         * edge crossings.
178         */
179        WINDING         (0),
180        /**
181         * Specifies that "inside" is computed by an odd number of edge
182         * crossings.
183         */
184        EVEN_ODD        (1),
185        /**
186         * Same as {@link #WINDING}, but draws outside of the path, rather than inside.
187         */
188        INVERSE_WINDING (2),
189        /**
190         * Same as {@link #EVEN_ODD}, but draws outside of the path, rather than inside.
191         */
192        INVERSE_EVEN_ODD(3);
193
194        FillType(int ni) {
195            nativeInt = ni;
196        }
197
198        final int nativeInt;
199    }
200
201    // these must be in the same order as their native values
202    static final FillType[] sFillTypeArray = {
203        FillType.WINDING,
204        FillType.EVEN_ODD,
205        FillType.INVERSE_WINDING,
206        FillType.INVERSE_EVEN_ODD
207    };
208
209    /**
210     * Return the path's fill type. This defines how "inside" is
211     * computed. The default value is WINDING.
212     *
213     * @return the path's fill type
214     */
215    public FillType getFillType() {
216        return sFillTypeArray[native_getFillType(mNativePath)];
217    }
218
219    /**
220     * Set the path's fill type. This defines how "inside" is computed.
221     *
222     * @param ft The new fill type for this path
223     */
224    public void setFillType(FillType ft) {
225        native_setFillType(mNativePath, ft.nativeInt);
226    }
227
228    /**
229     * Returns true if the filltype is one of the INVERSE variants
230     *
231     * @return true if the filltype is one of the INVERSE variants
232     */
233    public boolean isInverseFillType() {
234        final int ft = native_getFillType(mNativePath);
235        return (ft & 2) != 0;
236    }
237
238    /**
239     * Toggles the INVERSE state of the filltype
240     */
241    public void toggleInverseFillType() {
242        int ft = native_getFillType(mNativePath);
243        ft ^= 2;
244        native_setFillType(mNativePath, ft);
245    }
246
247    /**
248     * Returns true if the path is empty (contains no lines or curves)
249     *
250     * @return true if the path is empty (contains no lines or curves)
251     */
252    public boolean isEmpty() {
253        return native_isEmpty(mNativePath);
254    }
255
256    /**
257     * Returns true if the path specifies a rectangle. If so, and if rect is
258     * not null, set rect to the bounds of the path. If the path does not
259     * specify a rectangle, return false and ignore rect.
260     *
261     * @param rect If not null, returns the bounds of the path if it specifies
262     *             a rectangle
263     * @return     true if the path specifies a rectangle
264     */
265    public boolean isRect(RectF rect) {
266        return native_isRect(mNativePath, rect);
267    }
268
269    /**
270     * Compute the bounds of the control points of the path, and write the
271     * answer into bounds. If the path contains 0 or 1 points, the bounds is
272     * set to (0,0,0,0)
273     *
274     * @param bounds Returns the computed bounds of the path's control points.
275     * @param exact This parameter is no longer used.
276     */
277    @SuppressWarnings({"UnusedDeclaration"})
278    public void computeBounds(RectF bounds, boolean exact) {
279        native_computeBounds(mNativePath, bounds);
280    }
281
282    /**
283     * Hint to the path to prepare for adding more points. This can allow the
284     * path to more efficiently allocate its storage.
285     *
286     * @param extraPtCount The number of extra points that may be added to this
287     *                     path
288     */
289    public void incReserve(int extraPtCount) {
290        native_incReserve(mNativePath, extraPtCount);
291    }
292
293    /**
294     * Set the beginning of the next contour to the point (x,y).
295     *
296     * @param x The x-coordinate of the start of a new contour
297     * @param y The y-coordinate of the start of a new contour
298     */
299    public void moveTo(float x, float y) {
300        native_moveTo(mNativePath, x, y);
301    }
302
303    /**
304     * Set the beginning of the next contour relative to the last point on the
305     * previous contour. If there is no previous contour, this is treated the
306     * same as moveTo().
307     *
308     * @param dx The amount to add to the x-coordinate of the end of the
309     *           previous contour, to specify the start of a new contour
310     * @param dy The amount to add to the y-coordinate of the end of the
311     *           previous contour, to specify the start of a new contour
312     */
313    public void rMoveTo(float dx, float dy) {
314        native_rMoveTo(mNativePath, dx, dy);
315    }
316
317    /**
318     * Add a line from the last point to the specified point (x,y).
319     * If no moveTo() call has been made for this contour, the first point is
320     * automatically set to (0,0).
321     *
322     * @param x The x-coordinate of the end of a line
323     * @param y The y-coordinate of the end of a line
324     */
325    public void lineTo(float x, float y) {
326        isSimplePath = false;
327        native_lineTo(mNativePath, x, y);
328    }
329
330    /**
331     * Same as lineTo, but the coordinates are considered relative to the last
332     * point on this contour. If there is no previous point, then a moveTo(0,0)
333     * is inserted automatically.
334     *
335     * @param dx The amount to add to the x-coordinate of the previous point on
336     *           this contour, to specify a line
337     * @param dy The amount to add to the y-coordinate of the previous point on
338     *           this contour, to specify a line
339     */
340    public void rLineTo(float dx, float dy) {
341        isSimplePath = false;
342        native_rLineTo(mNativePath, dx, dy);
343    }
344
345    /**
346     * Add a quadratic bezier from the last point, approaching control point
347     * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
348     * this contour, the first point is automatically set to (0,0).
349     *
350     * @param x1 The x-coordinate of the control point on a quadratic curve
351     * @param y1 The y-coordinate of the control point on a quadratic curve
352     * @param x2 The x-coordinate of the end point on a quadratic curve
353     * @param y2 The y-coordinate of the end point on a quadratic curve
354     */
355    public void quadTo(float x1, float y1, float x2, float y2) {
356        isSimplePath = false;
357        native_quadTo(mNativePath, x1, y1, x2, y2);
358    }
359
360    /**
361     * Same as quadTo, but the coordinates are considered relative to the last
362     * point on this contour. If there is no previous point, then a moveTo(0,0)
363     * is inserted automatically.
364     *
365     * @param dx1 The amount to add to the x-coordinate of the last point on
366     *            this contour, for the control point of a quadratic curve
367     * @param dy1 The amount to add to the y-coordinate of the last point on
368     *            this contour, for the control point of a quadratic curve
369     * @param dx2 The amount to add to the x-coordinate of the last point on
370     *            this contour, for the end point of a quadratic curve
371     * @param dy2 The amount to add to the y-coordinate of the last point on
372     *            this contour, for the end point of a quadratic curve
373     */
374    public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
375        isSimplePath = false;
376        native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
377    }
378
379    /**
380     * Add a cubic bezier from the last point, approaching control points
381     * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
382     * made for this contour, the first point is automatically set to (0,0).
383     *
384     * @param x1 The x-coordinate of the 1st control point on a cubic curve
385     * @param y1 The y-coordinate of the 1st control point on a cubic curve
386     * @param x2 The x-coordinate of the 2nd control point on a cubic curve
387     * @param y2 The y-coordinate of the 2nd control point on a cubic curve
388     * @param x3 The x-coordinate of the end point on a cubic curve
389     * @param y3 The y-coordinate of the end point on a cubic curve
390     */
391    public void cubicTo(float x1, float y1, float x2, float y2,
392                        float x3, float y3) {
393        isSimplePath = false;
394        native_cubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
395    }
396
397    /**
398     * Same as cubicTo, but the coordinates are considered relative to the
399     * current point on this contour. If there is no previous point, then a
400     * moveTo(0,0) is inserted automatically.
401     */
402    public void rCubicTo(float x1, float y1, float x2, float y2,
403                         float x3, float y3) {
404        isSimplePath = false;
405        native_rCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
406    }
407
408    /**
409     * Append the specified arc to the path as a new contour. If the start of
410     * the path is different from the path's current last point, then an
411     * automatic lineTo() is added to connect the current contour to the
412     * start of the arc. However, if the path is empty, then we call moveTo()
413     * with the first point of the arc. The sweep angle is tread mod 360.
414     *
415     * @param oval        The bounds of oval defining shape and size of the arc
416     * @param startAngle  Starting angle (in degrees) where the arc begins
417     * @param sweepAngle  Sweep angle (in degrees) measured clockwise, treated
418     *                    mod 360.
419     * @param forceMoveTo If true, always begin a new contour with the arc
420     */
421    public void arcTo(RectF oval, float startAngle, float sweepAngle,
422                      boolean forceMoveTo) {
423        isSimplePath = false;
424        native_arcTo(mNativePath, oval, startAngle, sweepAngle, forceMoveTo);
425    }
426
427    /**
428     * Append the specified arc to the path as a new contour. If the start of
429     * the path is different from the path's current last point, then an
430     * automatic lineTo() is added to connect the current contour to the
431     * start of the arc. However, if the path is empty, then we call moveTo()
432     * with the first point of the arc.
433     *
434     * @param oval        The bounds of oval defining shape and size of the arc
435     * @param startAngle  Starting angle (in degrees) where the arc begins
436     * @param sweepAngle  Sweep angle (in degrees) measured clockwise
437     */
438    public void arcTo(RectF oval, float startAngle, float sweepAngle) {
439        isSimplePath = false;
440        native_arcTo(mNativePath, oval, startAngle, sweepAngle, false);
441    }
442
443    /**
444     * Close the current contour. If the current point is not equal to the
445     * first point of the contour, a line segment is automatically added.
446     */
447    public void close() {
448        isSimplePath = false;
449        native_close(mNativePath);
450    }
451
452    /**
453     * Specifies how closed shapes (e.g. rects, ovals) are oriented when they
454     * are added to a path.
455     */
456    public enum Direction {
457        /** clockwise */
458        CW  (1),    // must match enum in SkPath.h
459        /** counter-clockwise */
460        CCW (2);    // must match enum in SkPath.h
461
462        Direction(int ni) {
463            nativeInt = ni;
464        }
465        final int nativeInt;
466    }
467
468    private void detectSimplePath(float left, float top, float right, float bottom, Direction dir) {
469        if (mLastDirection == null) {
470            mLastDirection = dir;
471        }
472        if (mLastDirection != dir) {
473            isSimplePath = false;
474        } else {
475            if (rects == null) rects = new Region();
476            rects.op((int) left, (int) top, (int) right, (int) bottom, Region.Op.UNION);
477        }
478    }
479
480    /**
481     * Add a closed rectangle contour to the path
482     *
483     * @param rect The rectangle to add as a closed contour to the path
484     * @param dir  The direction to wind the rectangle's contour
485     */
486    public void addRect(RectF rect, Direction dir) {
487        if (rect == null) {
488            throw new NullPointerException("need rect parameter");
489        }
490        detectSimplePath(rect.left, rect.top, rect.right, rect.bottom, dir);
491        native_addRect(mNativePath, rect, dir.nativeInt);
492    }
493
494    /**
495     * Add a closed rectangle contour to the path
496     *
497     * @param left   The left side of a rectangle to add to the path
498     * @param top    The top of a rectangle to add to the path
499     * @param right  The right side of a rectangle to add to the path
500     * @param bottom The bottom of a rectangle to add to the path
501     * @param dir    The direction to wind the rectangle's contour
502     */
503    public void addRect(float left, float top, float right, float bottom, Direction dir) {
504        detectSimplePath(left, top, right, bottom, dir);
505        native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt);
506    }
507
508    /**
509     * Add a closed oval contour to the path
510     *
511     * @param oval The bounds of the oval to add as a closed contour to the path
512     * @param dir  The direction to wind the oval's contour
513     */
514    public void addOval(RectF oval, Direction dir) {
515        if (oval == null) {
516            throw new NullPointerException("need oval parameter");
517        }
518        isSimplePath = false;
519        native_addOval(mNativePath, oval, dir.nativeInt);
520    }
521
522    /**
523     * Add a closed circle contour to the path
524     *
525     * @param x   The x-coordinate of the center of a circle to add to the path
526     * @param y   The y-coordinate of the center of a circle to add to the path
527     * @param radius The radius of a circle to add to the path
528     * @param dir    The direction to wind the circle's contour
529     */
530    public void addCircle(float x, float y, float radius, Direction dir) {
531        isSimplePath = false;
532        native_addCircle(mNativePath, x, y, radius, dir.nativeInt);
533    }
534
535    /**
536     * Add the specified arc to the path as a new contour.
537     *
538     * @param oval The bounds of oval defining the shape and size of the arc
539     * @param startAngle Starting angle (in degrees) where the arc begins
540     * @param sweepAngle Sweep angle (in degrees) measured clockwise
541     */
542    public void addArc(RectF oval, float startAngle, float sweepAngle) {
543        if (oval == null) {
544            throw new NullPointerException("need oval parameter");
545        }
546        isSimplePath = false;
547        native_addArc(mNativePath, oval, startAngle, sweepAngle);
548    }
549
550    /**
551        * Add a closed round-rectangle contour to the path
552     *
553     * @param rect The bounds of a round-rectangle to add to the path
554     * @param rx   The x-radius of the rounded corners on the round-rectangle
555     * @param ry   The y-radius of the rounded corners on the round-rectangle
556     * @param dir  The direction to wind the round-rectangle's contour
557     */
558    public void addRoundRect(RectF rect, float rx, float ry, Direction dir) {
559        if (rect == null) {
560            throw new NullPointerException("need rect parameter");
561        }
562        isSimplePath = false;
563        native_addRoundRect(mNativePath, rect, rx, ry, dir.nativeInt);
564    }
565
566    /**
567     * Add a closed round-rectangle contour to the path. Each corner receives
568     * two radius values [X, Y]. The corners are ordered top-left, top-right,
569     * bottom-right, bottom-left
570     *
571     * @param rect The bounds of a round-rectangle to add to the path
572     * @param radii Array of 8 values, 4 pairs of [X,Y] radii
573     * @param dir  The direction to wind the round-rectangle's contour
574     */
575    public void addRoundRect(RectF rect, float[] radii, Direction dir) {
576        if (rect == null) {
577            throw new NullPointerException("need rect parameter");
578        }
579        if (radii.length < 8) {
580            throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
581        }
582        isSimplePath = false;
583        native_addRoundRect(mNativePath, rect, radii, dir.nativeInt);
584    }
585
586    /**
587     * Add a copy of src to the path, offset by (dx,dy)
588     *
589     * @param src The path to add as a new contour
590     * @param dx  The amount to translate the path in X as it is added
591     */
592    public void addPath(Path src, float dx, float dy) {
593        isSimplePath = false;
594        native_addPath(mNativePath, src.mNativePath, dx, dy);
595    }
596
597    /**
598     * Add a copy of src to the path
599     *
600     * @param src The path that is appended to the current path
601     */
602    public void addPath(Path src) {
603        isSimplePath = false;
604        native_addPath(mNativePath, src.mNativePath);
605    }
606
607    /**
608     * Add a copy of src to the path, transformed by matrix
609     *
610     * @param src The path to add as a new contour
611     */
612    public void addPath(Path src, Matrix matrix) {
613        if (!src.isSimplePath) isSimplePath = false;
614        native_addPath(mNativePath, src.mNativePath, matrix.native_instance);
615    }
616
617    /**
618     * Offset the path by (dx,dy), returning true on success
619     *
620     * @param dx  The amount in the X direction to offset the entire path
621     * @param dy  The amount in the Y direction to offset the entire path
622     * @param dst The translated path is written here. If this is null, then
623     *            the original path is modified.
624     */
625    public void offset(float dx, float dy, Path dst) {
626        int dstNative = 0;
627        if (dst != null) {
628            dstNative = dst.mNativePath;
629            dst.isSimplePath = false;
630        }
631        native_offset(mNativePath, dx, dy, dstNative);
632    }
633
634    /**
635     * Offset the path by (dx,dy), returning true on success
636     *
637     * @param dx The amount in the X direction to offset the entire path
638     * @param dy The amount in the Y direction to offset the entire path
639     */
640    public void offset(float dx, float dy) {
641        isSimplePath = false;
642        native_offset(mNativePath, dx, dy);
643    }
644
645    /**
646     * Sets the last point of the path.
647     *
648     * @param dx The new X coordinate for the last point
649     * @param dy The new Y coordinate for the last point
650     */
651    public void setLastPoint(float dx, float dy) {
652        isSimplePath = false;
653        native_setLastPoint(mNativePath, dx, dy);
654    }
655
656    /**
657     * Transform the points in this path by matrix, and write the answer
658     * into dst. If dst is null, then the the original path is modified.
659     *
660     * @param matrix The matrix to apply to the path
661     * @param dst    The transformed path is written here. If dst is null,
662     *               then the the original path is modified
663     */
664    public void transform(Matrix matrix, Path dst) {
665        int dstNative = 0;
666        if (dst != null) {
667            dst.isSimplePath = false;
668            dstNative = dst.mNativePath;
669        }
670        native_transform(mNativePath, matrix.native_instance, dstNative);
671    }
672
673    /**
674     * Transform the points in this path by matrix.
675     *
676     * @param matrix The matrix to apply to the path
677     */
678    public void transform(Matrix matrix) {
679        isSimplePath = false;
680        native_transform(mNativePath, matrix.native_instance);
681    }
682
683    protected void finalize() throws Throwable {
684        try {
685            finalizer(mNativePath);
686        } finally {
687            super.finalize();
688        }
689    }
690
691    final int ni() {
692        return mNativePath;
693    }
694
695    /**
696     * Approximate the <code>Path</code> with a series of line segments.
697     * This returns float[] with the array containing point components.
698     * There are three components for each point, in order:
699     * <ul>
700     *     <li>Fraction along the length of the path that the point resides</li>
701     *     <li>The x coordinate of the point</li>
702     *     <li>The y coordinate of the point</li>
703     * </ul>
704     * <p>Two points may share the same fraction along its length when there is
705     * a move action within the Path.</p>
706     *
707     * @param acceptableError The acceptable error for a line on the
708     *                        Path. Typically this would be 0.5 so that
709     *                        the error is less than half a pixel.
710     * @return An array of components for points approximating the Path.
711     * @hide
712     */
713    public float[] approximate(float acceptableError) {
714        return native_approximate(mNativePath, acceptableError);
715    }
716
717    private static native int init1();
718    private static native int init2(int nPath);
719    private static native void native_reset(int nPath);
720    private static native void native_rewind(int nPath);
721    private static native void native_set(int native_dst, int native_src);
722    private static native int native_getFillType(int nPath);
723    private static native void native_setFillType(int nPath, int ft);
724    private static native boolean native_isEmpty(int nPath);
725    private static native boolean native_isRect(int nPath, RectF rect);
726    private static native void native_computeBounds(int nPath, RectF bounds);
727    private static native void native_incReserve(int nPath, int extraPtCount);
728    private static native void native_moveTo(int nPath, float x, float y);
729    private static native void native_rMoveTo(int nPath, float dx, float dy);
730    private static native void native_lineTo(int nPath, float x, float y);
731    private static native void native_rLineTo(int nPath, float dx, float dy);
732    private static native void native_quadTo(int nPath, float x1, float y1,
733                                             float x2, float y2);
734    private static native void native_rQuadTo(int nPath, float dx1, float dy1,
735                                              float dx2, float dy2);
736    private static native void native_cubicTo(int nPath, float x1, float y1,
737                                        float x2, float y2, float x3, float y3);
738    private static native void native_rCubicTo(int nPath, float x1, float y1,
739                                        float x2, float y2, float x3, float y3);
740    private static native void native_arcTo(int nPath, RectF oval,
741                    float startAngle, float sweepAngle, boolean forceMoveTo);
742    private static native void native_close(int nPath);
743    private static native void native_addRect(int nPath, RectF rect, int dir);
744    private static native void native_addRect(int nPath, float left, float top,
745                                            float right, float bottom, int dir);
746    private static native void native_addOval(int nPath, RectF oval, int dir);
747    private static native void native_addCircle(int nPath, float x, float y, float radius, int dir);
748    private static native void native_addArc(int nPath, RectF oval,
749                                            float startAngle, float sweepAngle);
750    private static native void native_addRoundRect(int nPath, RectF rect,
751                                                   float rx, float ry, int dir);
752    private static native void native_addRoundRect(int nPath, RectF r, float[] radii, int dir);
753    private static native void native_addPath(int nPath, int src, float dx, float dy);
754    private static native void native_addPath(int nPath, int src);
755    private static native void native_addPath(int nPath, int src, int matrix);
756    private static native void native_offset(int nPath, float dx, float dy, int dst_path);
757    private static native void native_offset(int nPath, float dx, float dy);
758    private static native void native_setLastPoint(int nPath, float dx, float dy);
759    private static native void native_transform(int nPath, int matrix, int dst_path);
760    private static native void native_transform(int nPath, int matrix);
761    private static native boolean native_op(int path1, int path2, int op, int result);
762    private static native void finalizer(int nPath);
763    private static native float[] native_approximate(int nPath, float error);
764}
765