| /* | |
| * Copyright (C) 2007 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| package android.graphics; | |
| @android.ravenwood.annotation.RavenwoodKeepWholeClass | |
| public class PathMeasure { | |
| private Path mPath; | |
| /** | |
| * Create an empty PathMeasure object. To uses this to measure the length | |
| * of a path, and/or to find the position and tangent along it, call | |
| * setPath. | |
| * | |
| * Note that once a path is associated with the measure object, it is | |
| * undefined if the path is subsequently modified and the measure object | |
| * is used. If the path is modified, you must call setPath with the path. | |
| */ | |
| public PathMeasure() { | |
| mPath = null; | |
| native_instance = native_create(0, false); | |
| } | |
| /** | |
| * Create a PathMeasure object associated with the specified path object | |
| * (already created and specified). The measure object can now return the | |
| * path's length, and the position and tangent of any position along the | |
| * path. | |
| * | |
| * Note that once a path is associated with the measure object, it is | |
| * undefined if the path is subsequently modified and the measure object | |
| * is used. If the path is modified, you must call setPath with the path. | |
| * | |
| * @param path The path that will be measured by this object | |
| * @param forceClosed If true, then the path will be considered as "closed" | |
| * even if its contour was not explicitly closed. | |
| */ | |
| public PathMeasure(Path path, boolean forceClosed) { | |
| // The native implementation does not copy the path, prevent it from being GC'd | |
| mPath = path; | |
| native_instance = native_create(path != null ? path.readOnlyNI() : 0, | |
| forceClosed); | |
| } | |
| /** | |
| * Assign a new path, or null to have none. | |
| */ | |
| public void setPath(Path path, boolean forceClosed) { | |
| mPath = path; | |
| native_setPath(native_instance, | |
| path != null ? path.readOnlyNI() : 0, | |
| forceClosed); | |
| } | |
| /** | |
| * Return the total length of the current contour, or 0 if no path is | |
| * associated with this measure object. | |
| */ | |
| public float getLength() { | |
| return native_getLength(native_instance); | |
| } | |
| /** | |
| * Pins distance to 0 <= distance <= getLength(), and then computes the | |
| * corresponding position and tangent. Returns false if there is no path, | |
| * or a zero-length path was specified, in which case position and tangent | |
| * are unchanged. | |
| * | |
| * @param distance The distance along the current contour to sample | |
| * @param pos If not null, returns the sampled position (x==[0], y==[1]) | |
| * @param tan If not null, returns the sampled tangent (x==[0], y==[1]) | |
| * @return false if there was no path associated with this measure object | |
| */ | |
| public boolean getPosTan(float distance, float pos[], float tan[]) { | |
| if (pos != null && pos.length < 2 || | |
| tan != null && tan.length < 2) { | |
| throw new ArrayIndexOutOfBoundsException(); | |
| } | |
| return native_getPosTan(native_instance, distance, pos, tan); | |
| } | |
| public static final int POSITION_MATRIX_FLAG = 0x01; // must match flags in SkPathMeasure.h | |
| public static final int TANGENT_MATRIX_FLAG = 0x02; // must match flags in SkPathMeasure.h | |
| /** | |
| * Pins distance to 0 <= distance <= getLength(), and then computes the | |
| * corresponding matrix. Returns false if there is no path, or a zero-length | |
| * path was specified, in which case matrix is unchanged. | |
| * | |
| * @param distance The distance along the associated path | |
| * @param matrix Allocated by the caller, this is set to the transformation | |
| * associated with the position and tangent at the specified distance | |
| * @param flags Specified what aspects should be returned in the matrix. | |
| */ | |
| public boolean getMatrix(float distance, Matrix matrix, int flags) { | |
| return native_getMatrix(native_instance, distance, matrix.ni(), flags); | |
| } | |
| /** | |
| * Given a start and stop distance, return in dst the intervening | |
| * segment(s). If the segment is zero-length, return false, else return | |
| * true. startD and stopD are pinned to legal values (0..getLength()). | |
| * If startD >= stopD then return false (and leave dst untouched). | |
| * Begin the segment with a moveTo if startWithMoveTo is true. | |
| * | |
| * <p>On {@link android.os.Build.VERSION_CODES#KITKAT} and earlier | |
| * releases, the resulting path may not display on a hardware-accelerated | |
| * Canvas. A simple workaround is to add a single operation to this path, | |
| * such as <code>dst.rLineTo(0, 0)</code>.</p> | |
| */ | |
| public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) { | |
| // Skia used to enforce this as part of its API, but has since relaxed that restriction | |
| // so to maintain consistency in our API we enforce the preconditions here. | |
| float length = getLength(); | |
| if (startD < 0) { | |
| startD = 0; | |
| } | |
| if (stopD > length) { | |
| stopD = length; | |
| } | |
| if (startD >= stopD) { | |
| return false; | |
| } | |
| return native_getSegment(native_instance, startD, stopD, dst.mutateNI(), startWithMoveTo); | |
| } | |
| /** | |
| * Return true if the current contour is closed() | |
| */ | |
| public boolean isClosed() { | |
| return native_isClosed(native_instance); | |
| } | |
| /** | |
| * Move to the next contour in the path. Return true if one exists, or | |
| * false if we're done with the path. | |
| */ | |
| public boolean nextContour() { | |
| return native_nextContour(native_instance); | |
| } | |
| protected void finalize() throws Throwable { | |
| native_destroy(native_instance); | |
| native_instance = 0; // Other finalizers can still call us. | |
| } | |
| private static native long native_create(long native_path, boolean forceClosed); | |
| private static native void native_setPath(long native_instance, long native_path, boolean forceClosed); | |
| private static native float native_getLength(long native_instance); | |
| private static native boolean native_getPosTan(long native_instance, float distance, float pos[], float tan[]); | |
| private static native boolean native_getMatrix(long native_instance, float distance, long native_matrix, int flags); | |
| private static native boolean native_getSegment(long native_instance, float startD, float stopD, long native_path, boolean startWithMoveTo); | |
| private static native boolean native_isClosed(long native_instance); | |
| private static native boolean native_nextContour(long native_instance); | |
| private static native void native_destroy(long native_instance); | |
| /* package */private long native_instance; | |
| } | |