/*
 * 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;

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 the measure object is used. If the path is modified, you must call setPath with the path.
/** * 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 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 the measure object is used. If the path is modified, you must call setPath with the path.
Params:
  • path – The path that will be measured by this object
  • forceClosed – If true, then the path will be considered as "closed" even if its contour was not explicitly closed.
/** * 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 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.
/** * 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.
/** * 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.
Params:
  • distance – The distance along the current contour to sample
  • pos – If not null, returns the sampled position (x==[0], y==[1])
  • tan – If not null, returns the sampled tangent (x==[0], y==[1])
Returns:false if there was no path associated with this measure object
/** * 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.
Params:
  • distance – The distance along the associated path
  • matrix – Allocated by the caller, this is set to the transformation associated with the position and tangent at the specified distance
  • flags – Specified what aspects should be returned in the matrix.
/** * 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.native_instance, 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.

On 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 dst.rLineTo(0, 0).

/** * 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 it's 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()
/** * 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.
/** * 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; }