• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 @android.ravenwood.annotation.RavenwoodKeepWholeClass
20 public class PathMeasure {
21     private Path mPath;
22 
23     /**
24      * Create an empty PathMeasure object. To uses this to measure the length
25      * of a path, and/or to find the position and tangent along it, call
26      * setPath.
27      *
28      * Note that once a path is associated with the measure object, it is
29      * undefined if the path is subsequently modified and the measure object
30      * is used. If the path is modified, you must call setPath with the path.
31      */
PathMeasure()32     public PathMeasure() {
33         mPath = null;
34         native_instance = native_create(0, false);
35     }
36 
37     /**
38      * Create a PathMeasure object associated with the specified path object
39      * (already created and specified). The measure object can now return the
40      * path's length, and the position and tangent of any position along the
41      * path.
42      *
43      * Note that once a path is associated with the measure object, it is
44      * undefined if the path is subsequently modified and the measure object
45      * is used. If the path is modified, you must call setPath with the path.
46      *
47      * @param path The path that will be measured by this object
48      * @param forceClosed If true, then the path will be considered as "closed"
49      *        even if its contour was not explicitly closed.
50      */
PathMeasure(Path path, boolean forceClosed)51     public PathMeasure(Path path, boolean forceClosed) {
52         // The native implementation does not copy the path, prevent it from being GC'd
53         mPath = path;
54         native_instance = native_create(path != null ? path.readOnlyNI() : 0,
55                                         forceClosed);
56     }
57 
58     /**
59      * Assign a new path, or null to have none.
60      */
setPath(Path path, boolean forceClosed)61     public void setPath(Path path, boolean forceClosed) {
62         mPath = path;
63         native_setPath(native_instance,
64                        path != null ? path.readOnlyNI() : 0,
65                        forceClosed);
66     }
67 
68     /**
69      * Return the total length of the current contour, or 0 if no path is
70      * associated with this measure object.
71      */
getLength()72     public float getLength() {
73         return native_getLength(native_instance);
74     }
75 
76     /**
77      * Pins distance to 0 <= distance <= getLength(), and then computes the
78      * corresponding position and tangent. Returns false if there is no path,
79      * or a zero-length path was specified, in which case position and tangent
80      * are unchanged.
81      *
82      * @param distance The distance along the current contour to sample
83      * @param pos If not null, returns the sampled position (x==[0], y==[1])
84      * @param tan If not null, returns the sampled tangent (x==[0], y==[1])
85      * @return false if there was no path associated with this measure object
86     */
getPosTan(float distance, float pos[], float tan[])87     public boolean getPosTan(float distance, float pos[], float tan[]) {
88         if (pos != null && pos.length < 2 ||
89             tan != null && tan.length < 2) {
90             throw new ArrayIndexOutOfBoundsException();
91         }
92         return native_getPosTan(native_instance, distance, pos, tan);
93     }
94 
95     public static final int POSITION_MATRIX_FLAG = 0x01;    // must match flags in SkPathMeasure.h
96     public static final int TANGENT_MATRIX_FLAG  = 0x02;    // must match flags in SkPathMeasure.h
97 
98     /**
99      * Pins distance to 0 <= distance <= getLength(), and then computes the
100      * corresponding matrix. Returns false if there is no path, or a zero-length
101      * path was specified, in which case matrix is unchanged.
102      *
103      * @param distance The distance along the associated path
104      * @param matrix Allocated by the caller, this is set to the transformation
105      *        associated with the position and tangent at the specified distance
106      * @param flags Specified what aspects should be returned in the matrix.
107      */
getMatrix(float distance, Matrix matrix, int flags)108     public boolean getMatrix(float distance, Matrix matrix, int flags) {
109         return native_getMatrix(native_instance, distance, matrix.ni(), flags);
110     }
111 
112     /**
113      * Given a start and stop distance, return in dst the intervening
114      * segment(s). If the segment is zero-length, return false, else return
115      * true. startD and stopD are pinned to legal values (0..getLength()).
116      * If startD >= stopD then return false (and leave dst untouched).
117      * Begin the segment with a moveTo if startWithMoveTo is true.
118      *
119      * <p>On {@link android.os.Build.VERSION_CODES#KITKAT} and earlier
120      * releases, the resulting path may not display on a hardware-accelerated
121      * Canvas. A simple workaround is to add a single operation to this path,
122      * such as <code>dst.rLineTo(0, 0)</code>.</p>
123      */
getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)124     public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) {
125         // Skia used to enforce this as part of its API, but has since relaxed that restriction
126         // so to maintain consistency in our API we enforce the preconditions here.
127         float length = getLength();
128         if (startD < 0) {
129             startD = 0;
130         }
131         if (stopD > length) {
132             stopD = length;
133         }
134         if (startD >= stopD) {
135             return false;
136         }
137 
138         return native_getSegment(native_instance, startD, stopD, dst.mutateNI(), startWithMoveTo);
139     }
140 
141     /**
142      * Return true if the current contour is closed()
143      */
isClosed()144     public boolean isClosed() {
145         return native_isClosed(native_instance);
146     }
147 
148     /**
149      * Move to the next contour in the path. Return true if one exists, or
150      * false if we're done with the path.
151      */
nextContour()152     public boolean nextContour() {
153         return native_nextContour(native_instance);
154     }
155 
finalize()156     protected void finalize() throws Throwable {
157         native_destroy(native_instance);
158         native_instance = 0;  // Other finalizers can still call us.
159     }
160 
native_create(long native_path, boolean forceClosed)161     private static native long native_create(long native_path, boolean forceClosed);
native_setPath(long native_instance, long native_path, boolean forceClosed)162     private static native void native_setPath(long native_instance, long native_path, boolean forceClosed);
native_getLength(long native_instance)163     private static native float native_getLength(long native_instance);
native_getPosTan(long native_instance, float distance, float pos[], float tan[])164     private static native boolean native_getPosTan(long native_instance, float distance, float pos[], float tan[]);
native_getMatrix(long native_instance, float distance, long native_matrix, int flags)165     private static native boolean native_getMatrix(long native_instance, float distance, long native_matrix, int flags);
native_getSegment(long native_instance, float startD, float stopD, long native_path, boolean startWithMoveTo)166     private static native boolean native_getSegment(long native_instance, float startD, float stopD, long native_path, boolean startWithMoveTo);
native_isClosed(long native_instance)167     private static native boolean native_isClosed(long native_instance);
native_nextContour(long native_instance)168     private static native boolean native_nextContour(long native_instance);
native_destroy(long native_instance)169     private static native void native_destroy(long native_instance);
170 
171     /* package */private long native_instance;
172 }
173 
174