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
17package android.graphics;
18
19public class PathMeasure {
20
21    /**
22     * Create an empty PathMeasure object. To uses this to measure the length
23     * of a path, and/or to find the position and tangent along it, call
24     * setPath.
25     *
26     * Note that once a path is associated with the measure object, it is
27     * undefined if the path is subsequently modified and the the measure object
28     * is used. If the path is modified, you must call setPath with the path.
29     */
30    public PathMeasure() {
31        native_instance = native_create(0, false);
32    }
33
34    /**
35     * Create a PathMeasure object associated with the specified path object
36     * (already created and specified). The meansure object can now return the
37     * path's length, and the position and tangent of any position along the
38     * path.
39     *
40     * Note that once a path is associated with the measure object, it is
41     * undefined if the path is subsequently modified and the the measure object
42     * is used. If the path is modified, you must call setPath with the path.
43     *
44     * @param path The path that will be measured by this object
45     * @param forceClosed If true, then the path will be considered as "closed"
46     *        even if its contour was not explicitly closed.
47     */
48    public PathMeasure(Path path, boolean forceClosed) {
49        // note: the native side makes a copy of path, so we don't need a java
50        // reference to it here, since it's fine if it gets GC'd
51        native_instance = native_create(path != null ? path.ni() : 0,
52                                        forceClosed);
53    }
54
55    /**
56     * Assign a new path, or null to have none.
57     */
58    public void setPath(Path path, boolean forceClosed) {
59        // note: the native side makes a copy of path, so we don't need a java
60        // reference to it here, since it's fine if it gets GC'd
61        native_setPath(native_instance,
62                       path != null ? path.ni() : 0,
63                       forceClosed);
64    }
65
66    /**
67     * Return the total length of the current contour, or 0 if no path is
68     * associated with this measure object.
69     */
70    public float getLength() {
71        return native_getLength(native_instance);
72    }
73
74    /**
75     * Pins distance to 0 <= distance <= getLength(), and then computes the
76     * corresponding position and tangent. Returns false if there is no path,
77     * or a zero-length path was specified, in which case position and tangent
78     * are unchanged.
79     *
80     * @param distance The distance along the current contour to sample
81     * @param pos If not null, eturns the sampled position (x==[0], y==[1])
82     * @param tan If not null, returns the sampled tangent (x==[0], y==[1])
83     * @return false if there was no path associated with this measure object
84    */
85    public boolean getPosTan(float distance, float pos[], float tan[]) {
86        if (pos != null && pos.length < 2 ||
87            tan != null && tan.length < 2) {
88            throw new ArrayIndexOutOfBoundsException();
89        }
90        return native_getPosTan(native_instance, distance, pos, tan);
91    }
92
93    public static final int POSITION_MATRIX_FLAG = 0x01;    // must match flags in SkPathMeasure.h
94    public static final int TANGENT_MATRIX_FLAG  = 0x02;    // must match flags in SkPathMeasure.h
95
96    /**
97     * Pins distance to 0 <= distance <= getLength(), and then computes the
98     * corresponding matrix. Returns false if there is no path, or a zero-length
99     * path was specified, in which case matrix is unchanged.
100     *
101     * @param distance The distance along the associated path
102     * @param matrix Allocated by the caller, this is set to the transformation
103     *        associated with the position and tangent at the specified distance
104     * @param flags Specified what aspects should be returned in the matrix.
105     */
106    public boolean getMatrix(float distance, Matrix matrix, int flags) {
107        return native_getMatrix(native_instance, distance, matrix.native_instance, flags);
108    }
109
110    /**
111     * Given a start and stop distance, return in dst the intervening
112     * segment(s). If the segment is zero-length, return false, else return
113     * true. startD and stopD are pinned to legal values (0..getLength()).
114     * If startD <= stopD then return false (and leave dst untouched).
115     * Begin the segment with a moveTo if startWithMoveTo is true
116     */
117    public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) {
118        return native_getSegment(native_instance, startD, stopD, dst.ni(), startWithMoveTo);
119    }
120
121    /**
122     * Return true if the current contour is closed()
123     */
124    public boolean isClosed() {
125        return native_isClosed(native_instance);
126    }
127
128    /**
129     * Move to the next contour in the path. Return true if one exists, or
130     * false if we're done with the path.
131     */
132    public boolean nextContour() {
133        return native_nextContour(native_instance);
134    }
135
136    protected void finalize() throws Throwable {
137        native_destroy(native_instance);
138    }
139
140    private static native int native_create(int native_path, boolean forceClosed);
141    private static native void native_setPath(int native_instance, int native_path, boolean forceClosed);
142    private static native float native_getLength(int native_instance);
143    private static native boolean native_getPosTan(int native_instance, float distance, float pos[], float tan[]);
144    private static native boolean native_getMatrix(int native_instance, float distance, int native_matrix, int flags);
145    private static native boolean native_getSegment(int native_instance, float startD, float stopD, int native_path, boolean startWithMoveTo);
146    private static native boolean native_isClosed(int native_instance);
147    private static native boolean native_nextContour(int native_instance);
148    private static native void native_destroy(int native_instance);
149
150    /* package */private final int native_instance;
151}
152
153