Add animations along a Path.
Change-Id: If03bd10a3961ff874e33489e1253146b8dadca33
This commit is contained in:
@@ -2537,22 +2537,36 @@ package android.animation {
|
||||
method public static android.animation.ObjectAnimator ofArgb(java.lang.Object, java.lang.String, int...);
|
||||
method public static android.animation.ObjectAnimator ofArgb(T, android.util.Property<T, java.lang.Integer>, int...);
|
||||
method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, float...);
|
||||
method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, java.lang.String, android.graphics.Path);
|
||||
method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, float...);
|
||||
method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, android.util.Property<T, java.lang.Float>, android.graphics.Path);
|
||||
method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, int...);
|
||||
method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, java.lang.String, android.graphics.Path);
|
||||
method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, int...);
|
||||
method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, android.util.Property<T, java.lang.Integer>, android.graphics.Path);
|
||||
method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, float[][]);
|
||||
method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.graphics.Path);
|
||||
method public static android.animation.ObjectAnimator ofMultiFloat(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, T...);
|
||||
method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, int[][]);
|
||||
method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.graphics.Path);
|
||||
method public static android.animation.ObjectAnimator ofMultiInt(java.lang.Object, java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, T...);
|
||||
method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
|
||||
method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeConverter<android.graphics.PointF, ?>, android.graphics.Path);
|
||||
method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeEvaluator<V>, V...);
|
||||
method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, P>, android.animation.TypeConverter<V, P>, android.animation.TypeEvaluator<V>, V...);
|
||||
method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
|
||||
method public static android.animation.ObjectAnimator ofPropertyValuesHolder(java.lang.Object, android.animation.PropertyValuesHolder...);
|
||||
method public void setAutoCancel(boolean);
|
||||
method public void setProperty(android.util.Property);
|
||||
method public void setPropertyName(java.lang.String);
|
||||
}
|
||||
|
||||
public class PointFEvaluator implements android.animation.TypeEvaluator {
|
||||
ctor public PointFEvaluator();
|
||||
ctor public PointFEvaluator(android.graphics.PointF);
|
||||
method public android.graphics.PointF evaluate(float, android.graphics.PointF, android.graphics.PointF);
|
||||
}
|
||||
|
||||
public class PropertyValuesHolder implements java.lang.Cloneable {
|
||||
method public android.animation.PropertyValuesHolder clone();
|
||||
method public java.lang.String getPropertyName();
|
||||
@@ -2563,14 +2577,18 @@ package android.animation {
|
||||
method public static android.animation.PropertyValuesHolder ofKeyframe(java.lang.String, android.animation.Keyframe...);
|
||||
method public static android.animation.PropertyValuesHolder ofKeyframe(android.util.Property, android.animation.Keyframe...);
|
||||
method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, float[][]);
|
||||
method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.graphics.Path);
|
||||
method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<V, float[]>, android.animation.TypeEvaluator<V>, V...);
|
||||
method public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter<T, float[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
|
||||
method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, int[][]);
|
||||
method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.graphics.Path);
|
||||
method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<V, int[]>, android.animation.TypeEvaluator<V>, V...);
|
||||
method public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter<T, int[]>, android.animation.TypeEvaluator<T>, android.animation.Keyframe...);
|
||||
method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
|
||||
method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeConverter<android.graphics.PointF, ?>, android.graphics.Path);
|
||||
method public static android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator<V>, V...);
|
||||
method public static android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<T, V>, android.animation.TypeEvaluator<T>, T...);
|
||||
method public static android.animation.PropertyValuesHolder ofObject(android.util.Property<?, V>, android.animation.TypeConverter<android.graphics.PointF, V>, android.graphics.Path);
|
||||
method public void setConverter(android.animation.TypeConverter);
|
||||
method public void setEvaluator(android.animation.TypeEvaluator);
|
||||
method public void setFloatValues(float...);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.animation;
|
||||
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PointF;
|
||||
import android.util.Log;
|
||||
import android.util.Property;
|
||||
|
||||
@@ -209,6 +211,31 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code>
|
||||
* using two properties. A <code>Path</code></> animation moves in two dimensions, animating
|
||||
* coordinates <code>(x, y)</code> together to follow the line. In this variation, the
|
||||
* coordinates are integers that are set to separate properties designated by
|
||||
* <code>xPropertyName</code> and <code>yPropertyName</code>.
|
||||
*
|
||||
* @param target The object whose properties are to be animated. This object should
|
||||
* have public methods on it called <code>setNameX()</code> and
|
||||
* <code>setNameY</code>, where <code>nameX</code> and <code>nameY</code>
|
||||
* are the value of <code>xPropertyName</code> and <code>yPropertyName</code>
|
||||
* parameters, respectively.
|
||||
* @param xPropertyName The name of the property for the x coordinate being animated.
|
||||
* @param yPropertyName The name of the property for the y coordinate being animated.
|
||||
* @param path The <code>Path</code> to animate values along.
|
||||
* @return An ObjectAnimator object that is set up to animate along <code>path</code>.
|
||||
*/
|
||||
public static ObjectAnimator ofInt(Object target, String xPropertyName, String yPropertyName,
|
||||
Path path) {
|
||||
Keyframe[][] keyframes = PropertyValuesHolder.createKeyframes(path, true);
|
||||
PropertyValuesHolder x = PropertyValuesHolder.ofKeyframe(xPropertyName, keyframes[0]);
|
||||
PropertyValuesHolder y = PropertyValuesHolder.ofKeyframe(yPropertyName, keyframes[1]);
|
||||
return ofPropertyValuesHolder(target, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates between int values. A single
|
||||
* value implies that that value is the one being animated to. Two values imply starting
|
||||
@@ -227,6 +254,27 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code>
|
||||
* using two properties. A <code>Path</code></> animation moves in two dimensions, animating
|
||||
* coordinates <code>(x, y)</code> together to follow the line. In this variation, the
|
||||
* coordinates are integers that are set to separate properties, <code>xProperty</code> and
|
||||
* <code>yProperty</code>.
|
||||
*
|
||||
* @param target The object whose properties are to be animated.
|
||||
* @param xProperty The property for the x coordinate being animated.
|
||||
* @param yProperty The property for the y coordinate being animated.
|
||||
* @param path The <code>Path</code> to animate values along.
|
||||
* @return An ObjectAnimator object that is set up to animate along <code>path</code>.
|
||||
*/
|
||||
public static <T> ObjectAnimator ofInt(T target, Property<T, Integer> xProperty,
|
||||
Property<T, Integer> yProperty, Path path) {
|
||||
Keyframe[][] keyframes = PropertyValuesHolder.createKeyframes(path, true);
|
||||
PropertyValuesHolder x = PropertyValuesHolder.ofKeyframe(xProperty, keyframes[0]);
|
||||
PropertyValuesHolder y = PropertyValuesHolder.ofKeyframe(yProperty, keyframes[1]);
|
||||
return ofPropertyValuesHolder(target, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates over int values for a multiple
|
||||
* parameters setter. Only public methods that take only int parameters are supported.
|
||||
@@ -248,6 +296,26 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
return ofPropertyValuesHolder(target, pvh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates the target using a multi-int setter
|
||||
* along the given <code>Path</code>. A <code>Path</code></> animation moves in two dimensions,
|
||||
* animating coordinates <code>(x, y)</code> together to follow the line. In this variation, the
|
||||
* coordinates are integer x and y coordinates used in the first and second parameter of the
|
||||
* setter, respectively.
|
||||
*
|
||||
* @param target The object whose property is to be animated. This object may
|
||||
* have a public method on it called <code>setName()</code>, where <code>name</code> is
|
||||
* the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also
|
||||
* be the case-sensitive complete name of the public setter method.
|
||||
* @param propertyName The name of the property being animated or the name of the setter method.
|
||||
* @param path The <code>Path</code> to animate values along.
|
||||
* @return An ObjectAnimator object that is set up to animate along <code>path</code>.
|
||||
*/
|
||||
public static ObjectAnimator ofMultiInt(Object target, String propertyName, Path path) {
|
||||
PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, path);
|
||||
return ofPropertyValuesHolder(target, pvh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates over values for a multiple int
|
||||
* parameters setter. Only public methods that take only int parameters are supported.
|
||||
@@ -258,7 +326,7 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
* @param target The object whose property is to be animated. This object may
|
||||
* have a public method on it called <code>setName()</code>, where <code>name</code> is
|
||||
* the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also
|
||||
* be the complete name of the public method.
|
||||
* be the case-sensitive complete name of the public setter method.
|
||||
* @param propertyName The name of the property being animated or the name of the setter method.
|
||||
* @param converter Converts T objects into int parameters for the multi-value setter.
|
||||
* @param evaluator A TypeEvaluator that will be called on each animation frame to
|
||||
@@ -333,6 +401,31 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code>
|
||||
* using two properties. A <code>Path</code></> animation moves in two dimensions, animating
|
||||
* coordinates <code>(x, y)</code> together to follow the line. In this variation, the
|
||||
* coordinates are floats that are set to separate properties designated by
|
||||
* <code>xPropertyName</code> and <code>yPropertyName</code>.
|
||||
*
|
||||
* @param target The object whose properties are to be animated. This object should
|
||||
* have public methods on it called <code>setNameX()</code> and
|
||||
* <code>setNameY</code>, where <code>nameX</code> and <code>nameY</code>
|
||||
* are the value of the <code>xPropertyName</code> and <code>yPropertyName</code>
|
||||
* parameters, respectively.
|
||||
* @param xPropertyName The name of the property for the x coordinate being animated.
|
||||
* @param yPropertyName The name of the property for the y coordinate being animated.
|
||||
* @param path The <code>Path</code> to animate values along.
|
||||
* @return An ObjectAnimator object that is set up to animate along <code>path</code>.
|
||||
*/
|
||||
public static ObjectAnimator ofFloat(Object target, String xPropertyName, String yPropertyName,
|
||||
Path path) {
|
||||
Keyframe[][] keyframes = PropertyValuesHolder.createKeyframes(path, false);
|
||||
PropertyValuesHolder x = PropertyValuesHolder.ofKeyframe(xPropertyName, keyframes[0]);
|
||||
PropertyValuesHolder y = PropertyValuesHolder.ofKeyframe(yPropertyName, keyframes[1]);
|
||||
return ofPropertyValuesHolder(target, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates between float values. A single
|
||||
* value implies that that value is the one being animated to. Two values imply starting
|
||||
@@ -352,6 +445,24 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates coordinates along a <code>Path</code>
|
||||
* using two properties. A <code>Path</code></> animation moves in two dimensions, animating
|
||||
* coordinates <code>(x, y)</code> together to follow the line. In this variation, the
|
||||
* coordinates are floats that are set to separate properties, <code>xProperty</code> and
|
||||
* <code>yProperty</code>.
|
||||
*
|
||||
* @param target The object whose properties are to be animated.
|
||||
* @param xProperty The property for the x coordinate being animated.
|
||||
* @param yProperty The property for the y coordinate being animated.
|
||||
* @param path The <code>Path</code> to animate values along.
|
||||
* @return An ObjectAnimator object that is set up to animate along <code>path</code>.
|
||||
*/
|
||||
public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> xProperty,
|
||||
Property<T, Float> yProperty, Path path) {
|
||||
return ofFloat(target, xProperty.getName(), yProperty.getName(), path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates over float values for a multiple
|
||||
* parameters setter. Only public methods that take only float parameters are supported.
|
||||
@@ -363,7 +474,7 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
* @param target The object whose property is to be animated. This object may
|
||||
* have a public method on it called <code>setName()</code>, where <code>name</code> is
|
||||
* the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also
|
||||
* be the complete name of the public method.
|
||||
* be the case-sensitive complete name of the public setter method.
|
||||
* @param propertyName The name of the property being animated or the name of the setter method.
|
||||
* @param values A set of values that the animation will animate between over time.
|
||||
* @return An ObjectAnimator object that is set up to animate between the given values.
|
||||
@@ -374,6 +485,26 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
return ofPropertyValuesHolder(target, pvh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates the target using a multi-float setter
|
||||
* along the given <code>Path</code>. A <code>Path</code></> animation moves in two dimensions,
|
||||
* animating coordinates <code>(x, y)</code> together to follow the line. In this variation, the
|
||||
* coordinates are float x and y coordinates used in the first and second parameter of the
|
||||
* setter, respectively.
|
||||
*
|
||||
* @param target The object whose property is to be animated. This object may
|
||||
* have a public method on it called <code>setName()</code>, where <code>name</code> is
|
||||
* the value of the <code>propertyName</code> parameter. <code>propertyName</code> may also
|
||||
* be the case-sensitive complete name of the public setter method.
|
||||
* @param propertyName The name of the property being animated or the name of the setter method.
|
||||
* @param path The <code>Path</code> to animate values along.
|
||||
* @return An ObjectAnimator object that is set up to animate along <code>path</code>.
|
||||
*/
|
||||
public static ObjectAnimator ofMultiFloat(Object target, String propertyName, Path path) {
|
||||
PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, path);
|
||||
return ofPropertyValuesHolder(target, pvh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates over values for a multiple float
|
||||
* parameters setter. Only public methods that take only float parameters are supported.
|
||||
@@ -425,6 +556,30 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates a property along a <code>Path</code>.
|
||||
* A <code>Path</code></> animation moves in two dimensions, animating coordinates
|
||||
* <code>(x, y)</code> together to follow the line. This variant animates the coordinates
|
||||
* in a <code>PointF</code> to follow the <code>Path</code>. If the <code>Property</code>
|
||||
* associated with <code>propertyName</code> uses a type other than <code>PointF</code>,
|
||||
* <code>converter</code> can be used to change from <code>PointF</code> to the type
|
||||
* associated with the <code>Property</code>.
|
||||
*
|
||||
* @param target The object whose property is to be animated. This object should
|
||||
* have a public method on it called <code>setName()</code>, where <code>name</code> is
|
||||
* the value of the <code>propertyName</code> parameter.
|
||||
* @param propertyName The name of the property being animated.
|
||||
* @param converter Converts a PointF to the type associated with the setter. May be
|
||||
* null if conversion is unnecessary.
|
||||
* @param path The <code>Path</code> to animate values along.
|
||||
* @return An ObjectAnimator object that is set up to animate along <code>path</code>.
|
||||
*/
|
||||
public static ObjectAnimator ofObject(Object target, String propertyName,
|
||||
TypeConverter<PointF, ?> converter, Path path) {
|
||||
PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(propertyName, converter, path);
|
||||
return ofPropertyValuesHolder(target, pvh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates between Object values. A single
|
||||
* value implies that that value is the one being animated to. Two values imply starting
|
||||
@@ -474,6 +629,27 @@ public final class ObjectAnimator extends ValueAnimator {
|
||||
return ofPropertyValuesHolder(target, pvh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates a property along a <code>Path</code>.
|
||||
* A <code>Path</code></> animation moves in two dimensions, animating coordinates
|
||||
* <code>(x, y)</code> together to follow the line. This variant animates the coordinates
|
||||
* in a <code>PointF</code> to follow the <code>Path</code>. If <code>property</code>
|
||||
* uses a type other than <code>PointF</code>, <code>converter</code> can be used to change
|
||||
* from <code>PointF</code> to the type associated with the <code>Property</code>.
|
||||
*
|
||||
* @param target The object whose property is to be animated.
|
||||
* @param property The property being animated. Should not be null.
|
||||
* @param converter Converts a PointF to the type associated with the setter. May be
|
||||
* null if conversion is unnecessary.
|
||||
* @param path The <code>Path</code> to animate values along.
|
||||
* @return An ObjectAnimator object that is set up to animate along <code>path</code>.
|
||||
*/
|
||||
public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property,
|
||||
TypeConverter<PointF, V> converter, Path path) {
|
||||
PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(property, converter, path);
|
||||
return ofPropertyValuesHolder(target, pvh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns an ObjectAnimator that animates between the sets of values specified
|
||||
* in <code>PropertyValueHolder</code> objects. This variant should be used when animating
|
||||
|
||||
83
core/java/android/animation/PointFEvaluator.java
Normal file
83
core/java/android/animation/PointFEvaluator.java
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.animation;
|
||||
|
||||
import android.graphics.PointF;
|
||||
|
||||
/**
|
||||
* This evaluator can be used to perform type interpolation between <code>PointF</code> values.
|
||||
*/
|
||||
public class PointFEvaluator implements TypeEvaluator<PointF> {
|
||||
|
||||
/**
|
||||
* When null, a new PointF is returned on every evaluate call. When non-null,
|
||||
* mPoint will be modified and returned on every evaluate.
|
||||
*/
|
||||
private PointF mPoint;
|
||||
|
||||
/**
|
||||
* Construct a PointFEvaluator that returns a new PointF on every evaluate call.
|
||||
* To avoid creating an object for each evaluate call,
|
||||
* {@link PointFEvaluator#PointFEvaluator(android.graphics.PointF)} should be used
|
||||
* whenever possible.
|
||||
*/
|
||||
public PointFEvaluator() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PointFEvaluator that modifies and returns <code>reuse</code>
|
||||
* in {@link #evaluate(float, android.graphics.PointF, android.graphics.PointF)} calls.
|
||||
* The value returned from
|
||||
* {@link #evaluate(float, android.graphics.PointF, android.graphics.PointF)} should
|
||||
* not be cached because it will change over time as the object is reused on each
|
||||
* call.
|
||||
*
|
||||
* @param reuse A PointF to be modified and returned by evaluate.
|
||||
*/
|
||||
public PointFEvaluator(PointF reuse) {
|
||||
mPoint = reuse;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the result of linearly interpolating the start and
|
||||
* end PointF values, with <code>fraction</code> representing the proportion
|
||||
* between the start and end values. The calculation is a simple parametric
|
||||
* calculation on each of the separate components in the PointF objects
|
||||
* (x, y).
|
||||
*
|
||||
* <p>If {@link #PointFEvaluator(android.graphics.PointF)} was used to construct
|
||||
* this PointFEvaluator, the object returned will be the <code>reuse</code>
|
||||
* passed into the constructor.</p>
|
||||
*
|
||||
* @param fraction The fraction from the starting to the ending values
|
||||
* @param startValue The start PointF
|
||||
* @param endValue The end PointF
|
||||
* @return A linear interpolation between the start and end values, given the
|
||||
* <code>fraction</code> parameter.
|
||||
*/
|
||||
@Override
|
||||
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
|
||||
float x = startValue.x + (fraction * (endValue.x - startValue.x));
|
||||
float y = startValue.y + (fraction * (endValue.y - startValue.y));
|
||||
|
||||
if (mPoint != null) {
|
||||
mPoint.set(x, y);
|
||||
return mPoint;
|
||||
} else {
|
||||
return new PointF(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package android.animation;
|
||||
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PointF;
|
||||
import android.util.FloatMath;
|
||||
import android.util.FloatProperty;
|
||||
import android.util.IntProperty;
|
||||
import android.util.Log;
|
||||
@@ -176,8 +179,8 @@ public class PropertyValuesHolder implements Cloneable {
|
||||
* start, through all intermediate values to the end value. When used with ObjectAnimator,
|
||||
* the elements of the array represent the parameters of the setter function.
|
||||
*
|
||||
* @param propertyName The name of the property being animated. Can also be the name of the
|
||||
* entire setter method. Should not be null.
|
||||
* @param propertyName The name of the property being animated. Can also be the
|
||||
* case-sensitive name of the entire setter method. Should not be null.
|
||||
* @param values The values that the property will animate between.
|
||||
* @return PropertyValuesHolder The constructed PropertyValuesHolder object.
|
||||
* @see IntArrayEvaluator#IntArrayEvaluator(int[])
|
||||
@@ -203,6 +206,26 @@ public class PropertyValuesHolder implements Cloneable {
|
||||
return new MultiIntValuesHolder(propertyName, null, evaluator, (Object[]) values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns a PropertyValuesHolder with a given property name to use
|
||||
* as a multi-int setter. The values are animated along the path, with the first
|
||||
* parameter of the setter set to the x coordinate and the second set to the y coordinate.
|
||||
*
|
||||
* @param propertyName The name of the property being animated. Can also be the
|
||||
* case-sensitive name of the entire setter method. Should not be null.
|
||||
* The setter must take exactly two <code>int</code> parameters.
|
||||
* @param path The Path along which the values should be animated.
|
||||
* @return PropertyValuesHolder The constructed PropertyValuesHolder object.
|
||||
* @see ObjectAnimator#ofPropertyValuesHolder(Object, PropertyValuesHolder...)
|
||||
*/
|
||||
public static PropertyValuesHolder ofMultiInt(String propertyName, Path path) {
|
||||
Keyframe[] keyframes = createKeyframes(path);
|
||||
KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(keyframes);
|
||||
TypeEvaluator<PointF> evaluator = new PointFEvaluator(new PointF());
|
||||
PointFToIntArray converter = new PointFToIntArray();
|
||||
return new MultiIntValuesHolder(propertyName, converter, evaluator, keyframeSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns a PropertyValuesHolder with a given property and
|
||||
* set of Object values for use with ObjectAnimator multi-value setters. The Object
|
||||
@@ -276,8 +299,8 @@ public class PropertyValuesHolder implements Cloneable {
|
||||
* start, through all intermediate values to the end value. When used with ObjectAnimator,
|
||||
* the elements of the array represent the parameters of the setter function.
|
||||
*
|
||||
* @param propertyName The name of the property being animated. Can also be the name of the
|
||||
* entire setter method. Should not be null.
|
||||
* @param propertyName The name of the property being animated. Can also be the
|
||||
* case-sensitive name of the entire setter method. Should not be null.
|
||||
* @param values The values that the property will animate between.
|
||||
* @return PropertyValuesHolder The constructed PropertyValuesHolder object.
|
||||
* @see FloatArrayEvaluator#FloatArrayEvaluator(float[])
|
||||
@@ -303,6 +326,26 @@ public class PropertyValuesHolder implements Cloneable {
|
||||
return new MultiFloatValuesHolder(propertyName, null, evaluator, (Object[]) values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns a PropertyValuesHolder with a given property name to use
|
||||
* as a multi-float setter. The values are animated along the path, with the first
|
||||
* parameter of the setter set to the x coordinate and the second set to the y coordinate.
|
||||
*
|
||||
* @param propertyName The name of the property being animated. Can also be the
|
||||
* case-sensitive name of the entire setter method. Should not be null.
|
||||
* The setter must take exactly two <code>float</code> parameters.
|
||||
* @param path The Path along which the values should be animated.
|
||||
* @return PropertyValuesHolder The constructed PropertyValuesHolder object.
|
||||
* @see ObjectAnimator#ofPropertyValuesHolder(Object, PropertyValuesHolder...)
|
||||
*/
|
||||
public static PropertyValuesHolder ofMultiFloat(String propertyName, Path path) {
|
||||
Keyframe[] keyframes = createKeyframes(path);
|
||||
KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(keyframes);
|
||||
TypeEvaluator<PointF> evaluator = new PointFEvaluator(new PointF());
|
||||
PointFToFloatArray converter = new PointFToFloatArray();
|
||||
return new MultiFloatValuesHolder(propertyName, converter, evaluator, keyframeSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns a PropertyValuesHolder with a given property and
|
||||
* set of Object values for use with ObjectAnimator multi-value setters. The Object
|
||||
@@ -366,6 +409,27 @@ public class PropertyValuesHolder implements Cloneable {
|
||||
return pvh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns a PropertyValuesHolder with a given property name and
|
||||
* a Path along which the values should be animated. This variant supports a
|
||||
* <code>TypeConverter</code> to convert from <code>PointF</code> to the target
|
||||
* type.
|
||||
*
|
||||
* @param propertyName The name of the property being animated.
|
||||
* @param converter Converts a PointF to the type associated with the setter. May be
|
||||
* null if conversion is unnecessary.
|
||||
* @param path The Path along which the values should be animated.
|
||||
* @return PropertyValuesHolder The constructed PropertyValuesHolder object.
|
||||
*/
|
||||
public static PropertyValuesHolder ofObject(String propertyName,
|
||||
TypeConverter<PointF, ?> converter, Path path) {
|
||||
Keyframe[] keyframes = createKeyframes(path);
|
||||
PropertyValuesHolder pvh = ofKeyframe(propertyName, keyframes);
|
||||
pvh.setEvaluator(new PointFEvaluator(new PointF()));
|
||||
pvh.setConverter(converter);
|
||||
return pvh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns a PropertyValuesHolder with a given property and
|
||||
* set of Object values. This variant also takes a TypeEvaluator because the system
|
||||
@@ -414,6 +478,27 @@ public class PropertyValuesHolder implements Cloneable {
|
||||
return pvh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns a PropertyValuesHolder with a given property and
|
||||
* a Path along which the values should be animated. This variant supports a
|
||||
* <code>TypeConverter</code> to convert from <code>PointF</code> to the target
|
||||
* type.
|
||||
*
|
||||
* @param property The property being animated. Should not be null.
|
||||
* @param converter Converts a PointF to the type associated with the setter. May be
|
||||
* null if conversion is unnecessary.
|
||||
* @param path The Path along which the values should be animated.
|
||||
* @return PropertyValuesHolder The constructed PropertyValuesHolder object.
|
||||
*/
|
||||
public static <V> PropertyValuesHolder ofObject(Property<?, V> property,
|
||||
TypeConverter<PointF, V> converter, Path path) {
|
||||
Keyframe[] keyframes = createKeyframes(path);
|
||||
PropertyValuesHolder pvh = ofKeyframe(property, keyframes);
|
||||
pvh.setEvaluator(new PointFEvaluator(new PointF()));
|
||||
pvh.setConverter(converter);
|
||||
return pvh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns a PropertyValuesHolder object with the specified property name and set
|
||||
* of values. These values can be of any type, but the type should be consistent so that
|
||||
@@ -1439,6 +1524,113 @@ public class PropertyValuesHolder implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
/* Path interpolation relies on approximating the Path as a series of line segments.
|
||||
The line segments are recursively divided until there is less than 1/2 pixel error
|
||||
between the lines and the curve. Each point of the line segment is converted
|
||||
to a Keyframe and a linear interpolation between Keyframes creates a good approximation
|
||||
of the curve.
|
||||
|
||||
The fraction for each Keyframe is the length along the Path to the point, divided by
|
||||
the total Path length. Two points may have the same fraction in the case of a move
|
||||
command causing a disjoint Path.
|
||||
|
||||
The value for each Keyframe is either the point as a PointF or one of the x or y
|
||||
coordinates as an int or float. In the latter case, two Keyframes are generated for
|
||||
each point that have the same fraction. */
|
||||
|
||||
/**
|
||||
* Returns separate Keyframes arrays for the x and y coordinates along a Path. If
|
||||
* isInt is true, the Keyframes will be IntKeyframes, otherwise they will be FloatKeyframes.
|
||||
* The element at index 0 are the x coordinate Keyframes and element at index 1 are the
|
||||
* y coordinate Keyframes. The returned values can be linearly interpolated and get less
|
||||
* than 1/2 pixel error.
|
||||
*/
|
||||
static Keyframe[][] createKeyframes(Path path, boolean isInt) {
|
||||
if (path == null || path.isEmpty()) {
|
||||
throw new IllegalArgumentException("The path must not be null or empty");
|
||||
}
|
||||
float[] pointComponents = path.approximate(0.5f);
|
||||
|
||||
int numPoints = pointComponents.length / 3;
|
||||
|
||||
Keyframe[][] keyframes = new Keyframe[2][];
|
||||
keyframes[0] = new Keyframe[numPoints];
|
||||
keyframes[1] = new Keyframe[numPoints];
|
||||
int componentIndex = 0;
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
float fraction = pointComponents[componentIndex++];
|
||||
float x = pointComponents[componentIndex++];
|
||||
float y = pointComponents[componentIndex++];
|
||||
if (isInt) {
|
||||
keyframes[0][i] = Keyframe.ofInt(fraction, Math.round(x));
|
||||
keyframes[1][i] = Keyframe.ofInt(fraction, Math.round(y));
|
||||
} else {
|
||||
keyframes[0][i] = Keyframe.ofFloat(fraction, x);
|
||||
keyframes[1][i] = Keyframe.ofFloat(fraction, y);
|
||||
}
|
||||
}
|
||||
return keyframes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns PointF Keyframes for a Path. The resulting points can be linearly interpolated
|
||||
* with less than 1/2 pixel in error.
|
||||
*/
|
||||
private static Keyframe[] createKeyframes(Path path) {
|
||||
if (path == null || path.isEmpty()) {
|
||||
throw new IllegalArgumentException("The path must not be null or empty");
|
||||
}
|
||||
float[] pointComponents = path.approximate(0.5f);
|
||||
|
||||
int numPoints = pointComponents.length / 3;
|
||||
|
||||
Keyframe[] keyframes = new Keyframe[numPoints];
|
||||
int componentIndex = 0;
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
float fraction = pointComponents[componentIndex++];
|
||||
float x = pointComponents[componentIndex++];
|
||||
float y = pointComponents[componentIndex++];
|
||||
keyframes[i] = Keyframe.ofObject(fraction, new PointF(x, y));
|
||||
}
|
||||
return keyframes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from PointF to float[] for multi-float setters along a Path.
|
||||
*/
|
||||
private static class PointFToFloatArray extends TypeConverter<PointF, float[]> {
|
||||
private float[] mCoordinates = new float[2];
|
||||
|
||||
public PointFToFloatArray() {
|
||||
super(PointF.class, float[].class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] convert(PointF value) {
|
||||
mCoordinates[0] = value.x;
|
||||
mCoordinates[1] = value.y;
|
||||
return mCoordinates;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert from PointF to int[] for multi-int setters along a Path.
|
||||
*/
|
||||
private static class PointFToIntArray extends TypeConverter<PointF, int[]> {
|
||||
private int[] mCoordinates = new int[2];
|
||||
|
||||
public PointFToIntArray() {
|
||||
super(PointF.class, int[].class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] convert(PointF value) {
|
||||
mCoordinates[0] = Math.round(value.x);
|
||||
mCoordinates[1] = Math.round(value.y);
|
||||
return mCoordinates;
|
||||
}
|
||||
};
|
||||
|
||||
native static private int nGetIntMethod(Class targetClass, String methodName);
|
||||
native static private int nGetFloatMethod(Class targetClass, String methodName);
|
||||
native static private int nGetMultipleIntMethod(Class targetClass, String methodName,
|
||||
@@ -1456,4 +1648,4 @@ public class PropertyValuesHolder implements Cloneable {
|
||||
native static private void nCallFourFloatMethod(Object target, int methodID, float arg1,
|
||||
float arg2, float arg3, float arg4);
|
||||
native static private void nCallMultipleFloatMethod(Object target, int methodID, float[] args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "pathops/SkPathOps.h"
|
||||
|
||||
#include <Caches.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace android {
|
||||
|
||||
@@ -265,6 +267,196 @@ public:
|
||||
static jboolean op(JNIEnv* env, jobject clazz, SkPath* p1, SkPath* p2, SkPathOp op, SkPath* r) {
|
||||
return Op(*p1, *p2, op, r);
|
||||
}
|
||||
|
||||
|
||||
typedef SkPoint (*bezierCalculation)(float t, const SkPoint* points);
|
||||
|
||||
static void addMove(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths,
|
||||
const SkPoint& point) {
|
||||
float length = 0;
|
||||
if (!lengths.empty()) {
|
||||
length = lengths.back();
|
||||
}
|
||||
segmentPoints.push_back(point);
|
||||
lengths.push_back(length);
|
||||
}
|
||||
|
||||
static void addLine(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths,
|
||||
const SkPoint& toPoint) {
|
||||
if (segmentPoints.empty()) {
|
||||
segmentPoints.push_back(SkPoint::Make(0, 0));
|
||||
lengths.push_back(0);
|
||||
} else if (segmentPoints.back() == toPoint) {
|
||||
return; // Empty line
|
||||
}
|
||||
float length = lengths.back() + SkPoint::Distance(segmentPoints.back(), toPoint);
|
||||
segmentPoints.push_back(toPoint);
|
||||
lengths.push_back(length);
|
||||
}
|
||||
|
||||
static float cubicCoordinateCalculation(float t, float p0, float p1, float p2, float p3) {
|
||||
float oneMinusT = 1 - t;
|
||||
float oneMinusTSquared = oneMinusT * oneMinusT;
|
||||
float oneMinusTCubed = oneMinusTSquared * oneMinusT;
|
||||
float tSquared = t * t;
|
||||
float tCubed = tSquared * t;
|
||||
return (oneMinusTCubed * p0) + (3 * oneMinusTSquared * t * p1)
|
||||
+ (3 * oneMinusT * tSquared * p2) + (tCubed * p3);
|
||||
}
|
||||
|
||||
static SkPoint cubicBezierCalculation(float t, const SkPoint* points) {
|
||||
float x = cubicCoordinateCalculation(t, points[0].x(), points[1].x(),
|
||||
points[2].x(), points[3].x());
|
||||
float y = cubicCoordinateCalculation(t, points[0].y(), points[1].y(),
|
||||
points[2].y(), points[3].y());
|
||||
return SkPoint::Make(x, y);
|
||||
}
|
||||
|
||||
static float quadraticCoordinateCalculation(float t, float p0, float p1, float p2) {
|
||||
float oneMinusT = 1 - t;
|
||||
return oneMinusT * ((oneMinusT * p0) + (t * p1)) + t * ((oneMinusT * p1) + (t * p2));
|
||||
}
|
||||
|
||||
static SkPoint quadraticBezierCalculation(float t, const SkPoint* points) {
|
||||
float x = quadraticCoordinateCalculation(t, points[0].x(), points[1].x(), points[2].x());
|
||||
float y = quadraticCoordinateCalculation(t, points[0].y(), points[1].y(), points[2].y());
|
||||
return SkPoint::Make(x, y);
|
||||
}
|
||||
|
||||
// Subdivide a section of the Bezier curve, set the mid-point and the mid-t value.
|
||||
// Returns true if further subdivision is necessary as defined by errorSquared.
|
||||
static bool subdividePoints(const SkPoint* points, bezierCalculation bezierFunction,
|
||||
float t0, const SkPoint &p0, float t1, const SkPoint &p1,
|
||||
float& midT, SkPoint &midPoint, float errorSquared) {
|
||||
midT = (t1 + t0) / 2;
|
||||
float midX = (p1.x() + p0.x()) / 2;
|
||||
float midY = (p1.y() + p0.y()) / 2;
|
||||
|
||||
midPoint = (*bezierFunction)(midT, points);
|
||||
float xError = midPoint.x() - midX;
|
||||
float yError = midPoint.y() - midY;
|
||||
float midErrorSquared = (xError * xError) + (yError * yError);
|
||||
return midErrorSquared > errorSquared;
|
||||
}
|
||||
|
||||
// Divides Bezier curves until linear interpolation is very close to accurate, using
|
||||
// errorSquared as a metric. Cubic Bezier curves can have an inflection point that improperly
|
||||
// short-circuit subdivision. If you imagine an S shape, the top and bottom points being the
|
||||
// starting and end points, linear interpolation would mark the center where the curve places
|
||||
// the point. It is clearly not the case that we can linearly interpolate at that point.
|
||||
// doubleCheckDivision forces a second examination between subdivisions to ensure that linear
|
||||
// interpolation works.
|
||||
static void addBezier(const SkPoint* points,
|
||||
bezierCalculation bezierFunction, std::vector<SkPoint>& segmentPoints,
|
||||
std::vector<float>& lengths, float errorSquared, bool doubleCheckDivision) {
|
||||
typedef std::map<float, SkPoint> PointMap;
|
||||
PointMap tToPoint;
|
||||
|
||||
tToPoint[0] = (*bezierFunction)(0, points);
|
||||
tToPoint[1] = (*bezierFunction)(1, points);
|
||||
|
||||
PointMap::iterator iter = tToPoint.begin();
|
||||
PointMap::iterator next = iter;
|
||||
++next;
|
||||
while (next != tToPoint.end()) {
|
||||
bool needsSubdivision = true;
|
||||
SkPoint midPoint;
|
||||
do {
|
||||
float midT;
|
||||
needsSubdivision = subdividePoints(points, bezierFunction, iter->first,
|
||||
iter->second, next->first, next->second, midT, midPoint, errorSquared);
|
||||
if (!needsSubdivision && doubleCheckDivision) {
|
||||
SkPoint quarterPoint;
|
||||
float quarterT;
|
||||
needsSubdivision = subdividePoints(points, bezierFunction, iter->first,
|
||||
iter->second, midT, midPoint, quarterT, quarterPoint, errorSquared);
|
||||
if (needsSubdivision) {
|
||||
// Found an inflection point. No need to double-check.
|
||||
doubleCheckDivision = false;
|
||||
}
|
||||
}
|
||||
if (needsSubdivision) {
|
||||
next = tToPoint.insert(iter, PointMap::value_type(midT, midPoint));
|
||||
}
|
||||
} while (needsSubdivision);
|
||||
iter = next;
|
||||
next++;
|
||||
}
|
||||
|
||||
// Now that each division can use linear interpolation with less than the allowed error
|
||||
for (iter = tToPoint.begin(); iter != tToPoint.end(); ++iter) {
|
||||
addLine(segmentPoints, lengths, iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
static void createVerbSegments(SkPath::Verb verb, const SkPoint* points,
|
||||
std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, float errorSquared) {
|
||||
switch (verb) {
|
||||
case SkPath::kMove_Verb:
|
||||
addMove(segmentPoints, lengths, points[0]);
|
||||
break;
|
||||
case SkPath::kClose_Verb:
|
||||
case SkPath::kLine_Verb:
|
||||
addLine(segmentPoints, lengths, points[1]);
|
||||
break;
|
||||
case SkPath::kQuad_Verb:
|
||||
addBezier(points, quadraticBezierCalculation, segmentPoints, lengths,
|
||||
errorSquared, false);
|
||||
break;
|
||||
case SkPath::kCubic_Verb:
|
||||
addBezier(points, cubicBezierCalculation, segmentPoints, lengths,
|
||||
errorSquared, true);
|
||||
break;
|
||||
default:
|
||||
// Leave element as NULL, Conic sections are not supported.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a float[] with each point along the path represented by 3 floats
|
||||
// * fractional length along the path that the point resides
|
||||
// * x coordinate
|
||||
// * y coordinate
|
||||
// Note that more than one point may have the same length along the path in
|
||||
// the case of a move.
|
||||
// NULL can be returned if the Path is empty.
|
||||
static jfloatArray approximate(JNIEnv* env, jclass, SkPath* path, float acceptableError)
|
||||
{
|
||||
SkASSERT(path);
|
||||
SkPath::Iter pathIter(*path, false);
|
||||
SkPath::Verb verb;
|
||||
SkPoint points[4];
|
||||
std::vector<SkPoint> segmentPoints;
|
||||
std::vector<float> lengths;
|
||||
float errorSquared = acceptableError * acceptableError;
|
||||
|
||||
while ((verb = pathIter.next(points)) != SkPath::kDone_Verb) {
|
||||
createVerbSegments(verb, points, segmentPoints, lengths, errorSquared);
|
||||
}
|
||||
|
||||
if (segmentPoints.empty()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t numPoints = segmentPoints.size();
|
||||
size_t approximationArraySize = numPoints * 3;
|
||||
|
||||
float* approximation = new float[approximationArraySize];
|
||||
float totalLength = lengths.back();
|
||||
|
||||
int approximationIndex = 0;
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
const SkPoint& point = segmentPoints[i];
|
||||
approximation[approximationIndex++] = lengths[i] / totalLength;
|
||||
approximation[approximationIndex++] = point.x();
|
||||
approximation[approximationIndex++] = point.y();
|
||||
}
|
||||
|
||||
jfloatArray result = env->NewFloatArray(approximationArraySize);
|
||||
env->SetFloatArrayRegion(result, 0, approximationArraySize, approximation);
|
||||
delete[] approximation;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
static JNINativeMethod methods[] = {
|
||||
@@ -305,7 +497,8 @@ static JNINativeMethod methods[] = {
|
||||
{"native_setLastPoint","(IFF)V", (void*) SkPathGlue::setLastPoint},
|
||||
{"native_transform","(III)V", (void*) SkPathGlue::transform__MatrixPath},
|
||||
{"native_transform","(II)V", (void*) SkPathGlue::transform__Matrix},
|
||||
{"native_op","(IIII)Z", (void*) SkPathGlue::op}
|
||||
{"native_op","(IIII)Z", (void*) SkPathGlue::op},
|
||||
{"native_approximate", "(IF)[F", (void*) SkPathGlue::approximate},
|
||||
};
|
||||
|
||||
int register_android_graphics_Path(JNIEnv* env) {
|
||||
|
||||
@@ -703,6 +703,28 @@ public class Path {
|
||||
return mNativePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Approximate the <code>Path</code> with a series of line segments.
|
||||
* This returns float[] with the array containing point components.
|
||||
* There are three components for each point, in order:
|
||||
* <ul>
|
||||
* <li>Fraction along the length of the path that the point resides</li>
|
||||
* <li>The x coordinate of the point</li>
|
||||
* <li>The y coordinate of the point</li>
|
||||
* </ul>
|
||||
* <p>Two points may share the same fraction along its length when there is
|
||||
* a move action within the Path.</p>
|
||||
*
|
||||
* @param acceptableError The acceptable error for a line on the
|
||||
* Path. Typically this would be 0.5 so that
|
||||
* the error is less than half a pixel.
|
||||
* @return An array of components for points approximating the Path.
|
||||
* @hide
|
||||
*/
|
||||
public float[] approximate(float acceptableError) {
|
||||
return native_approximate(mNativePath, acceptableError);
|
||||
}
|
||||
|
||||
private static native int init1();
|
||||
private static native int init2(int nPath);
|
||||
private static native void native_reset(int nPath);
|
||||
@@ -749,4 +771,5 @@ public class Path {
|
||||
private static native void native_transform(int nPath, int matrix);
|
||||
private static native boolean native_op(int path1, int path2, int op, int result);
|
||||
private static native void finalizer(int nPath);
|
||||
private static native float[] native_approximate(int nPath, float error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user