• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     /**
29      * Create an empty path
30      */
Path()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      */
Path(Path src)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      */
reset()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      */
rewind()60     public void rewind() {
61         native_rewind(mNativePath);
62     }
63 
64     /** Replace the contents of this with the contents of src.
65     */
set(Path src)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 
FillType(int ni)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      */
getFillType()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      */
setFillType(FillType ft)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      */
isInverseFillType()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      */
toggleInverseFillType()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      */
isEmpty()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      */
isRect(RectF rect)151     public boolean isRect(RectF rect) {
152         return native_isRect(mNativePath, rect);
153     }
154 
155     /**
156      * Compute the bounds of the control points of the path, and write the
157      * answer into bounds. If the path contains 0 or 1 points, the bounds is
158      * set to (0,0,0,0)
159      *
160      * @param bounds Returns the computed bounds of the path's control points.
161      * @param exact This parameter is no longer used.
162      */
computeBounds(RectF bounds, boolean exact)163     public void computeBounds(RectF bounds, boolean exact) {
164         native_computeBounds(mNativePath, bounds);
165     }
166 
167     /**
168      * Hint to the path to prepare for adding more points. This can allow the
169      * path to more efficiently allocate its storage.
170      *
171      * @param extraPtCount The number of extra points that may be added to this
172      *                     path
173      */
incReserve(int extraPtCount)174     public void incReserve(int extraPtCount) {
175         native_incReserve(mNativePath, extraPtCount);
176     }
177 
178     /**
179      * Set the beginning of the next contour to the point (x,y).
180      *
181      * @param x The x-coordinate of the start of a new contour
182      * @param y The y-coordinate of the start of a new contour
183      */
moveTo(float x, float y)184     public void moveTo(float x, float y) {
185         native_moveTo(mNativePath, x, y);
186     }
187 
188     /**
189      * Set the beginning of the next contour relative to the last point on the
190      * previous contour. If there is no previous contour, this is treated the
191      * same as moveTo().
192      *
193      * @param dx The amount to add to the x-coordinate of the end of the
194      *           previous contour, to specify the start of a new contour
195      * @param dy The amount to add to the y-coordinate of the end of the
196      *           previous contour, to specify the start of a new contour
197      */
rMoveTo(float dx, float dy)198     public void rMoveTo(float dx, float dy) {
199         native_rMoveTo(mNativePath, dx, dy);
200     }
201 
202     /**
203      * Add a line from the last point to the specified point (x,y).
204      * If no moveTo() call has been made for this contour, the first point is
205      * automatically set to (0,0).
206      *
207      * @param x The x-coordinate of the end of a line
208      * @param y The y-coordinate of the end of a line
209      */
lineTo(float x, float y)210     public void lineTo(float x, float y) {
211         native_lineTo(mNativePath, x, y);
212     }
213 
214     /**
215      * Same as lineTo, but the coordinates are considered relative to the last
216      * point on this contour. If there is no previous point, then a moveTo(0,0)
217      * is inserted automatically.
218      *
219      * @param dx The amount to add to the x-coordinate of the previous point on
220      *           this contour, to specify a line
221      * @param dy The amount to add to the y-coordinate of the previous point on
222      *           this contour, to specify a line
223      */
rLineTo(float dx, float dy)224     public void rLineTo(float dx, float dy) {
225         native_rLineTo(mNativePath, dx, dy);
226     }
227 
228     /**
229      * Add a quadratic bezier from the last point, approaching control point
230      * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
231      * this contour, the first point is automatically set to (0,0).
232      *
233      * @param x1 The x-coordinate of the control point on a quadratic curve
234      * @param y1 The y-coordinate of the control point on a quadratic curve
235      * @param x2 The x-coordinate of the end point on a quadratic curve
236      * @param y2 The y-coordinate of the end point on a quadratic curve
237      */
quadTo(float x1, float y1, float x2, float y2)238     public void quadTo(float x1, float y1, float x2, float y2) {
239         native_quadTo(mNativePath, x1, y1, x2, y2);
240     }
241 
242     /**
243      * Same as quadTo, but the coordinates are considered relative to the last
244      * point on this contour. If there is no previous point, then a moveTo(0,0)
245      * is inserted automatically.
246      *
247      * @param dx1 The amount to add to the x-coordinate of the last point on
248      *            this contour, for the control point of a quadratic curve
249      * @param dy1 The amount to add to the y-coordinate of the last point on
250      *            this contour, for the control point of a quadratic curve
251      * @param dx2 The amount to add to the x-coordinate of the last point on
252      *            this contour, for the end point of a quadratic curve
253      * @param dy2 The amount to add to the y-coordinate of the last point on
254      *            this contour, for the end point of a quadratic curve
255      */
rQuadTo(float dx1, float dy1, float dx2, float dy2)256     public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
257         native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
258     }
259 
260     /**
261      * Add a cubic bezier from the last point, approaching control points
262      * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
263      * made for this contour, the first point is automatically set to (0,0).
264      *
265      * @param x1 The x-coordinate of the 1st control point on a cubic curve
266      * @param y1 The y-coordinate of the 1st control point on a cubic curve
267      * @param x2 The x-coordinate of the 2nd control point on a cubic curve
268      * @param y2 The y-coordinate of the 2nd control point on a cubic curve
269      * @param x3 The x-coordinate of the end point on a cubic curve
270      * @param y3 The y-coordinate of the end point on a cubic curve
271      */
cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)272     public void cubicTo(float x1, float y1, float x2, float y2,
273                         float x3, float y3) {
274         native_cubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
275     }
276 
277     /**
278      * Same as cubicTo, but the coordinates are considered relative to the
279      * current point on this contour. If there is no previous point, then a
280      * moveTo(0,0) is inserted automatically.
281      */
rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)282     public void rCubicTo(float x1, float y1, float x2, float y2,
283                          float x3, float y3) {
284         native_rCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
285     }
286 
287     /**
288      * Append the specified arc to the path as a new contour. If the start of
289      * the path is different from the path's current last point, then an
290      * automatic lineTo() is added to connect the current contour to the
291      * start of the arc. However, if the path is empty, then we call moveTo()
292      * with the first point of the arc. The sweep angle is tread mod 360.
293      *
294      * @param oval        The bounds of oval defining shape and size of the arc
295      * @param startAngle  Starting angle (in degrees) where the arc begins
296      * @param sweepAngle  Sweep angle (in degrees) measured clockwise, treated
297      *                    mod 360.
298      * @param forceMoveTo If true, always begin a new contour with the arc
299      */
arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)300     public void arcTo(RectF oval, float startAngle, float sweepAngle,
301                       boolean forceMoveTo) {
302         native_arcTo(mNativePath, oval, startAngle, sweepAngle, forceMoveTo);
303     }
304 
305     /**
306      * Append the specified arc to the path as a new contour. If the start of
307      * the path is different from the path's current last point, then an
308      * automatic lineTo() is added to connect the current contour to the
309      * start of the arc. However, if the path is empty, then we call moveTo()
310      * with the first point of the arc.
311      *
312      * @param oval        The bounds of oval defining shape and size of the arc
313      * @param startAngle  Starting angle (in degrees) where the arc begins
314      * @param sweepAngle  Sweep angle (in degrees) measured clockwise
315      */
arcTo(RectF oval, float startAngle, float sweepAngle)316     public void arcTo(RectF oval, float startAngle, float sweepAngle) {
317         native_arcTo(mNativePath, oval, startAngle, sweepAngle, false);
318     }
319 
320     /**
321      * Close the current contour. If the current point is not equal to the
322      * first point of the contour, a line segment is automatically added.
323      */
close()324     public void close() {
325         native_close(mNativePath);
326     }
327 
328     /**
329      * Specifies how closed shapes (e.g. rects, ovals) are oriented when they
330      * are added to a path.
331      */
332     public enum Direction {
333         /** clockwise */
334         CW  (0),    // must match enum in SkPath.h
335         /** counter-clockwise */
336         CCW (1);    // must match enum in SkPath.h
337 
Direction(int ni)338         Direction(int ni) {
339             nativeInt = ni;
340         }
341         final int nativeInt;
342     }
343 
344     /**
345      * Add a closed rectangle contour to the path
346      *
347      * @param rect The rectangle to add as a closed contour to the path
348      * @param dir  The direction to wind the rectangle's contour
349      */
addRect(RectF rect, Direction dir)350     public void addRect(RectF rect, Direction dir) {
351         if (rect == null) {
352             throw new NullPointerException("need rect parameter");
353         }
354         native_addRect(mNativePath, rect, dir.nativeInt);
355     }
356 
357     /**
358      * Add a closed rectangle contour to the path
359      *
360      * @param left   The left side of a rectangle to add to the path
361      * @param top    The top of a rectangle to add to the path
362      * @param right  The right side of a rectangle to add to the path
363      * @param bottom The bottom of a rectangle to add to the path
364      * @param dir    The direction to wind the rectangle's contour
365      */
addRect(float left, float top, float right, float bottom, Direction dir)366     public void addRect(float left, float top, float right, float bottom,
367                         Direction dir) {
368         native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt);
369     }
370 
371     /**
372      * Add a closed oval contour to the path
373      *
374      * @param oval The bounds of the oval to add as a closed contour to the path
375      * @param dir  The direction to wind the oval's contour
376      */
addOval(RectF oval, Direction dir)377     public void addOval(RectF oval, Direction dir) {
378         if (oval == null) {
379             throw new NullPointerException("need oval parameter");
380         }
381         native_addOval(mNativePath, oval, dir.nativeInt);
382     }
383 
384     /**
385      * Add a closed circle contour to the path
386      *
387      * @param x   The x-coordinate of the center of a circle to add to the path
388      * @param y   The y-coordinate of the center of a circle to add to the path
389      * @param radius The radius of a circle to add to the path
390      * @param dir    The direction to wind the circle's contour
391      */
addCircle(float x, float y, float radius, Direction dir)392     public void addCircle(float x, float y, float radius, Direction dir) {
393         native_addCircle(mNativePath, x, y, radius, dir.nativeInt);
394     }
395 
396     /**
397      * Add the specified arc to the path as a new contour.
398      *
399      * @param oval The bounds of oval defining the shape and size of the arc
400      * @param startAngle Starting angle (in degrees) where the arc begins
401      * @param sweepAngle Sweep angle (in degrees) measured clockwise
402      */
addArc(RectF oval, float startAngle, float sweepAngle)403     public void addArc(RectF oval, float startAngle, float sweepAngle) {
404         if (oval == null) {
405             throw new NullPointerException("need oval parameter");
406         }
407         native_addArc(mNativePath, oval, startAngle, sweepAngle);
408     }
409 
410     /**
411         * Add a closed round-rectangle contour to the path
412      *
413      * @param rect The bounds of a round-rectangle to add to the path
414      * @param rx   The x-radius of the rounded corners on the round-rectangle
415      * @param ry   The y-radius of the rounded corners on the round-rectangle
416      * @param dir  The direction to wind the round-rectangle's contour
417      */
addRoundRect(RectF rect, float rx, float ry, Direction dir)418     public void addRoundRect(RectF rect, float rx, float ry, Direction dir) {
419         if (rect == null) {
420             throw new NullPointerException("need rect parameter");
421         }
422         native_addRoundRect(mNativePath, rect, rx, ry, dir.nativeInt);
423     }
424 
425     /**
426      * Add a closed round-rectangle contour to the path. Each corner receives
427      * two radius values [X, Y]. The corners are ordered top-left, top-right,
428      * bottom-right, bottom-left
429      *
430      * @param rect The bounds of a round-rectangle to add to the path
431      * @param radii Array of 8 values, 4 pairs of [X,Y] radii
432      * @param dir  The direction to wind the round-rectangle's contour
433      */
addRoundRect(RectF rect, float[] radii, Direction dir)434     public void addRoundRect(RectF rect, float[] radii, Direction dir) {
435         if (rect == null) {
436             throw new NullPointerException("need rect parameter");
437         }
438         if (radii.length < 8) {
439             throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
440         }
441         native_addRoundRect(mNativePath, rect, radii, dir.nativeInt);
442     }
443 
444     /**
445      * Add a copy of src to the path, offset by (dx,dy)
446      *
447      * @param src The path to add as a new contour
448      * @param dx  The amount to translate the path in X as it is added
449      */
addPath(Path src, float dx, float dy)450     public void addPath(Path src, float dx, float dy) {
451         native_addPath(mNativePath, src.mNativePath, dx, dy);
452     }
453 
454     /**
455      * Add a copy of src to the path
456      *
457      * @param src The path that is appended to the current path
458      */
addPath(Path src)459     public void addPath(Path src) {
460         native_addPath(mNativePath, src.mNativePath);
461     }
462 
463     /**
464      * Add a copy of src to the path, transformed by matrix
465      *
466      * @param src The path to add as a new contour
467      */
addPath(Path src, Matrix matrix)468     public void addPath(Path src, Matrix matrix) {
469         native_addPath(mNativePath, src.mNativePath, matrix.native_instance);
470     }
471 
472     /**
473      * Offset the path by (dx,dy), returning true on success
474      *
475      * @param dx  The amount in the X direction to offset the entire path
476      * @param dy  The amount in the Y direction to offset the entire path
477      * @param dst The translated path is written here. If this is null, then
478      *            the original path is modified.
479      */
offset(float dx, float dy, Path dst)480     public void offset(float dx, float dy, Path dst) {
481         int dstNative = 0;
482         if (dst != null) {
483             dstNative = dst.mNativePath;
484         }
485         native_offset(mNativePath, dx, dy, dstNative);
486     }
487 
488     /**
489      * Offset the path by (dx,dy), returning true on success
490      *
491      * @param dx The amount in the X direction to offset the entire path
492      * @param dy The amount in the Y direction to offset the entire path
493      */
offset(float dx, float dy)494     public void offset(float dx, float dy) {
495         native_offset(mNativePath, dx, dy);
496     }
497 
498     /**
499      * Sets the last point of the path.
500      *
501      * @param dx The new X coordinate for the last point
502      * @param dy The new Y coordinate for the last point
503      */
setLastPoint(float dx, float dy)504     public void setLastPoint(float dx, float dy) {
505         native_setLastPoint(mNativePath, dx, dy);
506     }
507 
508     /**
509      * Transform the points in this path by matrix, and write the answer
510      * into dst. If dst is null, then the the original path is modified.
511      *
512      * @param matrix The matrix to apply to the path
513      * @param dst    The transformed path is written here. If dst is null,
514      *               then the the original path is modified
515      */
transform(Matrix matrix, Path dst)516     public void transform(Matrix matrix, Path dst) {
517         int dstNative = 0;
518         if (dst != null) {
519             dstNative = dst.mNativePath;
520         }
521         native_transform(mNativePath, matrix.native_instance, dstNative);
522     }
523 
524     /**
525      * Transform the points in this path by matrix.
526      *
527      * @param matrix The matrix to apply to the path
528      */
transform(Matrix matrix)529     public void transform(Matrix matrix) {
530         native_transform(mNativePath, matrix.native_instance);
531     }
532 
finalize()533     protected void finalize() throws Throwable {
534         try {
535             finalizer(mNativePath);
536         } finally {
537             super.finalize();
538         }
539     }
540 
ni()541     /*package*/ final int ni() {
542         return mNativePath;
543     }
544 
init1()545     private static native int init1();
init2(int nPath)546     private static native int init2(int nPath);
native_reset(int nPath)547     private static native void native_reset(int nPath);
native_rewind(int nPath)548     private static native void native_rewind(int nPath);
native_set(int native_dst, int native_src)549     private static native void native_set(int native_dst, int native_src);
native_getFillType(int nPath)550     private static native int native_getFillType(int nPath);
native_setFillType(int nPath, int ft)551     private static native void native_setFillType(int nPath, int ft);
native_isEmpty(int nPath)552     private static native boolean native_isEmpty(int nPath);
native_isRect(int nPath, RectF rect)553     private static native boolean native_isRect(int nPath, RectF rect);
native_computeBounds(int nPath, RectF bounds)554     private static native void native_computeBounds(int nPath, RectF bounds);
native_incReserve(int nPath, int extraPtCount)555     private static native void native_incReserve(int nPath, int extraPtCount);
native_moveTo(int nPath, float x, float y)556     private static native void native_moveTo(int nPath, float x, float y);
native_rMoveTo(int nPath, float dx, float dy)557     private static native void native_rMoveTo(int nPath, float dx, float dy);
native_lineTo(int nPath, float x, float y)558     private static native void native_lineTo(int nPath, float x, float y);
native_rLineTo(int nPath, float dx, float dy)559     private static native void native_rLineTo(int nPath, float dx, float dy);
native_quadTo(int nPath, float x1, float y1, float x2, float y2)560     private static native void native_quadTo(int nPath, float x1, float y1,
561                                              float x2, float y2);
native_rQuadTo(int nPath, float dx1, float dy1, float dx2, float dy2)562     private static native void native_rQuadTo(int nPath, float dx1, float dy1,
563                                               float dx2, float dy2);
native_cubicTo(int nPath, float x1, float y1, float x2, float y2, float x3, float y3)564     private static native void native_cubicTo(int nPath, float x1, float y1,
565                                         float x2, float y2, float x3, float y3);
native_rCubicTo(int nPath, float x1, float y1, float x2, float y2, float x3, float y3)566     private static native void native_rCubicTo(int nPath, float x1, float y1,
567                                         float x2, float y2, float x3, float y3);
native_arcTo(int nPath, RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)568     private static native void native_arcTo(int nPath, RectF oval,
569                     float startAngle, float sweepAngle, boolean forceMoveTo);
native_close(int nPath)570     private static native void native_close(int nPath);
native_addRect(int nPath, RectF rect, int dir)571     private static native void native_addRect(int nPath, RectF rect, int dir);
native_addRect(int nPath, float left, float top, float right, float bottom, int dir)572     private static native void native_addRect(int nPath, float left, float top,
573                                             float right, float bottom, int dir);
native_addOval(int nPath, RectF oval, int dir)574     private static native void native_addOval(int nPath, RectF oval, int dir);
native_addCircle(int nPath, float x, float y, float radius, int dir)575     private static native void native_addCircle(int nPath, float x, float y,
576                                                 float radius, int dir);
native_addArc(int nPath, RectF oval, float startAngle, float sweepAngle)577     private static native void native_addArc(int nPath, RectF oval,
578                                             float startAngle, float sweepAngle);
native_addRoundRect(int nPath, RectF rect, float rx, float ry, int dir)579     private static native void native_addRoundRect(int nPath, RectF rect,
580                                                    float rx, float ry, int dir);
native_addRoundRect(int nPath, RectF r, float[] radii, int dir)581     private static native void native_addRoundRect(int nPath, RectF r,
582                                                    float[] radii, int dir);
native_addPath(int nPath, int src, float dx, float dy)583     private static native void native_addPath(int nPath, int src, float dx,
584                                               float dy);
native_addPath(int nPath, int src)585     private static native void native_addPath(int nPath, int src);
native_addPath(int nPath, int src, int matrix)586     private static native void native_addPath(int nPath, int src, int matrix);
native_offset(int nPath, float dx, float dy, int dst_path)587     private static native void native_offset(int nPath, float dx, float dy,
588                                              int dst_path);
native_offset(int nPath, float dx, float dy)589     private static native void native_offset(int nPath, float dx, float dy);
native_setLastPoint(int nPath, float dx, float dy)590     private static native void native_setLastPoint(int nPath, float dx, float dy);
native_transform(int nPath, int matrix, int dst_path)591     private static native void native_transform(int nPath, int matrix,
592                                                 int dst_path);
native_transform(int nPath, int matrix)593     private static native void native_transform(int nPath, int matrix);
finalizer(int nPath)594     private static native void finalizer(int nPath);
595 
596     private final int mNativePath;
597 }
598