Merge "Import translations. DO NOT MERGE"
diff --git a/api/current.txt b/api/current.txt
index 2845af1..4d500c6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2537,22 +2537,36 @@
     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 @@
     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...);
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 3adbf08..c0ce795 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -16,6 +16,8 @@
 
 package android.animation;
 
+import android.graphics.Path;
+import android.graphics.PointF;
 import android.util.Log;
 import android.util.Property;
 
@@ -210,6 +212,31 @@
     }
 
     /**
+     * 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
      * and ending values. More than two values imply a starting value, values to animate through
@@ -228,6 +255,27 @@
     }
 
     /**
+     * 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.
      * Each <code>int[]</code> contains a complete set of parameters to the setter method.
@@ -249,6 +297,26 @@
     }
 
     /**
+     * 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.
      * <p>At least two values must be provided, a start and end. More than two
@@ -258,7 +326,7 @@
      * @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
@@ -334,6 +402,31 @@
     }
 
     /**
+     * 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
      * and ending values. More than two values imply a starting value, values to animate through
@@ -353,6 +446,24 @@
     }
 
     /**
+     * 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.
      * Each <code>float[]</code> contains a complete set of parameters to the setter method.
@@ -363,7 +474,7 @@
      * @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.
@@ -375,6 +486,26 @@
     }
 
     /**
+     * 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.
      * <p>At least two values must be provided, a start and end. More than two
@@ -426,6 +557,30 @@
     }
 
     /**
+     * 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
      * and ending values. More than two values imply a starting value, values to animate through
@@ -475,6 +630,27 @@
     }
 
     /**
+     * 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
      * several properties at once with the same ObjectAnimator, since PropertyValuesHolder allows
diff --git a/core/java/android/animation/PointFEvaluator.java b/core/java/android/animation/PointFEvaluator.java
new file mode 100644
index 0000000..91d501f
--- /dev/null
+++ b/core/java/android/animation/PointFEvaluator.java
@@ -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);
+        }
+    }
+}
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index c291970..1b028e0 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -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 @@
      * 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[])
@@ -204,6 +207,26 @@
     }
 
     /**
+     * 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
      * values are converted to <code>int[]</code> using the converter.
@@ -276,8 +299,8 @@
      * 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[])
@@ -304,6 +327,26 @@
     }
 
     /**
+     * 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
      * values are converted to <code>float[]</code> using the converter.
@@ -367,6 +410,27 @@
     }
 
     /**
+     * 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
      * cannot automatically interpolate between objects of unknown type.
@@ -415,6 +479,27 @@
     }
 
     /**
+     * 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
      * an appropriate {@link android.animation.TypeEvaluator} can be found that matches
@@ -1439,6 +1524,113 @@
         }
     }
 
+    /* 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 @@
     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);
-}
\ No newline at end of file
+}
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index ab7f1dc..97a7de6 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -28,6 +28,8 @@
 #include "pathops/SkPathOps.h"
 
 #include <Caches.h>
+#include <vector>
+#include <map>
 
 namespace android {
 
@@ -265,6 +267,196 @@
     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 @@
     {"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) {
diff --git a/docs/html/guide/topics/connectivity/bluetooth-le.jd b/docs/html/guide/topics/connectivity/bluetooth-le.jd
index fa0d36e..5c32e56 100644
--- a/docs/html/guide/topics/connectivity/bluetooth-le.jd
+++ b/docs/html/guide/topics/connectivity/bluetooth-le.jd
@@ -44,6 +44,15 @@
 </div>
 </div>
 
+<a class="notice-developers-video" href="http://www.youtube.com/watch?v=vUbFB1Qypg8">
+<div>
+    <h3>Video</h3>
+    <p>DevBytes: Bluetooth Low Energy API</p>
+</div>
+</a>
+
+
+
 
 <p>
 Android 4.3 (API Level 18) introduces built-in platform support for Bluetooth Low
diff --git a/docs/html/training/connect-devices-wirelessly/index.jd b/docs/html/training/connect-devices-wirelessly/index.jd
index 2da4e38..3206d7f 100644
--- a/docs/html/training/connect-devices-wirelessly/index.jd
+++ b/docs/html/training/connect-devices-wirelessly/index.jd
@@ -20,9 +20,15 @@
   <li><a href="{@docRoot}guide/topics/connectivity/wifip2p.html">Wi-Fi P2P</a></li>
 </ul>
 
+</div>
+</div>
 
+<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=oi_ARV_I8Dc">
+<div>
+    <h3>Video</h3>
+    <p>DevBytes: Network Service Discovery</p>
 </div>
-</div>
+</a>
 
 
 <p>Besides enabling communication with the cloud, Android's wireless APIs also
diff --git a/docs/html/training/displaying-bitmaps/index.jd b/docs/html/training/displaying-bitmaps/index.jd
index 5521870..7003585 100644
--- a/docs/html/training/displaying-bitmaps/index.jd
+++ b/docs/html/training/displaying-bitmaps/index.jd
@@ -25,6 +25,20 @@
 </div>
 </div>
 
+<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=rsQet4nBVi8">
+<div>
+    <h3>Video</h3>
+    <p>DevBytes: Bitmap Allocation</p>
+</div>
+</a>
+
+<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=pMRnGDR6Cu0">
+<div>
+    <h3>Video</h3>
+    <p>DevBytes: Making Apps Beautiful - Part 4 - Performance Tuning</p>
+</div>
+</a>
+
 <p>Learn how to use common techniques to process and load {@link
 android.graphics.Bitmap} objects in a way that keeps your user interface (UI) components responsive
 and avoids exceeding your application memory limit. If you're not careful, bitmaps can quickly
diff --git a/docs/html/training/improving-layouts/index.jd b/docs/html/training/improving-layouts/index.jd
index 2f44c30..a2ab7a1 100644
--- a/docs/html/training/improving-layouts/index.jd
+++ b/docs/html/training/improving-layouts/index.jd
@@ -26,6 +26,13 @@
 </div>
 </div>
 
+<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=-FUw8HMbmBQ">
+<div>
+    <h3>Video</h3>
+    <p>DevBytes: Optimising Layouts with Hierarchy Viewer</p>
+</div>
+</a>
+
 
 
 <p>Layouts are a key part of Android applications that directly affect the user experience. If
diff --git a/docs/html/training/printing/index.jd b/docs/html/training/printing/index.jd
index 5b34a9d..e33e5e8 100644
--- a/docs/html/training/printing/index.jd
+++ b/docs/html/training/printing/index.jd
@@ -17,6 +17,13 @@
   </div>
 </div>
 
+<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=Iub67ic87KI">
+<div>
+    <h3>Video</h3>
+    <p>DevBytes: Android 4.4 Printing API</p>
+</div>
+</a>
+
 <p>
   Android users frequently view content solely on their devices, but there are times when
   showing someone a screen is not an adequate way to share information. Being able to print
diff --git a/docs/html/training/tv/index.jd b/docs/html/training/tv/index.jd
index 7c4abc7..a99e378 100644
--- a/docs/html/training/tv/index.jd
+++ b/docs/html/training/tv/index.jd
@@ -17,6 +17,14 @@
 
 </div>
 </div>
+
+<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=zsRnRLh-O34">
+<div>
+    <h3>Video</h3>
+    <p>DevBytes: Design for Large Displays - Part 1</p>
+</div>
+</a>
+
 <p> 
   Smart TVs powered by Android bring your favorite Android apps to the best screen in your house. 
   Thousands of apps in the Google Play Store are already optimized for TVs. This class shows how 
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 09481d4..1a7e3ec 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -692,6 +692,28 @@
         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);
@@ -738,4 +760,5 @@
     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);
 }