summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Hoford <hoford@google.com>2014-03-27 00:14:14 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-03-27 00:14:14 +0000
commit49224acd789b2aae60bd0ec03cbf60cb9c712917 (patch)
tree3e48aa1b464017331b580e25f85381e7c83efae7
parent2cd84701fe3df4ad65fc1c794ba403e6c9d88923 (diff)
parentabb7d134c02ac60091108c491dafb00877093170 (diff)
downloadframeworks_base-49224acd789b2aae60bd0ec03cbf60cb9c712917.zip
frameworks_base-49224acd789b2aae60bd0ec03cbf60cb9c712917.tar.gz
frameworks_base-49224acd789b2aae60bd0ec03cbf60cb9c712917.tar.bz2
Merge "add Dynamic Drawable (vector graphics for Icons)"
-rw-r--r--api/current.txt44
-rw-r--r--core/res/res/values/attrs.xml139
-rw-r--r--core/res/res/values/public.xml19
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java1955
-rw-r--r--tests/DynamicDrawableTest/Android.mk26
-rw-r--r--tests/DynamicDrawableTest/AndroidManifest.xml99
-rw-r--r--tests/DynamicDrawableTest/lint.xml3
-rw-r--r--tests/DynamicDrawableTest/res/drawable-hdpi/icon.pngbin0 -> 5141 bytes
-rw-r--r--tests/DynamicDrawableTest/res/drawable/icon.pngbin0 -> 3133 bytes
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml73
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml46
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml137
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml126
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml147
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml76
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml45
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml48
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml41
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml114
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml62
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml90
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml82
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml54
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml48
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml46
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml46
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml45
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml45
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml37
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml29
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml29
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml29
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml33
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml29
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_test01.xml31
-rw-r--r--tests/DynamicDrawableTest/res/drawable/vector_test02.xml31
-rw-r--r--tests/DynamicDrawableTest/res/values/strings.xml18
-rw-r--r--tests/DynamicDrawableTest/res/values/styles.xml16
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java69
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java89
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java43
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java95
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java36
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java152
-rw-r--r--tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java25
46 files changed, 4447 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt
index 9a52d26..dfee226 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -287,6 +287,7 @@ package android {
field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
field public static final int angle = 16843168; // 0x10101a0
+ field public static final int animate = 16843794; // 0x1010412
field public static final int animateFirstView = 16843477; // 0x10102d5
field public static final int animateLayoutChanges = 16843506; // 0x10102f2
field public static final int animateOnClick = 16843356; // 0x101025c
@@ -373,6 +374,7 @@ package android {
field public static final int clipChildren = 16842986; // 0x10100ea
field public static final int clipOrientation = 16843274; // 0x101020a
field public static final int clipToPadding = 16842987; // 0x10100eb
+ field public static final int clipToPath = 16843793; // 0x1010411
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int color = 16843173; // 0x10101a5
@@ -471,6 +473,7 @@ package android {
field public static final int dropDownWidth = 16843362; // 0x1010262
field public static final int duplicateParentState = 16842985; // 0x10100e9
field public static final int duration = 16843160; // 0x1010198
+ field public static final int durations = 16843786; // 0x101040a
field public static final int editTextBackground = 16843602; // 0x1010352
field public static final int editTextColor = 16843601; // 0x1010351
field public static final int editTextPreferenceStyle = 16842898; // 0x1010092
@@ -515,9 +518,11 @@ package android {
field public static final int fastScrollTextColor = 16843609; // 0x1010359
field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
+ field public static final int fill = 16843781; // 0x1010405
field public static final int fillAfter = 16843197; // 0x10101bd
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillEnabled = 16843343; // 0x101024f
+ field public static final int fillOpacity = 16843780; // 0x1010404
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -721,6 +726,7 @@ package android {
field public static final int layout_x = 16843135; // 0x101017f
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
+ field public static final int limitTo = 16843795; // 0x1010413
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -823,6 +829,7 @@ package android {
field public static final int parentActivityName = 16843687; // 0x10103a7
field public static final deprecated int password = 16843100; // 0x101015c
field public static final int path = 16842794; // 0x101002a
+ field public static final int pathData = 16843782; // 0x1010406
field public static final int pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
field public static final int permission = 16842758; // 0x1010006
@@ -832,7 +839,7 @@ package android {
field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee
field public static final deprecated int phoneNumber = 16843111; // 0x1010167
- field public static final int pinned = 16843778; // 0x1010402
+ field public static final int pinned = 16843797; // 0x1010415
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
field public static final int popupAnimationStyle = 16843465; // 0x10102c9
@@ -887,6 +894,7 @@ package android {
field public static final int readPermission = 16842759; // 0x1010007
field public static final int repeatCount = 16843199; // 0x10101bf
field public static final int repeatMode = 16843200; // 0x10101c0
+ field public static final int repeatStyle = 16843788; // 0x101040c
field public static final int reqFiveWayNav = 16843314; // 0x1010232
field public static final int reqHardKeyboard = 16843305; // 0x1010229
field public static final int reqKeyboardType = 16843304; // 0x1010228
@@ -896,7 +904,7 @@ package android {
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
- field public static final int requiredForProfile = 16843777; // 0x1010401
+ field public static final int requiredForProfile = 16843796; // 0x1010414
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
field public static final int resizeMode = 16843619; // 0x1010363
@@ -960,6 +968,7 @@ package android {
field public static final int selectableItemBackground = 16843534; // 0x101030e
field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
+ field public static final int sequence = 16843787; // 0x101040b
field public static final int settingsActivity = 16843301; // 0x1010225
field public static final int shadowColor = 16843105; // 0x1010161
field public static final int shadowDx = 16843106; // 0x1010162
@@ -1031,6 +1040,10 @@ package android {
field public static final int streamType = 16843273; // 0x1010209
field public static final int stretchColumns = 16843081; // 0x1010149
field public static final int stretchMode = 16843030; // 0x1010116
+ field public static final int stroke = 16843783; // 0x1010407
+ field public static final int strokeLineCap = 16843792; // 0x1010410
+ field public static final int strokeOpacity = 16843784; // 0x1010408
+ field public static final int strokeWidth = 16843785; // 0x1010409
field public static final int subtitle = 16843473; // 0x10102d1
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int subtypeExtraValue = 16843674; // 0x101039a
@@ -1171,6 +1184,10 @@ package android {
field public static final int translationX = 16843554; // 0x1010322
field public static final int translationY = 16843555; // 0x1010323
field public static final int translationZ = 16843769; // 0x10103f9
+ field public static final int trigger = 16843777; // 0x1010401
+ field public static final int trimPathEnd = 16843790; // 0x101040e
+ field public static final int trimPathOffset = 16843791; // 0x101040f
+ field public static final int trimPathStart = 16843789; // 0x101040d
field public static final int type = 16843169; // 0x10101a1
field public static final int typeface = 16842902; // 0x1010096
field public static final int uiOptions = 16843672; // 0x1010398
@@ -1195,6 +1212,8 @@ package android {
field public static final int verticalGap = 16843328; // 0x1010240
field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
field public static final int verticalSpacing = 16843029; // 0x1010115
+ field public static final int viewportHeight = 16843779; // 0x1010403
+ field public static final int viewportWidth = 16843778; // 0x1010402
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -10842,6 +10861,27 @@ package android.graphics.drawable {
method public void startTransition(int);
}
+ public class VectorDrawable extends android.graphics.drawable.Drawable {
+ ctor public VectorDrawable();
+ method public void draw(android.graphics.Canvas);
+ method public float geAnimationFraction();
+ method public int getOpacity();
+ method public int getRepeatCount();
+ method public void setAlpha(int);
+ method public void setAnimationFraction(float);
+ method public void setColorFilter(android.graphics.ColorFilter);
+ method public void setDuration(long);
+ method public void setIntrinsicHeight(int);
+ method public void setIntrinsicWidth(int);
+ method public void setPadding(android.graphics.Rect);
+ method public void setPadding(int, int, int, int);
+ method public void setRepeatCount(int);
+ method public void setRepeatMode(int);
+ method public void start();
+ method public void stop();
+ field public static final int INFINITE = -1; // 0xffffffff
+ }
+
}
package android.graphics.drawable.shapes {
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0cdaba8..1f03ace 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4541,6 +4541,145 @@
</declare-styleable>
<!-- ========================== -->
+ <!-- Vector drawable class -->
+ <!-- ========================== -->
+ <eat-comment />
+
+ <!-- Drawable used to draw Vector Drawables. -->
+ <declare-styleable name="VectorDrawable">
+ <!-- What event triggers the animation -->
+ <attr name="trigger" format="enum">
+ <enum name="state_pressed" value="1" />
+ <enum name="state_focused" value="2" />
+ <enum name="state_hovered" value="3" />
+ <enum name="state_selected" value="4" />
+ <enum name="state_checkable" value="5" />
+ <enum name="state_checked" value="6" />
+ <enum name="state_enabled" value="7" />
+ <enum name="state_activated" value="8" />
+ <enum name="state_window_focused" value="9" />
+ </attr>
+ </declare-styleable>
+
+ <!-- Define the virtual size of the drawing surface paths will draw to. -->
+ <declare-styleable name="VectorDrawableViewport">
+ <!-- The width of the canvas the drawing is on. -->
+ <attr name="viewportWidth" format="float"/>
+ <!-- The height of the canvas the drawing is on. -->
+ <attr name="viewportHeight" format="float"/>
+ </declare-styleable>
+
+ <!-- Define the size of the drawable -->
+ <declare-styleable name="VectorDrawableSize">
+ <!-- Width of the Vector Drawable. -->
+ <attr name="width" />
+ <!-- Height of the Vector Drawable. -->
+ <attr name="height" />
+ </declare-styleable>
+
+ <!-- Define the animations of drawable -->
+ <declare-styleable name="VectorDrawableAnimation">
+ <!-- Configures this animation sequence between the named paths -->
+ <attr name="sequence" format="string"/>
+ <!-- Limits an animation to only interpolate the selected variable -->
+ <attr name="limitTo" format="enum">
+ <enum name="unlimited" value="0"/>
+ <enum name="path" value="1"/>
+ <enum name="rotation" value="2"/>
+ <enum name="trimPathStart" value="3"/>
+ <enum name="trimPathEnd" value="4"/>
+ <enum name="trimPathOffset" value="5"/>
+ </attr>
+ <!-- Number of times to loop this aspect of the animation -->
+ <attr name="repeatCount"/>
+ <!-- A list of times in milliseconds to transision from on path to another.
+ List must contain one less than the number of named paths
+ e.g. given sequence="A,B,C,D" durations="100,0,100" implies 100ms for the
+ "A" to "B" transision instantanious switch to "C" and 100ms for "C" to "D". -->
+ <attr name="durations" format="string" />
+ <!-- The delay before stating this aspect of the animation in milli seconds -->
+ <attr name="startDelay" />
+ <!-- when repeating how does it repeat back and forth or a to b -->
+ <attr name="repeatStyle" format="enum">
+ <enum name="forward" value="0"/>
+ <enum name="reverse" value="1"/>[]
+ </attr>
+ <!-- how does the animation progress from start to finish -->
+ <attr name="animate" format="enum">
+ <enum name="linear" value="0"/>
+ <enum name="easeIn" value="1"/>
+ <enum name="easeOut" value="2"/>
+ <enum name="easeInOut" value="3"/>
+ </attr>
+ </declare-styleable>
+
+ <!-- Defines the path used in Vector Drawables. -->
+ <declare-styleable name="VectorDrawablePath">
+ <!-- The Name of this path -->
+ <attr name="name" />
+ <!-- The width a path stroke -->
+ <attr name="strokeWidth" format="float" />
+ <!-- The opacity of a path stroke -->
+ <attr name="strokeOpacity" format="float" />
+ <!-- The amount to rotate the path stroke -->
+ <attr name="rotation" />
+ <!-- The X coordinate of the center of rotation of a path -->
+ <attr name="pivotX" />
+ <!-- The Y coordinate of the center of rotation of a path -->
+ <attr name="pivotY" />
+ <!-- The color to stroke the path if not defined implies no stroke-->
+ <attr name="stroke" format="color" />
+ <!-- The color to fill the path if not defined implies no fill-->
+ <attr name="fill" format="color" />
+ <!-- The level of opacity of the filled area of the path -->
+ <attr name="fillOpacity" format="float" />
+ <!-- The specification of the operations that define the path -->
+ <attr name="pathData" format="string" />
+ <!-- The fraction of the path to trim from the start from 0 to 1 -->
+ <attr name="trimPathStart" format="float" />
+ <!-- The fraction of the path to trim from the end from 0 to 1 -->
+ <attr name="trimPathEnd" format="float" />
+ <!-- Shift trim region (allows visible region to include the start and end) from 0 to 1 -->
+ <attr name="trimPathOffset" format="float" />
+ <!-- Path will set the current clip path -->
+ <attr name="clipToPath" format="boolean" />
+ <!-- sets the linecap for a stroked path -->
+ <attr name="strokeLineCap" format="enum">
+ <enum name="butt" value="0"/>
+ <enum name="round" value="1"/>
+ <enum name="square" value="2"/>
+ </attr>
+ <!-- sets the lineJoin for a stroked path -->
+ <attr name="strokeLineJoin" format="enum">
+ <enum name="miter" value="0"/>
+ <enum name="round" value="1"/>
+ <enum name="bevel" value="2"/>
+ </attr>
+ <!-- sets the Miter limit for a stroked path -->
+ <attr name="strokeMiterLimit" format="float"/>
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_pressed" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_focused" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_selected" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_window_focused" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_enabled" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_activated" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_accelerated" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_hovered" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_checked" />
+ <!-- sets a condition to be met to draw path -->
+ <attr name="state_checkable" />
+ </declare-styleable>
+
+ <!-- ========================== -->
<!-- Animation class attributes -->
<!-- ========================== -->
<eat-comment />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d0dadf3..6aec77f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2113,6 +2113,25 @@
<public type="attr" name="controlY2" />
<public type="attr" name="sharedElementName" />
<public type="attr" name="transitionGroup" />
+ <public type="attr" name="trigger" />
+ <public type="attr" name="viewportWidth" />
+ <public type="attr" name="viewportHeight" />
+ <public type="attr" name="fillOpacity" />
+ <public type="attr" name="fill" />
+ <public type="attr" name="pathData" />
+ <public type="attr" name="stroke" />
+ <public type="attr" name="strokeOpacity" />
+ <public type="attr" name="strokeWidth" />
+ <public type="attr" name="durations" />
+ <public type="attr" name="sequence" />
+ <public type="attr" name="repeatStyle" />
+ <public type="attr" name="trimPathStart" />
+ <public type="attr" name="trimPathEnd" />
+ <public type="attr" name="trimPathOffset" />
+ <public type="attr" name="strokeLineCap" />
+ <public type="attr" name="clipToPath" />
+ <public type="attr" name="animate" />
+ <public type="attr" name="limitTo" />
<public type="attr" name="requiredForProfile"/>
<public type="attr" name="pinned" />
<public type="attr" name="colorControlNormal" />
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index de2b68f..737970b 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1062,6 +1062,8 @@ public abstract class Drawable {
drawable = new ColorDrawable();
} else if (name.equals("shape")) {
drawable = new GradientDrawable();
+ } else if (name.equals("vector")) {
+ drawable = new VectorDrawable();
} else if (name.equals("scale")) {
drawable = new ScaleDrawable();
} else if (name.equals("clip")) {
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
new file mode 100644
index 0000000..f3dd2fc
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -0,0 +1,1955 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.graphics.drawable;
+
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.Resources.Theme;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.location.Address;
+import android.net.ParseException;
+import android.sax.StartElementListener;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+/**
+ * This lets you create a drawable based on an XML vector graphic
+ * It can be defined in an XML file with the <code>&lt;vector></code> element.
+ * <p/>
+ * The vector drawable has 6 elements:
+ * <p/>
+ * <dl>
+ * <dt><code>&lt;vector></code></dt><dd>
+ * The attribute <code>android:trigger</code> which defines a state change that
+ * will drive the animation </dd>
+ * <dt><code>&lt;size></code></dt>
+ * <dd>Used to defined the intrinsic Width Height size of the drawable using
+ * <code>android:width</code> and <code>android:height</code> </dd>
+ * <dt><code>&lt;viewport></code></dt>
+ * <dd>Used to defined the size of the virtual canvas the paths are drawn on.
+ * The size is defined using the attributes <code>android:viewportHeight
+ * </code> <code>android:viewportWidth</code></dd>
+ * <dt><code>&lt;group></code></dt>
+ * <dd>Defines a "key frame" in the animation if there is only one group the
+ * drawable is static 2D image that has no animation.</dd>
+ * <dt><code>&lt;path></code></dt>
+ * <dd>Defines paths to be drawn. The path elements must be within a group
+ * <dl>
+ * <dt><code>android:name</code>
+ * <dd>Defines the name of the path.</dd></dt>
+ * <dt><code>android:pathData</code>
+ * <dd>Defines path string.</dd></dt>
+ * <dt><code>android:fill</code>
+ * <dd>Defines the color to fill the path (none if not present).</dd></dt>
+ * <dt><code>android:stroke</code>
+ * <dd>Defines the color to draw the path outline (none if not present).</dd></dt>
+ * <dt><code>android:strokeWidth</code>
+ * <dd>The width a path stroke</dd></dt>
+ * <dt><code>android:strokeOpacity</code>
+ * <dd>The opacity of a path stroke</dd></dt>
+ * <dt><code>android:rotation</code>
+ * <dd>The amount to rotation the path stroke.</dd></dt>
+ * <dt><code>android:pivotX</code>
+ * <dd>The X coordinate of the center of rotation of a path</dd></dt>
+ * <dt><code>android:pivotY</code>
+ * <dd>The Y coordinate of the center of rotation of a path</dd></dt>
+ * <dt><code>android:fillOpacity</code>
+ * <dd>The opacity to fill the path with</dd></dt>
+ * <dt><code>android:trimPathStart</code>
+ * <dd>The fraction of the path to trim from the start from 0 to 1</dd></dt>
+ * <dt><code>android:trimPathEnd</code>
+ * <dd>The fraction of the path to trim from the end from 0 to 1</dd></dt>
+ * <dt><code>android:trimPathOffset</code>
+ * <dd>Shift trim region (allows showed region to include the start and end) from 0 to 1</dd></dt>
+ * <dt><code>android:clipToPath</code>
+ * <dd>Path will set the clip path</dd></dt>
+ * <dt><code>android:strokeLineCap</code>
+ * <dd>Sets the linecap for a stroked path: butt, round, square</dd></dt>
+ * <dt><code>android:strokeLineJoin</code>
+ * <dd>Sets the lineJoin for a stroked path: miter,round,bevel</dd></dt>
+ * <dt><code>android:strokeMiterLimit</code>
+ * <dd>Sets the Miter limit for a stroked path</dd></dt>
+ * <dt><code>android:state_pressed</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_focused</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_selected</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_window_focused</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_enabled</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_activated</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_accelerated</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_hovered</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_checked</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * <dt><code>android:state_checkable</code>
+ * <dd>Sets a condition to be met to draw path</dd></dt>
+ * </dl>
+ * </dd>
+ * <dt><code>&lt;animation></code></dt>
+ * <dd>Used to customize the transition between two paths
+ * <dl>
+ * <dt><code>android:sequence</code>
+ * <dd>Configures this animation sequence between the named paths.</dd></dt>
+ * <dt><code>android:limitTo</code>
+ * <dd>Limits an animation to only interpolate the selected variable
+ * unlimited, path, rotation, trimPathStart, trimPathEnd, trimPathOffset</dd></dt>
+ * <dt><code>android:repeatCount</code>
+ * <dd>Number of times to loop this aspect of the animation</dd></dt>
+ * <dt><code>android:durations</code>
+ * <dd>The duration of each step in the animation in milliseconds
+ * Must contain the number of named paths - 1</dd></dt>
+ * <dt><code>android:startDelay</code>
+ * <dd></dd></dt>
+ * <dt><code>android:repeatStyle</code>
+ * <dd>when repeating how does it repeat back and forth or a to b: forward, inAndOut</dd></dt>
+ * <dt><code>android:animate</code>
+ * <dd>linear, accelerate, decelerate, easing</dd></dt>
+ * </dl>
+ * </dd>
+ */
+public class VectorDrawable extends Drawable {
+ private static final String LOGTAG = "VectorDrawable";
+ public static final int INFINITE = ValueAnimator.INFINITE;
+ private static final String SHAPE_SIZE = "size";
+ private static final String SHAPE_VIEWPORT = "viewport";
+ private static final String SHAPE_GROUP = "group";
+ private static final String SHAPE_PATH = "path";
+ private static final String SHAPE_TRANSITION = "transition";
+ private static final String SHAPE_ANIMATION = "animation";
+ private static final String SHAPE_VECTOR = "vector";
+
+ private static final int LINECAP_BUTT = 0;
+ private static final int LINECAP_ROUND = 1;
+ private static final int LINECAP_SQUARE = 2;
+ private static final int LINEJOIN_MITER = 0;
+ private static final int LINEJOIN_ROUND = 1;
+ private static final int LINEJOIN_BEVEL = 2;
+ private static final int DEFAULT_DURATION = 1000;
+ private static final long DEFAULT_INFINITE_DURATION = 60 * 60 * 1000;
+ private VectorDrawableState mVectorState;
+ private int mAlpha = 0xFF;
+
+ public VectorDrawable() {
+ mVectorState = new VectorDrawableState();
+ mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+ setDuration(DEFAULT_DURATION);
+ }
+
+ private VectorDrawable(VectorDrawableState state) {
+ mVectorState = new VectorDrawableState(state);
+ mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+ long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
+ if (duration == -1) { // if it set to infinite set to 1 hour
+ duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
+ mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
+ mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
+ }
+ setDuration(duration);
+ }
+
+ final static class VectorDrawableState extends ConstantState {
+ int mChangingConfigurations;
+ ValueAnimator mBasicAnimator;
+ VAnimatedPath mVAnimatedPath = new VAnimatedPath();
+ Rect mPadding;
+ int mIntrinsicHeight;
+ int mIntrinsicWidth;
+
+ public VectorDrawableState(){
+ }
+
+ public VectorDrawableState(VectorDrawableState copy){
+ mChangingConfigurations = copy.mChangingConfigurations;
+ mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
+ mPadding = new Rect(copy.mPadding);
+ mIntrinsicHeight = copy.mIntrinsicHeight;
+ mIntrinsicWidth = copy.mIntrinsicWidth;
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new VectorDrawable(this);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return mChangingConfigurations;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see android.graphics.drawable.Drawable#getConstantState()
+ */
+ @Override
+ public ConstantState getConstantState() {
+ return mVectorState;
+ }
+
+ /**
+ * start the animation
+ */
+ public void start() {
+ mVectorState.mBasicAnimator.start();
+ }
+
+ /**
+ * Stop the animation.
+ */
+ public void stop() {
+ mVectorState.mBasicAnimator.end();
+ }
+
+ /**
+ * Get the current time point in the animation
+ *
+ * @return the current point on the animation
+ */
+ public float geAnimationFraction() {
+ return mVectorState.mVAnimatedPath.getValue();
+ }
+
+ /**
+ * set the time point in the animation
+ *
+ * @param value the point along the animation typically between 0 and 1
+ */
+ public void setAnimationFraction(float value) {
+ mVectorState.mVAnimatedPath.setAnimationFraction(value);
+ invalidateSelf();
+ }
+
+ /**
+ * set the amount of time the animation will take
+ *
+ * @param duration amount of time in milliseconds
+ */
+ public void setDuration(long duration) {
+ mVectorState.mBasicAnimator.setDuration(duration);
+ }
+
+ /**
+ * Defines what this animation should do when it reaches the end. This setting is applied only
+ * when the repeat count is either greater than 0 or {@link #INFINITE}.
+ */
+ public void setRepeatMode(int mode) {
+ mVectorState.mBasicAnimator.setRepeatMode(mode);
+ }
+
+ /**
+ * Sets animation to repeat
+ *
+ * @param repeat True if this drawable repeats its animation
+ */
+ public void setRepeatCount(int repeat) {
+ mVectorState.mBasicAnimator.setRepeatCount(repeat);
+ }
+
+ /**
+ * @return True if this drawable repeats its animation
+ */
+ public int getRepeatCount() {
+ return mVectorState.mBasicAnimator.getRepeatCount();
+ }
+
+ @Override
+ public boolean isStateful() {
+ return true;
+ }
+
+ @Override
+ protected boolean onStateChange(int[] state) {
+ mVectorState.mVAnimatedPath.setState(state);
+ int direction = mVectorState.mVAnimatedPath.getTrigger(state);
+ if (direction>0) {
+ animateForward();
+ } else if (direction<0) {
+ animateBackward();
+ }
+ super.onStateChange(state);
+ invalidateSelf();
+ return true;
+ }
+
+ private void animateForward(){
+ if (!mVectorState.mBasicAnimator.isStarted()) {
+ mVectorState.mBasicAnimator.setFloatValues(0,1);
+ start();
+ }
+ }
+
+ private void animateBackward(){
+ if (!mVectorState.mBasicAnimator.isStarted()) {
+ mVectorState.mBasicAnimator.setFloatValues(.99f,0);
+ start();
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ mVectorState.mVAnimatedPath.draw(canvas);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // TODO correct handling of transparent
+ if (mAlpha != alpha) {
+ mAlpha = alpha;
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * Not implemented yet
+ * @hide
+ */
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ // TODO: support color filter
+ }
+
+ /**
+ * Returns a {@link android.graphics.PixelFormat graphics.PixelFormat}
+ * value of TRANSLUCENT.
+ */
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ /**
+ * Sets padding for this shape, defined by a Rect object. Define the padding in the Rect object
+ * as: left, top, right, bottom.
+ */
+ public void setPadding(Rect padding) {
+ setPadding(padding.left, padding.top, padding.right, padding.bottom);
+ }
+
+ /**
+ * Sets padding for the shape.
+ *
+ * @param left padding for the left side (in pixels)
+ * @param top padding for the top (in pixels)
+ * @param right padding for the right side (in pixels)
+ * @param bottom padding for the bottom (in pixels)
+ */
+ public void setPadding(int left, int top, int right, int bottom) {
+ if ((left | top | right | bottom) == 0) {
+ mVectorState.mPadding = null;
+ } else {
+ if (mVectorState.mPadding == null) {
+ mVectorState.mPadding = new Rect();
+ }
+ mVectorState.mPadding.set(left, top, right, bottom);
+ }
+ invalidateSelf();
+ }
+
+ /**
+ * Sets the intrinsic (default) width for this shape.
+ *
+ * @param width the intrinsic width (in pixels)
+ */
+ public void setIntrinsicWidth(int width) {
+ if (mVectorState.mIntrinsicWidth != width) {
+ mVectorState.mIntrinsicWidth = width;
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * Sets the intrinsic (default) height for this shape.
+ *
+ * @param height the intrinsic height (in pixels)
+ */
+ public void setIntrinsicHeight(int height) {
+ if (mVectorState.mIntrinsicHeight != height) {
+ mVectorState.mIntrinsicHeight = height;
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mVectorState.mIntrinsicWidth;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mVectorState.mIntrinsicHeight;
+ }
+
+ @Override
+ public boolean getPadding(Rect padding) {
+ if (mVectorState.mPadding != null) {
+ padding.set(mVectorState.mPadding);
+ return true;
+ } else {
+ return super.getPadding(padding);
+ }
+ }
+
+ /** @hide */
+ public static VectorDrawable create(Resources resources, int rid) {
+ try {
+ VectorDrawable drawable = new VectorDrawable();
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ XmlPullParser xpp = resources.getXml(rid);
+ AttributeSet attrs = Xml.asAttributeSet(xpp);
+ drawable.inflate(resources, xpp, attrs);
+ drawable.setAnimationFraction(0);
+ return drawable;
+ } catch (XmlPullParserException e) {
+ Log.e(LOGTAG, "parser error", e);
+ } catch (IOException e) {
+ Log.e(LOGTAG, "parser error", e);
+ }
+ return null;
+ }
+
+ @Override
+ public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
+ throws XmlPullParserException, IOException {
+ setAnimatedPath(inflateInternal(res, parser, attrs));
+ }
+
+ private VAnimatedPath inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs)
+ throws XmlPullParserException, IOException {
+ boolean noSizeTag = true;
+ boolean noViewportTag = true;
+ boolean noGroupTag = true;
+ boolean noPathTag = true;
+ final VAnimatedPath animatedPath = new VAnimatedPath();
+ VectorDrawable.VGroup currentGroup = null;
+
+ int eventType = parser.getEventType();
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ String tagName = parser.getName();
+ if (SHAPE_PATH.equals(tagName)) {
+ VectorDrawable.VPath p = new VPath(res, attrs);
+ currentGroup.add(p);
+ noPathTag = false;
+ } else if (SHAPE_ANIMATION.equals(tagName)) {
+ VectorDrawable.VAnimation anim =
+ new VAnimation(res, attrs, animatedPath.mGroupList);
+ animatedPath.addAnimation(anim);
+ } else if (SHAPE_SIZE.equals(tagName)) {
+ animatedPath.parseSize(res, attrs);
+ noSizeTag = false;
+ } else if (SHAPE_VIEWPORT.equals(tagName)) {
+ animatedPath.parseViewport(res, attrs);
+ noViewportTag = false;
+ } else if (SHAPE_GROUP.equals(tagName)) {
+ currentGroup = new VectorDrawable.VGroup();
+ animatedPath.mGroupList.add(currentGroup);
+ noGroupTag = false;
+ } else if (SHAPE_VECTOR.equals(tagName)) {
+ TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable);
+ animatedPath.setTrigger(a.getInteger(R.styleable.VectorDrawable_trigger, 0));
+ a.recycle();
+ }
+ }
+ eventType = parser.next();
+ }
+ if (noSizeTag || noViewportTag || noGroupTag || noPathTag) {
+ StringBuffer tag = new StringBuffer();
+ if (noSizeTag) {
+ tag.append("size");
+ }
+ if (noViewportTag){
+ if (tag.length()>0) {
+ tag.append(" & ");
+ }
+ tag.append("size");
+ }
+ if (noGroupTag){
+ if (tag.length()>0) {
+ tag.append(" & ");
+ }
+ tag.append("group");
+ }
+ if (noPathTag){
+ if (tag.length()>0) {
+ tag.append(" or ");
+ }
+ tag.append("path");
+ }
+ throw new XmlPullParserException("no "+tag+" defined");
+ }
+ // post parse cleanup
+ animatedPath.parseFinish();
+ return animatedPath;
+ }
+
+ private void setAnimatedPath(VAnimatedPath animatedPath) {
+ mVectorState.mVAnimatedPath = animatedPath;
+ setIntrinsicWidth((int) mVectorState.mVAnimatedPath.mBaseWidth);
+ setIntrinsicHeight((int) mVectorState.mVAnimatedPath.mBaseHeight);
+ long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
+ if (duration == -1) { // if it set to infinite set to 1 hour
+ duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
+ mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
+ mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
+ }
+ setDuration(duration);
+
+ setAnimationFraction(0);
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ boolean changed = super.setVisible(visible, restart);
+ if (visible) {
+ if (changed || restart) {
+ setAnimationFraction(0);
+ }
+ } else {
+ stop();
+ }
+ return changed;
+ }
+
+ private static class VAnimatedPath {
+ private static final String LOGTAG = "VAnimatedPath";
+
+ private ArrayList<VAnimation> mCurrentAnimList = null;
+ private VPath[] mCurrentPaths;
+ private float mAnimationValue = 0; // value goes from 0 to 1
+ private Paint mStrokePaint = null;
+ private Paint mFillPaint = null;
+ private PathMeasure mPathMeasure;
+ private Path mPath = new Path();
+ private Path mRenderPath = new Path();
+ private Matrix mMatrix = new Matrix();
+ private long mTotalDuration;
+ private int[] mCurrentState = new int[0];
+ private int mTrigger;
+ private boolean mTriggerState;
+ ArrayList<VGroup> mGroupList = new ArrayList<VGroup>();
+ float mBaseWidth = 1;
+ float mBaseHeight = 1;
+ float mViewportWidth;
+ float mViewportHeight;
+
+ public VAnimatedPath() {
+ setup();
+ }
+ public VAnimatedPath(VAnimatedPath copy) {
+ setup();
+ mCurrentAnimList = new ArrayList<VAnimation>(copy.mCurrentAnimList);
+ mGroupList = new ArrayList<VGroup>(copy.mGroupList);
+ if (copy.mCurrentPaths != null) {
+ mCurrentPaths = new VPath[copy.mCurrentPaths.length];
+ for (int i = 0; i < mCurrentPaths.length; i++) {
+ mCurrentPaths[i] = new VPath(copy.mCurrentPaths[i]);
+ }
+ }
+ mAnimationValue = copy.mAnimationValue; // time goes from 0 to 1
+
+ mBaseWidth = copy.mBaseWidth;
+ mBaseHeight = copy.mBaseHeight;
+ mViewportWidth = copy.mViewportHeight;
+ mViewportHeight = copy.mViewportHeight;
+ mTotalDuration = copy.mTotalDuration;
+ mTrigger = copy.mTrigger;
+ mCurrentState = new int[0];
+ }
+
+ public void setTrigger(int trigger){
+ int []lut = { 0,
+ R.attr.state_pressed,
+ R.attr.state_focused,
+ R.attr.state_hovered,
+ R.attr.state_selected,
+ R.attr.state_checkable,
+ R.attr.state_checked,
+ R.attr.state_activated,
+ R.attr.state_focused
+ };
+ mTrigger = lut[trigger];
+ }
+
+ private void setup(){
+ mStrokePaint = new Paint();
+ mStrokePaint.setStyle(Paint.Style.STROKE);
+ mStrokePaint.setAntiAlias(true);
+ mFillPaint = new Paint();
+ mFillPaint.setStyle(Paint.Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ }
+
+ public long getTotalAnimationDuration() {
+ mTotalDuration = 0;
+ int size = mCurrentAnimList.size();
+ for (int i = 0; i < size; i++) {
+ VAnimation vAnimation = mCurrentAnimList.get(i);
+ long t = vAnimation.getTotalDuration();
+ if (t == -1) {
+ mTotalDuration = -1;
+ return -1;
+ }
+ mTotalDuration = Math.max(mTotalDuration, t);
+ }
+
+ return mTotalDuration;
+ }
+
+ public float getValue() {
+ return mAnimationValue;
+ }
+
+ /**
+ * @param value the point along the animations to show typically between 0.0f and 1.0f
+ * @return true if you need to keep repeating
+ */
+ public boolean setAnimationFraction(float value) {
+ int len = mCurrentPaths.length;
+ getTotalAnimationDuration();
+ long animationTime = (long) (value * mTotalDuration);
+
+ for (int i = 0; i < len; i++) {
+ VPath path = mCurrentPaths[i];
+ animationTime =
+ (long) ((mTotalDuration == -1) ? value * 1000 : mTotalDuration * value);
+ int size = mCurrentAnimList.size();
+ for (int j = 0; j < size; j++) {
+ VAnimation vAnimation = mCurrentAnimList.get(j);
+ if (vAnimation.doesAdjustPath(path)) {
+ mCurrentPaths[i] = vAnimation.getPathAtTime(animationTime, path);
+ }
+ }
+ }
+ this.mAnimationValue = value;
+ if (mTotalDuration == -1) {
+ return true;
+ } else {
+ return animationTime < mTotalDuration;
+ }
+ }
+
+ public void draw(Canvas canvas) {
+ int w = canvas.getWidth();
+ int h = canvas.getHeight();
+ float scale = w / mViewportWidth;
+ scale = Math.min(h / mViewportHeight, scale);
+
+ if (mCurrentPaths == null) {
+ Log.e(LOGTAG,"mCurrentPaths == null");
+ return;
+ }
+
+ for (int i = 0; i < mCurrentPaths.length; i++) {
+ if (mCurrentPaths[i] != null && mCurrentPaths[i].isVisible(mCurrentState)) {
+ drawPath(mCurrentPaths[i], canvas, w, h);
+ }
+ }
+ }
+
+ private void drawPath(VPath vPath, Canvas canvas, int w, int h) {
+ float scale = w / mViewportWidth;
+ scale = Math.min(h / mViewportHeight, scale);
+
+ vPath.toPath(mPath);
+ Path path = mPath;
+
+ if (vPath.mTrimPathStart != 0.0f || vPath.mTrimPathEnd != 1.0f) {
+ float start = (vPath.mTrimPathStart + vPath.mTrimPathOffset) % 1.0f;
+ float end = (vPath.mTrimPathEnd + vPath.mTrimPathOffset) % 1.0f;
+
+ if (mPathMeasure == null) {
+ mPathMeasure = new PathMeasure();
+ }
+ mPathMeasure.setPath(mPath, false);
+
+ float len = mPathMeasure.getLength();
+ start = start * len;
+ end = end * len;
+ path.reset();
+ if (start > end) {
+ mPathMeasure.getSegment(start, len, path, true);
+ mPathMeasure.getSegment(0f, end, path, true);
+ } else {
+ mPathMeasure.getSegment(start, end, path, true);
+ }
+ path.rLineTo(0, 0); // fix bug in measure
+ }
+
+ mRenderPath.reset();
+ mMatrix.reset();
+
+ mMatrix.postRotate(vPath.mRotate, vPath.mPivotX, vPath.mPivotY);
+ mMatrix.postScale(scale, scale, mViewportWidth / 2f, mViewportHeight / 2f);
+ mMatrix.postTranslate(w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
+
+ mRenderPath.addPath(path, mMatrix);
+
+ if (vPath.mClip) {
+ canvas.clipPath(mRenderPath, Region.Op.REPLACE);
+ }
+ if (vPath.mFillColor != 0) {
+ mFillPaint.setColor(vPath.mFillColor);
+ int alpha = 0xFF & (vPath.mFillColor >> 24);
+ mFillPaint.setAlpha(alpha);
+ canvas.drawPath(mRenderPath, mFillPaint);
+ }
+ if (vPath.mStrokeColor != 0) {
+ if (vPath.mStrokelineJoin != null) {
+ mStrokePaint.setStrokeJoin(vPath.mStrokelineJoin);
+ }
+ if (vPath.mStrokelineCap != null) {
+ mStrokePaint.setStrokeCap(vPath.mStrokelineCap);
+ }
+ mStrokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
+ mStrokePaint.setColor(vPath.mStrokeColor);
+ mStrokePaint.setAlpha(0xFF & (vPath.mStrokeColor >> 24));
+ mStrokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
+ canvas.drawPath(mRenderPath, mStrokePaint);
+ }
+ }
+
+ /**
+ * Ensure there is at least one animation for every path in group (linking them by names)
+ * Build the "current" path based on the first group
+ * TODO: improve memory use & performance or move to C++
+ */
+ public void parseFinish() {
+ HashMap<String, VAnimation> newAnimations = new HashMap<String, VAnimation>();
+ for (VGroup group : mGroupList) {
+ for (VPath vPath : group.getPaths()) {
+ if (!vPath.mAnimated) {
+ VAnimation ap = null;
+
+ if (!newAnimations.containsKey(vPath.getID())) {
+ newAnimations.put(vPath.getID(), ap = new VAnimation());
+ } else {
+ ap = newAnimations.get(vPath.getID());
+ }
+ ap.addPath(vPath);
+ vPath.mAnimated = true;
+ }
+ }
+ }
+ if (mCurrentAnimList == null) {
+ mCurrentAnimList = new ArrayList<VectorDrawable.VAnimation>();
+ }
+ mCurrentAnimList.addAll(newAnimations.values());
+ Collection<VPath> paths = mGroupList.get(0).getPaths();
+ mCurrentPaths = paths.toArray(new VPath[paths.size()]);
+ for (int i = 0; i < mCurrentPaths.length; i++) {
+ mCurrentPaths[i] = new VPath(mCurrentPaths[i]);
+ }
+ }
+
+ public void setState(int[] state) {
+ mCurrentState = Arrays.copyOf(state, state.length);
+ }
+
+ int getTrigger(int []state){
+ if (mTrigger == 0) return 0;
+ for (int i = 0; i < state.length; i++) {
+ if (state[i] == mTrigger){
+ if (mTriggerState)
+ return 0;
+ mTriggerState = true;
+ return 1;
+ }
+ }
+ if (mTriggerState) {
+ mTriggerState = false;
+ return -1;
+ }
+ return 0;
+ }
+
+ public void addAnimation(VAnimation anim) {
+ if (mCurrentAnimList == null) {
+ mCurrentAnimList = new ArrayList<VectorDrawable.VAnimation>();
+ }
+ mCurrentAnimList.add(anim);
+ }
+
+ private void parseViewport(Resources r, AttributeSet attrs)
+ throws XmlPullParserException {
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
+ mViewportWidth = a.getFloat(R.styleable.VectorDrawableViewport_viewportWidth, 0);
+ mViewportHeight = a.getFloat(R.styleable.VectorDrawableViewport_viewportHeight, 0);
+ if (mViewportWidth == 0 || mViewportHeight == 0) {
+ throw new XmlPullParserException(a.getPositionDescription()+
+ "<viewport> tag requires viewportWidth & viewportHeight to be set");
+ }
+ a.recycle();
+ }
+
+ private void parseSize(Resources r, AttributeSet attrs)
+ throws XmlPullParserException {
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
+ mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, 0);
+ mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, 0);
+ if (mBaseWidth == 0 || mBaseHeight == 0) {
+ throw new XmlPullParserException(a.getPositionDescription()+
+ "<size> tag requires width & height to be set");
+ }
+ a.recycle();
+ }
+ }
+
+ private static class VAnimation {
+ private static final String LOGTAG = "VAnimation";
+ private VPath[] mPaths = new VPath[0];
+
+ public enum Style {
+ INTERPOLATE, CROSSFADE, WIPE
+ }
+ Interpolator mAnimInterpolator = new AccelerateDecelerateInterpolator();
+ private Style mStyle;
+ private int mLimitProperty = 0;
+ private long[] mDuration = {DEFAULT_DURATION};
+ private long mStartOffset;
+ private long mRepeat = 1;
+ private HashSet<String>mSeqMap = new HashSet<String>();
+ private long mWipeDirection;
+ private int mMode = 0; // forward = 0 inAndOut = 1;
+ private int mInterpolatorType;
+ private String mId;
+ private final static int DIRECTION_FORWARD = 0;
+ private final static int DIRECTION_IN_AND_OUT = 1;
+
+ public VAnimation() {
+ }
+
+ public boolean doesAdjustPath(VPath path) {
+ return mSeqMap.contains(path.getID());
+ }
+
+ public VAnimation(Resources r, AttributeSet attrs, ArrayList<VGroup> groups)
+ throws XmlPullParserException {
+ String value;
+ String[] sp;
+ int name;
+
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableAnimation);
+
+ value = a.getString(R.styleable.VectorDrawableAnimation_sequence);
+ if (value != null) {
+ sp = value.split(",");
+ VectorDrawable.VPath[] paths = new VectorDrawable.VPath[sp.length];
+
+ for (int j = 0; j < sp.length; j++) {
+ mSeqMap.add(sp[j].trim());
+ VectorDrawable.VPath path = groups.get(j).get(sp[j]);
+ path.mAnimated = true;
+ paths[j] = path;
+ }
+ setPaths(paths);
+ }
+
+ setLimitProperty(a.getInt(R.styleable.VectorDrawableAnimation_limitTo, 0));
+
+ name = R.styleable.VectorDrawableAnimation_durations;
+ value = a.getString(name);
+ if (value != null) {
+ long totalDuration = 0;
+ sp = value.split(",");
+ long[] dur = new long[sp.length];
+ for (int j = 0; j < dur.length; j++) {
+ dur[j] = Long.parseLong(sp[j]);
+ totalDuration += dur[j];
+ }
+ if (totalDuration == 0){
+ throw new XmlPullParserException(a.getPositionDescription()+
+ "total duration must not be zero");
+ }
+ setDuration(dur);
+ }
+
+ setRepeat(a.getInt(R.styleable.VectorDrawableAnimation_repeatCount, 1));
+
+ setStartOffset(a.getInt(R.styleable.VectorDrawableAnimation_startDelay, 0));
+
+ setMode(a.getInt(R.styleable.VectorDrawableAnimation_repeatStyle, 0));
+
+ fixMissingParameters();
+ a.recycle();
+ }
+
+ public String getId() {
+ if (mId == null) {
+ mId = mPaths[0].getID();
+ for (int i = 1; i < mPaths.length; i++) {
+ mId += mPaths[i].getID();
+ }
+ }
+ return mId;
+ }
+
+ public String getPathName() {
+ return mPaths[0].getID();
+ }
+
+ public Style getStyle() {
+ return mStyle;
+ }
+
+ public void setStyle(Style style) {
+ this.mStyle = style;
+ }
+
+ public int getLimitProperty() {
+ return mLimitProperty;
+ }
+
+ public void setLimitProperty(int limitProperty) {
+ this.mLimitProperty = limitProperty;
+ }
+
+ public long[] getDuration() {
+ return mDuration;
+ }
+
+ public void setDuration(long[] duration) {
+ this.mDuration = duration;
+ }
+
+ public long getRepeat() {
+ return mRepeat;
+ }
+
+ public void setRepeat(long repeat) {
+ this.mRepeat = repeat;
+ }
+
+ public long getStartOffset() {
+ return mStartOffset;
+ }
+
+ public void setStartOffset(long startOffset) {
+ this.mStartOffset = startOffset;
+ }
+
+ public long getWipeDirection() {
+ return mWipeDirection;
+ }
+
+ public void setWipeDirection(long wipeDirection) {
+ this.mWipeDirection = wipeDirection;
+ }
+
+ public int getMode() {
+ return mMode;
+ }
+
+ public void setMode(int mode) {
+ this.mMode = mode;
+ }
+
+ public int getInterpolator() {
+ return mInterpolatorType;
+ }
+
+ public void setInterpolator(int interpolator) {
+ this.mInterpolatorType = interpolator;
+ }
+
+ /**
+ * compute the total time in milliseconds
+ *
+ * @return the total time in milliseconds the animation will take
+ */
+ public long getTotalDuration() {
+ long total = mStartOffset;
+ if (getRepeat() == -1) {
+ return -1;
+ }
+ for (int i = 0; i < mDuration.length; i++) {
+ if (mRepeat > 1) {
+ total += mDuration[i] * mRepeat;
+ } else {
+ total += mDuration[i];
+ }
+ }
+ return total;
+ }
+
+ public void setPaths(VPath[] paths) {
+ this.mPaths = paths;
+ }
+
+ public void addPath(VPath path) {
+ mPaths = Arrays.copyOf(mPaths, mPaths.length + 1);
+ mPaths[mPaths.length - 1] = path;
+ }
+
+ public boolean containsPath(String pathid) {
+ for (int i = 0; i < mPaths.length; i++) {
+ if (mPaths[i].getID().equals(pathid)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void interpolate(VPath p1, VPath p2, float time, VPath dest) {
+ dest.interpolate(time, p1, p2, dest, mLimitProperty);
+ }
+
+ public VPath getPathAtTime(long milliseconds, VPath dest) {
+ if (mPaths.length == 1) {
+ dest.copyFrom(mPaths[0]);
+ return dest;
+ }
+ long point = milliseconds - mStartOffset;
+ if (point < 0) {
+ point = 0;
+ }
+ float time = 0;
+ long sum = mDuration[0];
+ for (int i = 1; i < mDuration.length; i++) {
+ sum += mDuration[i];
+ }
+
+ if (mRepeat > 1) {
+ time = point / (float) (sum * mRepeat);
+ time = mAnimInterpolator.getInterpolation(time);
+
+ if (mMode == DIRECTION_IN_AND_OUT) {
+ point = ((long) (time * sum * 2 * mRepeat)) % (sum * 2);
+ if (point > sum) {
+ point = sum * 2 - point;
+ }
+ } else {
+ point = ((long) (time * sum * mRepeat)) % sum;
+ }
+ } else if (mRepeat == 1) {
+ time = point / (float) (sum * mRepeat);
+ time = mAnimInterpolator.getInterpolation(time);
+ if (mMode == DIRECTION_IN_AND_OUT) {
+ point = ((long) (time * sum * 2 * mRepeat));
+ if (point > sum) {
+ point = sum * 2 - point;
+ }
+ } else {
+ point = Math.min(((long) (time * sum * mRepeat)), sum);
+ }
+
+ } else { // repeat = -1
+ if (mMode == DIRECTION_IN_AND_OUT) {
+ point = point % (sum * 2);
+ if (point > sum) {
+ point = sum * 2 - point;
+ }
+ time = point / (float) sum;
+ } else {
+ point = point % sum;
+ time = point / (float) sum;
+ }
+ }
+
+ int transition = 0;
+ while (point > mDuration[transition]) {
+ point -= mDuration[transition++];
+ }
+ if (mPaths.length > (transition + 1)) {
+ if (mPaths[transition].getID() != dest.getID()) {
+ dest.copyFrom(mPaths[transition]);
+ }
+ interpolate(mPaths[transition], mPaths[transition + 1],
+ point / (float) mDuration[transition], dest);
+ } else {
+ interpolate(mPaths[transition], mPaths[transition], 0, dest);
+ }
+ return dest;
+ }
+
+ void fixMissingParameters() {
+ // fix missing points
+ float rotation = Float.NaN;
+ float rotationY = Float.NaN;
+ float rotationX = Float.NaN;
+ for (int i = 0; i < mPaths.length; i++) {
+ if (mPaths[i].mPivotX > 0) {
+ rotationX = mPaths[i].mPivotX;
+ }
+ if (mPaths[i].mPivotY > 0) {
+ rotationY = mPaths[i].mPivotY;
+ }
+ if (mPaths[i].mRotate > 0) {
+ rotation = mPaths[i].mRotate;
+ }
+ }
+ if (rotation > 0) {
+ for (int i = 0; i < mPaths.length; i++) {
+ if (mPaths[i].mPivotX == 0) {
+ mPaths[i].mPivotX = rotationX;
+ }
+ if (mPaths[i].mPivotY == 0) {
+ mPaths[i].mPivotY = rotationY;
+ }
+ }
+ }
+ }
+ }
+
+ private static class VGroup {
+ private HashMap<String, VPath> mVGPathMap = new HashMap<String, VPath>();
+ private ArrayList<VPath> mVGList = new ArrayList<VPath>();
+
+ public void add(VPath path) {
+ String id = path.getID();
+ mVGPathMap.put(id, path);
+ mVGList.add(path);
+ }
+
+ public VPath get(String name) {
+ return mVGPathMap.get(name);
+ }
+
+ /**
+ * Must return in order of adding
+ * @return ordered list of paths
+ */
+ public Collection<VPath> getPaths() {
+ return mVGList;
+ }
+
+ public int size() {
+ return mVGPathMap.size();
+ }
+ }
+
+ private static class VPath {
+ private static final int LIMIT_ALL = 0;
+ private static final int LIMIT_PATH = 1;
+ private static final int LIMIT_ROTATE = 2;
+ private static final int LIMIT_TRIM_PATH_START = 3;
+ private static final int LIMIT_TRIM_PATH_OFFSET = 5;
+ private static final int LIMIT_TRIM_PATH_END = 4;
+ private static final int STATE_UNDEFINED=0;
+ private static final int STATE_TRUE=1;
+ private static final int STATE_FALSE=2;
+ private static final int MAX_STATES = 10;
+ private VNode[] mNode = null;
+ private String mId;
+ int mStrokeColor = 0;
+ float mStrokeWidth = 0;
+ float mStrokeOpacity = Float.NaN;
+ int mFillColor = 0;
+ int mFillRule;
+ float mFillOpacity = Float.NaN;
+ float mRotate = 0;
+ float mPivotX = 0;
+ float mPivotY = 0;
+ float mTrimPathStart = 0;
+ float mTrimPathEnd = 1;
+ float mTrimPathOffset = 0;
+ boolean mAnimated = false;
+ boolean mClip = false;
+ public Paint.Cap mStrokelineCap = null;
+ public Paint.Join mStrokelineJoin = null;
+ float mStrokeMiterlimit = 4;
+ private int[] mCheckState = new int[MAX_STATES];
+ private boolean[] mCheckValue = new boolean[MAX_STATES];
+ private int mNumberOfStates = 0;
+ private int mNumberOfTrue = 0;
+
+ public void addStateFilter(int state, boolean condition) {
+ int k = 0;
+ while (k < mNumberOfStates) {
+ if (mCheckState[mNumberOfStates] == state)
+ break;
+ k++;
+ }
+ mCheckState[k] = state;
+ mCheckValue[k] = condition;
+ if (k==mNumberOfStates){
+ mNumberOfStates++;
+ }
+ if (condition) {
+ mNumberOfTrue++;
+ }
+ }
+
+ int getState(int state){
+ for (int i = 0; i < mNumberOfStates; i++) {
+ if (mCheckState[mNumberOfStates] == state){
+ return (mCheckValue[i])?STATE_TRUE:STATE_FALSE;
+ }
+ }
+ return STATE_UNDEFINED;
+ }
+ /**
+ * @return the name of the path
+ */
+ public String getName() {
+ return mId;
+ }
+
+ public void toPath(Path path) {
+ path.reset();
+ if (mNode != null) {
+ VNode.createPath(mNode, path);
+ }
+ }
+
+ public VPath() {
+ mId = this.toString(); // to ensure paths have unique names
+ }
+
+ public VPath(VPath p) {
+ copyFrom(p);
+ }
+
+ public String getID(){
+ return mId;
+ }
+
+ public VPath(Resources r, AttributeSet attrs) {
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawablePath);
+ mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, false);
+ mId = a.getString(R.styleable.VectorDrawablePath_name);
+ mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData));
+ mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, 0);
+ mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, Float.NaN);
+
+ if (!Float.isNaN(mFillOpacity)) {
+ mFillColor &= 0x00FFFFFF;
+ mFillColor |= ((int) (0xFF * mFillOpacity)) << 24;
+ }
+ mRotate = a.getFloat(R.styleable.VectorDrawablePath_rotation, 0);
+ mPivotX = a.getFloat(R.styleable.VectorDrawablePath_pivotX, 0);
+ mPivotY = a.getFloat(R.styleable.VectorDrawablePath_pivotY, 0);
+ int lineCap = a.getInt(R.styleable.VectorDrawablePath_strokeLineCap, 0);
+ switch (lineCap) {
+ case LINECAP_BUTT:
+ mStrokelineCap = Paint.Cap.BUTT;
+ break;
+ case LINECAP_ROUND:
+ mStrokelineCap = Paint.Cap.ROUND;
+ break;
+ case LINECAP_SQUARE:
+ mStrokelineCap = Paint.Cap.SQUARE;
+ break;
+ }
+ int lineJoin = a.getInt(R.styleable.VectorDrawablePath_strokeLineJoin, 0);
+ switch (lineJoin) {
+ case LINEJOIN_MITER:
+ mStrokelineJoin = Paint.Join.MITER;
+ break;
+ case LINEJOIN_ROUND:
+ mStrokelineJoin = Paint.Join.ROUND;
+ break;
+ case LINEJOIN_BEVEL:
+ mStrokelineJoin = Paint.Join.BEVEL;
+ break;
+ }
+ mStrokeMiterlimit = a.getFloat(R.styleable.VectorDrawablePath_strokeMiterLimit,
+ mStrokeMiterlimit);
+ mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
+ mStrokeOpacity = a.getFloat(R.styleable.VectorDrawablePath_strokeOpacity, Float.NaN);
+ if (!Float.isNaN(mStrokeOpacity)) {
+ mStrokeColor &= 0x00FFFFFF;
+ mStrokeColor |= ((int) (0xFF * mStrokeOpacity)) << 24;
+ }
+ mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, 0);
+ mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, 1);
+ mTrimPathOffset = a.getFloat(R.styleable.VectorDrawablePath_trimPathOffset, 0);
+ mTrimPathStart = a.getFloat(R.styleable.VectorDrawablePath_trimPathStart, 0);
+ int[] states = {R.styleable.VectorDrawablePath_state_activated,
+ R.styleable.VectorDrawablePath_state_checkable,
+ R.styleable.VectorDrawablePath_state_checked,
+ R.styleable.VectorDrawablePath_state_enabled,
+ R.styleable.VectorDrawablePath_state_focused,
+ R.styleable.VectorDrawablePath_state_hovered,
+ R.styleable.VectorDrawablePath_state_pressed,
+ R.styleable.VectorDrawablePath_state_selected,
+ R.styleable.VectorDrawablePath_state_window_focused};
+ for (int state : states) {
+ if (a.hasValue(state)) {
+ addStateFilter(state, a.getBoolean(state, false));
+ }
+ }
+ a.recycle();
+ }
+
+ private static int nextStart(String s, int end) {
+ char c;
+
+ while (end < s.length()) {
+ c = s.charAt(end);
+ if (((c - 'A') * (c - 'Z') <= 0) || (((c - 'a') * (c - 'z') <= 0))) {
+ return end;
+ }
+ end++;
+ }
+ return end;
+ }
+
+ private void addNode(ArrayList<VectorDrawable.VNode> list, char cmd, float[] val) {
+ list.add(new VectorDrawable.VNode(cmd, val));
+ }
+
+ /**
+ * parse the floats in the string
+ * this is an optimized version of
+ * parseFloat(s.split(",|\\s"));
+ *
+ * @param s the string containing a command and list of floats
+ * @return array of floats
+ */
+ private static float[] getFloats(String s) {
+ if (s.charAt(0) == 'z' | s.charAt(0) == 'Z') {
+ return new float[0];
+ }
+ try {
+ float[] tmp = new float[s.length()];
+ int count = 0;
+ int pos = 1, end;
+ while ((end = extract(s, pos)) >= 0) {
+ if (pos < end) {
+ tmp[count++] = Float.parseFloat(s.substring(pos, end));
+ }
+ pos = end + 1;
+ }
+ // handle the final float if there is one
+ if (pos < s.length()) {
+ tmp[count++] = Float.parseFloat(s.substring(pos, s.length()));
+ }
+ return Arrays.copyOf(tmp, count);
+ } catch (NumberFormatException e){
+ Log.e(LOGTAG,"error in parsing \""+s+"\"");
+ throw e;
+ }
+ }
+
+ /**
+ * calculate the position of the next comma or space
+ * @param s the string to search
+ * @param start the position to start searching
+ * @return the position of the next comma or space or -1 if none found
+ */
+ private static int extract(String s, int start) {
+ int space = s.indexOf(' ', start);
+ int comma = s.indexOf(',', start);
+ if (space == -1) {
+ return comma;
+ }
+ if (comma == -1) {
+ return space;
+ }
+ return (comma > space) ? space : comma;
+ }
+
+ private VectorDrawable.VNode[] parsePath(String value) {
+ int start = 0;
+ int end = 1;
+
+ ArrayList<VectorDrawable.VNode> list = new ArrayList<VectorDrawable.VNode>();
+ while (end < value.length()) {
+ end = nextStart(value, end);
+ String s = value.substring(start, end);
+ float[] val = getFloats(s);
+ addNode(list, s.charAt(0), val);
+
+ start = end;
+ end++;
+ }
+ if ((end - start) == 1 && start < value.length()) {
+
+ addNode(list, value.charAt(start), new float[0]);
+ }
+ return list.toArray(new VectorDrawable.VNode[list.size()]);
+ }
+
+ public void copyFrom(VPath p1) {
+ mNode = new VNode[p1.mNode.length];
+ for (int i = 0; i < mNode.length; i++) {
+ mNode[i] = new VNode(p1.mNode[i]);
+ }
+ mId = p1.mId;
+ mStrokeColor = p1.mStrokeColor;
+ mFillColor = p1.mFillColor;
+ mStrokeWidth = p1.mStrokeWidth;
+ mRotate = p1.mRotate;
+ mPivotX = p1.mPivotX;
+ mPivotY = p1.mPivotY;
+ mAnimated = p1.mAnimated;
+ mTrimPathStart = p1.mTrimPathStart;
+ mTrimPathEnd = p1.mTrimPathEnd;
+ mTrimPathOffset = p1.mTrimPathOffset;
+ mStrokelineCap = p1.mStrokelineCap;
+ mStrokelineJoin = p1.mStrokelineJoin;
+ mStrokeMiterlimit = p1.mStrokeMiterlimit;
+ mNumberOfStates = p1.mNumberOfStates;
+ for (int i = 0; i < mNumberOfStates; i++) {
+ mCheckState[i] = p1.mCheckState[i];
+ mCheckValue[i] = p1.mCheckValue[i];
+ }
+
+ mFillRule = p1.mFillRule;
+ }
+
+ public static VPath interpolate(float t, VPath p1, VPath p2, VPath returnPath, int limit) {
+ if (limit == LIMIT_ALL || limit == LIMIT_PATH) {
+ if (returnPath.mNode == null || returnPath.mNode.length != p1.mNode.length) {
+ returnPath.mNode = new VNode[p1.mNode.length];
+ }
+ for (int i = 0; i < returnPath.mNode.length; i++) {
+ if (returnPath.mNode[i] == null) {
+ returnPath.mNode[i] = new VNode(p1.mNode[i], p2.mNode[i], t);
+ } else {
+ returnPath.mNode[i].interpolate(p1.mNode[i], p2.mNode[i], t);
+ }
+ }
+ }
+ float t1 = 1 - t;
+ switch (limit) {
+ case LIMIT_ALL:
+ returnPath.mRotate = t1 * p1.mRotate + t * p2.mRotate;
+ returnPath.mPivotX = t1 * p1.mPivotX + t * p2.mPivotX;
+ returnPath.mPivotY = t1 * p1.mPivotY + t * p2.mPivotY;
+ returnPath.mClip = p1.mClip | p2.mClip;
+
+ returnPath.mTrimPathStart = t1 * p1.mTrimPathStart + t * p2.mTrimPathStart;
+ returnPath.mTrimPathEnd = t1 * p1.mTrimPathEnd + t * p2.mTrimPathEnd;
+ returnPath.mTrimPathOffset = t1 * p1.mTrimPathOffset + t * p2.mTrimPathOffset;
+ returnPath.mStrokeMiterlimit =
+ t1 * p1.mStrokeMiterlimit + t * p2.mStrokeMiterlimit;
+ returnPath.mStrokelineCap = p1.mStrokelineCap;
+ if (returnPath.mStrokelineCap == null) {
+ returnPath.mStrokelineCap = p2.mStrokelineCap;
+ }
+ returnPath.mStrokelineJoin = p1.mStrokelineJoin;
+ if (returnPath.mStrokelineJoin == null) {
+ returnPath.mStrokelineJoin = p2.mStrokelineJoin;
+ }
+ returnPath.mFillRule = p1.mFillRule;
+
+ returnPath.mStrokeColor = rgbInterpolate(t, p1.mStrokeColor, p2.mStrokeColor);
+ returnPath.mFillColor = rgbInterpolate(t, p1.mFillColor, p2.mFillColor);
+ returnPath.mStrokeWidth = t1 * p1.mStrokeWidth + t * p2.mStrokeWidth;
+ returnPath.mNumberOfStates = p1.mNumberOfStates;
+ for (int i = 0; i < returnPath.mNumberOfStates; i++) {
+ returnPath.mCheckState[i] = p1.mCheckState[i];
+ returnPath.mCheckValue[i] = p1.mCheckValue[i];
+ }
+ for (int i = 0; i < p2.mNumberOfStates; i++) {
+ returnPath.addStateFilter(p2.mCheckState[i], p2.mCheckValue[i]);
+ }
+
+ int count = 0;
+ for (int i = 0; i < returnPath.mNumberOfStates; i++) {
+ if (returnPath.mCheckValue[i]) {
+ count++;
+ }
+ }
+ returnPath.mNumberOfTrue = count;
+ break;
+ case LIMIT_ROTATE:
+ returnPath.mRotate = t1 * p1.mRotate + t * p2.mRotate;
+ break;
+ case LIMIT_TRIM_PATH_END:
+ returnPath.mTrimPathEnd = t1 * p1.mTrimPathEnd + t * p2.mTrimPathEnd;
+ break;
+ case LIMIT_TRIM_PATH_OFFSET:
+ returnPath.mTrimPathOffset = t1 * p1.mTrimPathOffset + t * p2.mTrimPathOffset;
+ break;
+ case LIMIT_TRIM_PATH_START:
+ returnPath.mTrimPathStart = t1 * p1.mTrimPathStart + t * p2.mTrimPathStart;
+ break;
+ }
+ return returnPath;
+ }
+
+ private static int rgbInterpolate(float t, int color1, int color2) {
+ int ret;
+ if (color1 == color2) {
+ return color2;
+ }
+ if (color1 == 0) {
+ return color2;
+ }
+ if (color2 == 0) {
+ return color1;
+ }
+
+ float t1 = 1 - t;
+ ret = 0xFF & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)));
+ color1 >>= 8;
+ color2 >>= 8;
+
+ ret |= 0xFF00 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 8);
+ color1 >>= 8;
+ color2 >>= 8;
+ ret |= 0xFF0000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 16);
+ color1 >>= 8;
+ color2 >>= 8;
+ ret |= 0xFF000000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 24);
+
+ return ret;
+ }
+
+ public boolean isVisible(int[] state) {
+ int match = 0;
+ for (int i = 0; i < state.length; i++) {
+ int v = getState(state[i]);
+ if (v != STATE_UNDEFINED) {
+ if (v==STATE_TRUE) {
+ match++;
+ } else {
+ return false;
+ }
+ }
+ }
+ return match == mNumberOfTrue;
+ }
+ }
+
+ private static class VNode {
+ char type;
+ float[] params;
+ private static float[] current = new float[4];
+ public VNode(char type, float[] params) {
+ this.type = type;
+ this.params = params;
+ }
+
+ public VNode(VNode n) {
+ this.type = n.type;
+ this.params = Arrays.copyOf(n.params, n.params.length);
+ }
+
+ public VNode(VNode n1, VNode n2, float t) {
+ this.type = n1.type;
+ this.params = new float[n1.params.length];
+ interpolate(n1, n2, t);
+ }
+
+ private boolean match(VNode n) {
+ if (n.type != type) {
+ return false;
+ }
+ return (params.length == n.params.length);
+ }
+
+ public void interpolate(VNode n1, VNode n2, float t) {
+ for (int i = 0; i < n1.params.length; i++) {
+ params[i] = n1.params[i] * (1 - t) + n2.params[i] * t;
+ }
+ }
+
+ private void nodeListToPath(VNode[] node, Path path) {
+ float[] current = new float[4];
+ for (int i = 0; i < node.length; i++) {
+ addCommand(path, current, node[i].type, node[i].params);
+ }
+ }
+
+ public static void createPath(VNode[] node, Path path) {
+ Arrays.fill(current,0);
+ for (int i = 0; i < node.length; i++) {
+ addCommand(path, current, node[i].type, node[i].params);
+ }
+ }
+
+ private static void addCommand(Path path, float[] current, char cmd, float[] val) {
+
+ int incr = 2;
+ float currentX = current[0];
+ float currentY = current[1];
+ float ctrlPointX = current[2];
+ float ctrlPointY = current[3];
+
+ switch (cmd) {
+ case 'z':
+ case 'Z':
+ path.close();
+ return;
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ case 't':
+ case 'T':
+ incr = 2;
+ break;
+ case 'h':
+ case 'H':
+ case 'v':
+ case 'V':
+ incr = 1;
+ break;
+ case 'c':
+ case 'C':
+ incr = 6;
+ break;
+ case 's':
+ case 'S':
+ case 'q':
+ case 'Q':
+ incr = 4;
+ break;
+ case 'a':
+ case 'A':
+ incr = 7;
+ break;
+ }
+ for (int k = 0; k < val.length; k += incr) {
+ // TODO: build test to prove all permutations work
+ switch (cmd) {
+ case 'm': // moveto - Start a new sub-path (relative)
+ path.rMoveTo(val[k + 0], val[k + 1]);
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+ break;
+ case 'M': // moveto - Start a new sub-path
+ path.moveTo(val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+ break;
+ case 'l': // lineto - Draw a line from the current point (relative)
+ path.rLineTo(val[k + 0], val[k + 1]);
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+ break;
+ case 'L': // lineto - Draw a line from the current point
+ path.lineTo(val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+ break;
+ case 'z': // closepath - Close the current subpath
+ case 'Z': // closepath - Close the current subpath
+ path.close();
+ break;
+ case 'h': // horizontal lineto - Draws a horizontal line (relative)
+ path.rLineTo(val[k + 0], 0);
+ currentX += val[k + 0];
+ break;
+ case 'H': // horizontal lineto - Draws a horizontal line
+ path.lineTo(val[k + 0], currentY);
+ currentX = val[k + 0];
+ break;
+ case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+ path.rLineTo(0, val[k + 0]);
+ currentY += val[k + 0];
+ break;
+ case 'V': // vertical lineto - Draws a vertical line from the current point
+ path.lineTo(currentX, val[k + 0]);
+ currentY = val[k + 0];
+ break;
+ case 'c': // curveto - Draws a cubic Bézier curve (relative)
+ path.rCubicTo(val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3],
+ val[k + 4],
+ val[k + 5]);
+
+ ctrlPointX = currentX + val[k + 2];
+ ctrlPointY = currentY + val[k + 3];
+ currentX += val[k + 4];
+ currentY += val[k + 5];
+
+ break;
+ case 'C': // curveto - Draws a cubic Bézier curve
+ path.cubicTo(val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3],
+ val[k + 4],
+ val[k + 5]);
+ currentX = val[k + 4];
+ currentY = val[k + 5];
+ ctrlPointX = val[k + 2];
+ ctrlPointY = val[k + 3];
+
+ break;
+ case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+ path.rCubicTo(currentX - ctrlPointX, currentY - ctrlPointY,
+ val[k + 0], val[k + 1],
+ val[k + 2], val[k + 3]);
+
+ ctrlPointX = currentX + val[k + 0];
+ ctrlPointY = currentY + val[k + 1];
+ currentX += val[k + 2];
+ currentY += val[k + 3];
+ break;
+ case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+ path.cubicTo(2 * currentX - ctrlPointX,
+ 2 * currentY - ctrlPointY,
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3]);
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ break;
+ case 'q': // Draws a quadratic Bézier (relative)
+ path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ currentX += val[k + 2];
+ currentY += val[k + 3];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ break;
+ case 'Q': // Draws a quadratic Bézier
+ path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ break;
+ case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+ path.rQuadTo(currentX - ctrlPointX, currentY - ctrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = ctrlPointX + currentX;
+ ctrlPointY = ctrlPointY + currentY;
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+
+ break;
+ case 'T': // Draws a quadratic Bézier curve (reflective control point)
+ path.quadTo(currentX * 2 - ctrlPointX, currentY * 2 - ctrlPointY,
+ val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1]; // TODO: Check this logic
+ ctrlPointX = -(val[k + 0] - currentX);
+ ctrlPointY = -(val[k + 1] - currentY);
+ break;
+ case 'a': // Draws an elliptical arc
+ // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5] + currentX,
+ val[k + 6] + currentY,
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
+ val[k + 4] != 0);
+ currentX += val[k + 5];
+ currentY += val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+
+ break;
+ case 'A': // Draws an elliptical arc
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5],
+ val[k + 6],
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
+ val[k + 4] != 0);
+ currentX = val[k + 5];
+ currentY = val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+ break;
+ }
+ }
+ current[0] = currentX;
+ current[1] = currentY;
+ current[2] = ctrlPointX;
+ current[3] = ctrlPointY;
+ }
+
+ private static void drawArc(Path p,
+ float x0,
+ float y0,
+ float x1,
+ float y1,
+ float a,
+ float b,
+ float theta,
+ boolean isMoreThanHalf,
+ boolean isPositiveArc) {
+
+ /* Convert rotation angle from degrees to radians */
+ double thetaD = Math.toRadians(theta);
+ /* Pre-compute rotation matrix entries */
+ double cosTheta = Math.cos(thetaD);
+ double sinTheta = Math.sin(thetaD);
+ /* Transform (x0, y0) and (x1, y1) into unit space */
+ /* using (inverse) rotation, followed by (inverse) scale */
+ double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
+ double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
+ double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
+ double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
+
+ /* Compute differences and averages */
+ double dx = x0p - x1p;
+ double dy = y0p - y1p;
+ double xm = (x0p + x1p) / 2;
+ double ym = (y0p + y1p) / 2;
+ /* Solve for intersecting unit circles */
+ double dsq = dx * dx + dy * dy;
+ if (dsq == 0.0) {
+ Log.w(LOGTAG, " Points are coincident");
+ return; /* Points are coincident */
+ }
+ double disc = 1.0 / dsq - 1.0 / 4.0;
+ if (disc < 0.0) {
+ Log.w(LOGTAG, "Points are too far apart " + dsq);
+ float adjust = (float) (Math.sqrt(dsq) / 1.99999);
+ drawArc(p, x0, y0, x1, y1, a * adjust,
+ b * adjust, theta, isMoreThanHalf, isPositiveArc);
+ return; /* Points are too far apart */
+ }
+ double s = Math.sqrt(disc);
+ double sdx = s * dx;
+ double sdy = s * dy;
+ double cx;
+ double cy;
+ if (isMoreThanHalf == isPositiveArc) {
+ cx = xm - sdy;
+ cy = ym + sdx;
+ } else {
+ cx = xm + sdy;
+ cy = ym - sdx;
+ }
+
+ double eta0 = Math.atan2((y0p - cy), (x0p - cx));
+
+ double eta1 = Math.atan2((y1p - cy), (x1p - cx));
+
+ double sweep = (eta1 - eta0);
+ if (isPositiveArc != (sweep >= 0)) {
+ if (sweep > 0) {
+ sweep -= 2 * Math.PI;
+ } else {
+ sweep += 2 * Math.PI;
+ }
+ }
+
+ cx *= a;
+ cy *= b;
+ double tcx = cx;
+ cx = cx * cosTheta - cy * sinTheta;
+ cy = tcx * sinTheta + cy * cosTheta;
+
+ arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
+ }
+
+ /**
+ * Converts an arc to cubic Bezier segments and records them in p.
+ *
+ * @param p The target for the cubic Bezier segments
+ * @param cx The x coordinate center of the ellipse
+ * @param cy The y coordinate center of the ellipse
+ * @param a The radius of the ellipse in the horizontal direction
+ * @param b The radius of the ellipse in the vertical direction
+ * @param e1x E(eta1) x coordinate of the starting point of the arc
+ * @param e1y E(eta2) y coordinate of the starting point of the arc
+ * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane
+ * @param start The start angle of the arc on the ellipse
+ * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
+ */
+ private static void arcToBezier(Path p,
+ double cx,
+ double cy,
+ double a,
+ double b,
+ double e1x,
+ double e1y,
+ double theta,
+ double start,
+ double sweep) {
+ // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html
+ // and http://www.spaceroots.org/documents/ellipse/node22.html
+
+ // Maximum of 45 degrees per cubic Bezier segment
+ int numSegments = Math.abs((int) Math.ceil(sweep * 4 / Math.PI));
+
+ double eta1 = start;
+ double cosTheta = Math.cos(theta);
+ double sinTheta = Math.sin(theta);
+ double cosEta1 = Math.cos(eta1);
+ double sinEta1 = Math.sin(eta1);
+ double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
+ double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
+
+ double anglePerSegment = sweep / numSegments;
+ for (int i = 0; i < numSegments; i++) {
+ double eta2 = eta1 + anglePerSegment;
+ double sinEta2 = Math.sin(eta2);
+ double cosEta2 = Math.cos(eta2);
+ double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2);
+ double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2);
+ double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
+ double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
+ double tanDiff2 = Math.tan((eta2 - eta1) / 2);
+ double alpha =
+ Math.sin(eta2 - eta1) * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
+ double q1x = e1x + alpha * ep1x;
+ double q1y = e1y + alpha * ep1y;
+ double q2x = e2x - alpha * ep2x;
+ double q2y = e2y - alpha * ep2y;
+
+ p.cubicTo((float) q1x,
+ (float) q1y,
+ (float) q2x,
+ (float) q2y,
+ (float) e2x,
+ (float) e2y);
+ eta1 = eta2;
+ e1x = e2x;
+ e1y = e2y;
+ ep1x = ep2x;
+ ep1y = ep2y;
+ }
+ }
+
+ }
+}
diff --git a/tests/DynamicDrawableTest/Android.mk b/tests/DynamicDrawableTest/Android.mk
new file mode 100644
index 0000000..5c51301
--- /dev/null
+++ b/tests/DynamicDrawableTest/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2014 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := DynamicDrawableTest
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/DynamicDrawableTest/AndroidManifest.xml b/tests/DynamicDrawableTest/AndroidManifest.xml
new file mode 100644
index 0000000..4ca3e3c
--- /dev/null
+++ b/tests/DynamicDrawableTest/AndroidManifest.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.dynamic" >
+ <uses-sdk android:minSdkVersion="11" />
+
+ <application
+ android:hardwareAccelerated="true"
+ android:label="vector" >
+ <activity
+ android:name="VectorDrawableTest"
+ android:label="Vector Icon" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name="VectorDrawable01"
+ android:label="VectorTest1" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="VectorDrawablePerformance"
+ android:label="Vector Performance" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+
+ <activity
+ android:name="VectorDrawableDupPerf"
+ android:label="Vector Performance of clones" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+ <activity
+ android:name="VectorDrawableStaticPerf"
+ android:label="Performance of vector images" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+
+ <activity
+ android:name="VectorCheckbox"
+ android:label="On a Checkbox" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+ <activity
+ android:name="VectorPathChecking"
+ android:label="Path Checking graphics" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/tests/DynamicDrawableTest/lint.xml b/tests/DynamicDrawableTest/lint.xml
new file mode 100644
index 0000000..ee0eead
--- /dev/null
+++ b/tests/DynamicDrawableTest/lint.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+</lint> \ No newline at end of file
diff --git a/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png b/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..60fbdf5
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/tests/DynamicDrawableTest/res/drawable/icon.png b/tests/DynamicDrawableTest/res/drawable/icon.png
new file mode 100644
index 0000000..cb40a19
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/icon.png
Binary files differ
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml
new file mode 100644
index 0000000..4f4b386
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml
@@ -0,0 +1,73 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:trigger="state_checked" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="480"
+ android:viewportWidth="480" />
+
+ <group>
+ <path
+ android:name="check"
+ android:pathData="m20,200l100,90l180,-180l-35,-35l-145,145l-60,-60l-40,40z"
+ android:fill="#ffff00ff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="5" />
+ </group>
+ <group>
+ <path
+ android:name="box1"
+ android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
+ android:fill="#ffffffff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="5" />
+ </group>
+ <group>
+ <path
+ android:name="box2"
+ android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
+ android:fill="#ff000000"
+ android:rotation="46.757"
+ android:pivotX="162"
+ android:pivotY="173.5"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="5" />
+ </group>
+ <group>
+ <path
+ android:name="box3"
+ android:pathData="m187,147l-1,55l-49,-1l2,-53l48,0z"
+ android:stroke="#FF000000"
+ android:strokeWidth="4" />
+ </group>
+ <group>
+ <path
+ android:name="box4"
+ android:pathData="m248,74l0,164l-177,0l1,-165l173,-1l3,2z"
+ android:stroke="#FF000000"
+ android:strokeWidth="30" />
+ </group>
+
+ <animation
+ android:durations="300,100,0,300"
+ android:sequence="check,box1,box2,box3,box4" />
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml
new file mode 100644
index 0000000..49906d17
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml
@@ -0,0 +1,46 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="320"
+ android:viewportHeight="320"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M 100,225 L 100,115 L 130,115 L 70,15 L 10,115 L 40,115 L 40,225 z"
+ android:fill="#ffffffff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+ </group>
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M 130,225 L 130,115 L 130,115 L 70,15 L 10,115 L 10,115 L 10,225 z"
+ android:fill="#ff440000"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="180"
+ android:pivotX="70"
+ android:pivotY="120"
+ android:trimPathStart=".1"
+ android:trimPathEnd=".9"/>
+ </group>
+ <animation android:sequence="arrow,house"/>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml
new file mode 100644
index 0000000..137049d
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml
@@ -0,0 +1,137 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="7.30625"
+ android:viewportHeight="12.25"/>
+
+ <group>
+
+ <path
+ android:name="clip1"
+ android:pathData="
+ M 0, 0
+ l 7.3, 0
+ l 0, 0
+ l -7.3, 0
+ z"
+ android:clipToPath="true"
+ android:rotation="-30"
+ android:pivotX="3.65"
+ android:pivotY="6.125"
+ />
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+ l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ff88ff"
+ />
+ <path
+ android:name="clip2"
+ android:pathData="
+ M 0, 0
+ l 7.3, 0
+ l 0, 12.25
+ l -7.3, 0
+ z"
+ android:clipToPath="true"
+ android:rotation="-30"
+ android:pivotX="3.65"
+ android:pivotY="6.125"
+ />
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ff88ff"
+ />
+ </group>
+ <group>
+ <path
+ android:name="clip1"
+ android:pathData="
+ M 0, 0
+ l 7.3, 0
+ l 0, 12.25
+ l -7.3, 0
+ z"
+ android:clipToPath="true"
+ android:rotation="-30"
+ android:pivotX="3.65"
+ android:pivotY="6.125"
+ />
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+ l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ff88ff"
+ />
+ <path
+ android:name="clip2"
+ android:pathData="
+ M 0, 12.25
+ l 7.3, 0
+ l 0, 12.25
+ l -7.3, 0
+ z"
+ android:clipToPath="true"
+ android:rotation="-30"
+ android:pivotX="3.65"
+ android:pivotY="6.125"
+ />
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ff88ff"
+ />
+ </group>
+
+
+ <animation
+ android:sequence="one,one"
+ android:durations="4000"/>
+ <animation
+ android:sequence="two,two"
+ android:durations="4000"/>
+ <animation
+ android:sequence="clip1,clip1"
+ android:durations="4000"/>
+ <animation
+ android:sequence="clip2,clip2"
+ android:durations="4000"/>
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml
new file mode 100644
index 0000000..cffb73f
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml
@@ -0,0 +1,126 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="7.30625"
+ android:viewportHeight="12.25"/>
+
+ <group>
+ <path
+ android:name="clip1"
+ android:pathData="
+ M 3.65, 6.125
+ m -.001, 0
+ a .001,.001 0 1,0 .002,0
+ a .001,.001 0 1,0 -.002,0z"
+ android:clipToPath="true"
+ android:fill="#112233"
+ />
+
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+ l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ff88ff"
+ />
+ <path
+ android:name="clip2"
+ android:pathData="
+ M 3.65, 6.125
+ m -6, 0
+ a 6,6 0 1,0 12,0
+ a 6,6 0 1,0 -12,0z"
+ android:clipToPath="true"
+ android:fill="#112233"
+ />
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ff88ff"
+ />
+ </group>
+ <group>
+ <path
+ android:name="clip1"
+ android:pathData="
+ M 3.65, 6.125
+ m -6, 0
+ a 6,6 0 1,0 12,0
+ a 6,6 0 1,0 -12,0z"
+ android:clipToPath="true"
+ android:fill="#332233"
+ />
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+ l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ff88ff"
+ />
+ <path
+ android:name="clip2"
+ android:pathData="
+ M 3.65, 6.125
+ m -.001, 0
+ a .001,.001 0 1,0 .002,0
+ a .001,.001 0 1,0 -.002,0z"
+ android:clipToPath="true"
+ android:fill="#662233"
+ />
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ff88ff"
+ />
+ </group>
+
+
+
+ <animation
+ android:sequence="one,one"
+ android:durations="4000"/>
+ <animation
+ android:sequence="two,two"
+ android:durations="4000"/>
+ <animation
+ android:sequence="clip1,clip1"
+ android:durations="4000"/>
+ <animation
+ android:sequence="clip2,clip2"
+ android:durations="4000"/>
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml
new file mode 100644
index 0000000..bcf3ae6
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml
@@ -0,0 +1,147 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="7.30625"
+ android:viewportHeight="12.25"/>
+
+ <group>
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+ l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ffff00"
+ />
+
+
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ffff00"
+ android:fillOpacity="0"
+ />
+ </group>
+ <group>
+ <path
+ android:name="one"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+l -5.046875,0.0 0.0,-1.0Z"
+ android:fill="#ffff00"
+ android:fillOpacity="0"
+ />
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ffff00"
+ />
+ </group>
+ <group>
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ffff00"
+ />
+ <path
+ android:name="three"
+ android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625
+ q 0.0,1.296875 -0.890625,2.015625 -0.890625,0.703125 -2.53125,0.703125
+ q -0.546875,0.0 -1.140625,-0.109375 -0.5781251,-0.109375 -1.1875001,-0.328125
+ l 0.0,-1.140625q 0.484375,0.28125 1.0625001,0.4375 0.59375,0.140625 1.234375,0.140625
+ q 1.109375,0.0 1.6875,-0.4375 0.59375,-0.4375 0.59375,-1.28125
+ q 0.0,-0.765625 -0.546875,-1.203125 -0.546875,-0.4375 -1.5,-0.4375
+ l -1.03125,0.0 0.0,-0.96875 1.078125,0.0q 0.859375,0.0 1.328125,-0.34375
+ q 0.46875,-0.359375 0.46875,-1.015625 0.0,-0.671875 -0.484375,-1.03125
+ q -0.46875,-0.359375 -1.359375,-0.359375 -0.5,0.0 -1.0625,0.109375
+ q -0.546875,0.09375 -1.2187501,0.3125l 0.0,-1.046875q 0.6875001,-0.1875 1.2656251,-0.28125
+ q 0.59375,-0.09375 1.109375,-0.09375 1.359375,0.0 2.140625,0.609375
+ q 0.78125,0.609375 0.78125,1.65625 0.0,0.734375 -0.421875,1.234375
+ q -0.40625,0.5 -1.171875,0.6875Z"
+ android:fill="#ffff00"
+ android:fillOpacity="0"
+ />
+ </group>
+ <group>
+ <path
+ android:name="two"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+ q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
+ q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
+ q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
+ q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
+ q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
+ q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
+ q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:fill="#ffff00"
+ android:fillOpacity="0"
+ />
+ <path
+ android:name="three"
+ android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625
+ q 0.0,1.296875 -0.890625,2.015625 -0.890625,0.703125 -2.53125,0.703125
+ q -0.546875,0.0 -1.140625,-0.109375 -0.5781251,-0.109375 -1.1875001,-0.328125
+ l 0.0,-1.140625q 0.484375,0.28125 1.0625001,0.4375 0.59375,0.140625 1.234375,0.140625
+ q 1.109375,0.0 1.6875,-0.4375 0.59375,-0.4375 0.59375,-1.28125
+ q 0.0,-0.765625 -0.546875,-1.203125 -0.546875,-0.4375 -1.5,-0.4375
+ l -1.03125,0.0 0.0,-0.96875 1.078125,0.0q 0.859375,0.0 1.328125,-0.34375
+ q 0.46875,-0.359375 0.46875,-1.015625 0.0,-0.671875 -0.484375,-1.03125
+ q -0.46875,-0.359375 -1.359375,-0.359375 -0.5,0.0 -1.0625,0.109375
+ q -0.546875,0.09375 -1.2187501,0.3125l 0.0,-1.046875q 0.6875001,-0.1875 1.2656251,-0.28125
+ q 0.59375,-0.09375 1.109375,-0.09375 1.359375,0.0 2.140625,0.609375
+ q 0.78125,0.609375 0.78125,1.65625 0.0,0.734375 -0.421875,1.234375
+ q -0.40625,0.5 -1.171875,0.6875Z"
+ android:fill="#ffff00"
+ />
+ </group>
+
+
+ <animation
+ android:sequence="one,one,three,three"
+ android:durations="2000,0,2000"/>
+ <animation
+ android:sequence="two,two,two,two"
+ android:durations="2000,0,2000"/>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml
new file mode 100644
index 0000000..73ff5e2
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml
@@ -0,0 +1,76 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="700"
+ android:viewportHeight="700"/>
+
+ <group>
+ </group>
+ <path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
+ android:name="path2451"
+ android:stroke="#FF000000"
+ android:strokeWidth="30.65500000000000"/>
+ <path android:pathData="M 365.015 311.066"
+ android:name="path2453"
+ android:stroke="#FF000000"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928"
+ android:name="path2455"
+ android:stroke="#FF000000"
+ android:fill="#FF0000FF"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 170.515 451.566L 305.61 313.46"
+ android:name="path2457"
+ android:stroke="#000000"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 557.968 449.974L 426.515 315.375"
+ android:name="path2459"
+ android:stroke="#000000"
+ android:strokeWidth="30.655000000000001"/>
+ <group>
+ <path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
+ android:name="path2451"
+ android:stroke="#FF000000"
+ android:strokeWidth="30.65500000000000"/>
+ <path android:pathData="M 365.015 311.066"
+ android:name="path2453"
+ android:stroke="#FF000000"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928"
+ android:name="path2455"
+ android:stroke="#FF000000"
+ android:fill="#FFFFFFFF"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 170.515 451.566L 305.61 313.46"
+ android:name="path2457"
+ android:stroke="#000000"
+ android:strokeWidth="30.655000000000001"/>
+ <path android:pathData="M 557.968 449.974L 426.515 315.375"
+ android:name="path2459"
+ android:stroke="#000000"
+ android:strokeWidth="30.655000000000001"/>
+ </group>
+
+ <animation android:sequence="path2451,path2451"
+ android:durations="1000"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml
new file mode 100644
index 0000000..99d37ef
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml
@@ -0,0 +1,45 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="140"
+ android:viewportHeight="110"/>
+ <group>
+ <path
+ android:name="menu"
+ android:pathData="M 20,20 l 100,0 0,10 -100,0 z
+ M 20,50 l 100,0 0,10 -100,0 z
+ M 20,80 l 0,-10 100,0 0,10 z"
+ android:fill="#ffffffff"/>
+ </group>
+ <group>
+ <path
+ android:name="back"
+ android:pathData="M 20,55 l 35.3,-35.3 7.07,7.07 -35.3,35.3 z
+ M 27,50 l 97,0 0,10 -97,0 z
+ M 20,55 l 7.07,-7.07 35.3,35.3 -7.07,7.07 z"
+ android:fill="#ffffffff"
+ android:rotation="180"
+ android:pivotX="70"
+ android:pivotY="55"
+ />
+ </group>
+ <animation android:sequence="menu,back"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml
new file mode 100644
index 0000000..f8a03d7
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml
@@ -0,0 +1,48 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="600"
+ android:viewportHeight="600"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M535.441,412.339A280.868,280.868 0 1,1 536.186,161.733L284.493,286.29Z"
+ android:fill="#ffffcc00"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+ </group>
+
+ <group>
+ <path
+ android:name="pie2"
+ android:pathData="M564.441,287A280.868,280.868 0 1,1 564.441,285L284.493,286.29Z"
+ android:fill="#FFccaa00"
+ android:stroke="#FF000000"
+ android:strokeWidth="10"
+ android:pivotX="90"
+ android:pivotY="100"/>
+ </group>
+
+ <animation android:sequence="pie1,pie2"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml
new file mode 100644
index 0000000..09934de
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml
@@ -0,0 +1,41 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="200"
+ android:viewportHeight="200"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M 20,20 l 60,0 0,140 -60,0 z M 120,20 l 60,0 0,140 -60,0 z"
+ android:fill="#ffffffff"/>
+ </group>
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M 100,20 l 0,0 0,140 -80,0 z M 100,20 l 0,0 80,140 -80,0 z"
+ android:fill="#ffffffff"
+ android:rotation="90"
+ android:pivotX="100"
+ android:pivotY="100"/>
+ </group>
+ <animation android:sequence="arrow,house"/>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml
new file mode 100644
index 0000000..f17f67a
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="200"
+ android:viewportWidth="200" />
+
+ <group>
+ <path
+ android:name="bar3"
+ android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
+ android:fill="#FF555555" />
+ <path
+ android:name="bar1"
+ android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
+ android:fill="#FF555555" />
+ <path
+ android:name="bar0"
+ android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
+ android:fill="#FF555555" />
+ </group>
+ <group>
+ <path
+ android:name="bar3"
+ android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar1"
+ android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
+ android:fill="#FF555555" />
+ <path
+ android:name="bar0"
+ android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
+ android:fill="#FF555555" />
+ </group>
+
+ <group>
+ <path
+ android:name="bar3"
+ android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar1"
+ android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar0"
+ android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
+ android:fill="#FF555555" />
+ </group>
+
+ <group>
+ <path
+ android:name="bar3"
+ android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar1"
+ android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar0"
+ android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
+ android:fill="#FFFFFFFF" />
+ </group>
+
+ <animation
+ android:sequence="bar0,bar0,bar0,bar0"
+ android:durations="500,500,500"/>
+ <animation
+ android:sequence="bar1,bar1,bar1,bar1"
+ android:durations="500,500,500"/>
+ <animation
+ android:sequence="bar2,bar2,bar2,bar2"
+ android:durations="500,500,500"/>
+ <animation
+ android:sequence="bar3,bar3,bar3,bar3"
+ android:durations="500,500,500"/>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml
new file mode 100644
index 0000000..a1a03be
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml
@@ -0,0 +1,62 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="80"
+ android:viewportWidth="40" />
+
+ <group>
+ <path
+ android:name="battery"
+ android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
+ android:fill="#3388ff"
+ android:stroke="#ff8833"
+ android:strokeWidth="1"
+ android:rotation="0"/>
+ <path
+ android:name="spark"
+ android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z"
+ android:fill="#FFFF0000" />
+
+ </group>
+ <group>
+ <path
+ android:name="battery"
+ android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
+ android:fill="#ff8833"
+ android:stroke="#3388ff"
+ android:strokeWidth="1"
+ android:rotation="0" />
+ <path
+ android:name="spark"
+ android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z"
+ android:fill="#FFFF0000" />
+ </group>
+
+ <animation
+ android:durations="2000"
+ android:sequence="spark,spark" />
+ <animation
+ android:durations="2000"
+ android:sequence="battery,battery" />
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml
new file mode 100644
index 0000000..89748d5
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml
@@ -0,0 +1,90 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="600"
+ android:viewportHeight="600"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M300,70 a230,230 0 1,0 1,0 z"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="70"
+ android:trimPathStart="0"
+ android:trimPathEnd=".75"
+ android:trimPathOffset="0"/>
+
+ <path
+ android:name="v"
+ android:pathData="M300,70 l 0,-70 70,70 -70,70z"
+ android:fill="#FF00FF00"
+ android:pivotX="300"
+ android:pivotY="300"
+ android:rotation="0"
+ />
+ </group>
+
+ <group>
+ <path
+ android:name="v"
+ android:pathData="M300,70 l 0,-70 70,70 -70,70z"
+ android:pivotX="300"
+ android:pivotY="300"
+ android:rotation="360"/>
+ <path
+ android:name="pie2"
+ android:pathData="M300,70 a230,230 0 1,0 1,0 z"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="70"
+ android:rotation="360"
+ android:pivotX="300"
+ android:pivotY="300"
+ android:trimPathStart="0"
+ android:trimPathEnd=".5"
+ android:trimPathOffset="0"
+ android:strokeLineCap="round"
+ />
+ </group>
+
+ <animation android:sequence="pie1,pie2"
+ android:durations="2000"
+ android:startOffset="500"
+ android:repeatCount="-1"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+ <animation android:sequence="v,v"
+ android:durations="2000"
+ android:startOffset="500"
+ android:repeatCount="-1"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+ <animation android:sequence="pie1,pie2"
+ android:durations="2800"
+ android:startOffset="500"
+ android:limitTo="trimPathEnd"
+ android:repeatCount="-1"
+ android:repeatStyle="reverse"
+ android:animate="easeInOut"
+ />
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml
new file mode 100644
index 0000000..43dda52
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml
@@ -0,0 +1,82 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="600"
+ android:viewportHeight="400"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
+ android:fill="#ffffffff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+
+ <path
+ android:name="half"
+ android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
+ android:fill="#FFFF0000"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="5"
+ android:rotation="0"
+ android:pivotX="300"
+ android:pivotY="200"/>
+ </group>
+
+ <group>
+ <path
+ android:name="pie2"
+ android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
+ android:fill="#ffff0000"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="300"
+ android:pivotY="200"/>
+
+ <path
+ android:name="half"
+ android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
+ android:fill="#FFFFFF00"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="5"
+ android:rotation="-360"
+ android:pivotX="300"
+ android:pivotY="200"/>
+ </group>
+ <animation android:sequence="pie1,pie2"
+ android:durations="1000"
+ android:startOffset="500"
+ android:repeatCount="2"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+ <animation android:sequence="half,half"
+ android:durations="1000"
+ android:startOffset="500"
+ android:repeatCount="5"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml
new file mode 100644
index 0000000..0f1f149
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml
@@ -0,0 +1,54 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="800"
+ android:viewportHeight="500"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M200,450 l 50,-25
+ a25,25 -30 0,1 100,-50 l 50,-25
+ a25,50 -30 0,1 100,-50 l 50,-25
+ a25,75 -30 0,1 100,-50 l 50,-25
+ a25,100 -30 0,1 100,-50 l 50,-25"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"/>
+ </group>
+
+ <group>
+ <path
+ android:name="pie2"
+ android:pathData="M200,350 l 50,-25
+ a25,12 -30 0,1 100,-50 l 50,-25
+ a25,25 -30 0,1 100,-50 l 50,-25
+ a25,37 -30 0,1 100,-50 l 50,-25
+ a25,50 -30 0,1 100,-50 l 50,-25"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="20"
+ android:pivotX="90"
+ android:pivotY="100"/>
+
+ </group>
+ <animation android:sequence="pie1,pie2"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml
new file mode 100644
index 0000000..6bc946f
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml
@@ -0,0 +1,48 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="500"
+ android:viewportHeight="400"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:fill="#ffffffff"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="1"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:fill="#ff440000"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="10"
+ android:rotation="180"
+ android:pivotX="250"
+ android:pivotY="200"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml
new file mode 100644
index 0000000..c9c8e8a
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml
@@ -0,0 +1,46 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="200"
+ android:viewportHeight="200"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M 100,10 v 180 M 10,100 h 180"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M 100,10 v 90 M 10,100 h 90"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="100"
+ android:pivotY="100"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml
new file mode 100644
index 0000000..9427652
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml
@@ -0,0 +1,46 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="1200"
+ android:viewportHeight="600"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M200,300 Q400,50 600,300 T1000,300"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M200,300 Q400,50 600,300 T1000,300"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="600"
+ android:pivotY="300"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml
new file mode 100644
index 0000000..83dfbd2
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml
@@ -0,0 +1,45 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="500"
+ android:viewportHeight="400"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:stroke="#FFFFFF00"
+ android:strokeWidth="10"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="250"
+ android:pivotY="200"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml
new file mode 100644
index 0000000..013254f
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml
@@ -0,0 +1,45 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="1000"
+ android:viewportHeight="800"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M10,300 Q400,50 600,300 T1000,300"
+ android:stroke="#FF00FFFF"
+ android:strokeWidth="40"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M10,300 Q400,550 600,300 T1000,300"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="60"
+ android:pivotX="90"
+ android:pivotY="100"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml
new file mode 100644
index 0000000..aba7e5f
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml
@@ -0,0 +1,37 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="480"
+ android:viewportHeight="480"/>
+
+ <group>
+ <path
+ android:name="edit"
+ android:pathData="M406.667,180c0,0 -100 -100 -113.334 -113.333
+ c-13.333 -13.334 -33.333,0 -33.333,0l-160,160c0,0 -40,153.333 -40,173.333c0,13.333,13.333,13.333,13.333,13.333l173.334 -40
+ c0,0,146.666 -146.666,160 -160C420,200,406.667,180,406.667,180z M226.399,356.823L131.95,378.62l-38.516 -38.522
+ c7.848 -34.675,20.152 -82.52,23.538 -95.593l3.027,2.162l106.667,106.666L226.399,356.823z"
+ android:stroke="#FF000000"
+ android:fill="#FF00FFFF"
+ android:strokeWidth="10"/>
+ </group>
+
+
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml
new file mode 100644
index 0000000..8897181
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.813995,9.936001l-3.75,-3.75L3.0,17.25zM20.707,7.0429993c0.391,-0.391 0.391,-1.023 0.0,-1.414l-2.336,-2.336c-0.391,-0.391 -1.023,-0.391 -1.414,0.0l-1.832,1.832l3.75,3.75L20.707,7.0429993z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml
new file mode 100644
index 0000000..2c7ebbd
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0,-0.896 2.0,-2.0l0.0,-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0,-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0,-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml
new file mode 100644
index 0000000..e4cf78c
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67,-1.732 -2.547,-3.0 -4.5,-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207,-5.242 9.0,-7.971 9.0,-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml
new file mode 100644
index 0000000..cec12ba
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml
@@ -0,0 +1,33 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M11.994999,2.0C6.4679985,2.0 2.0,6.4780006 2.0,12.0s4.468,10.0 9.995,10.0S22.0,17.522 22.0,12.0S17.521,2.0 11.994999,2.0zM12.0,20.0c-4.42,0.0 -8.0,-3.582 -8.0,-8.0s3.58,-8.0 8.0,-8.0s8.0,3.582 8.0,8.0S16.419998,20.0 12.0,20.0z"
+ android:fillOpacity="0.9"
+ />
+<path
+ android:pathData="M12.5,6.0l-1.5,0.0 0.0,7.0 5.3029995,3.1819992 0.75,-1.249999 -4.5529995,-2.7320004z"
+ android:fillOpacity="0.9"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml
new file mode 100644
index 0000000..5fe1fb6
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M19.429,12.975998c0.042,-0.32 0.07,-0.645 0.07,-0.976s-0.029,-0.655 -0.07,-0.976l2.113,-1.654c0.188,-0.151 0.243,-0.422 0.118,-0.639l-2.0,-3.463c-0.125,-0.217 -0.386,-0.304 -0.612,-0.218l-2.49,1.004c-0.516,-0.396 -1.081,-0.731 -1.69,-0.984l-0.375,-2.648C14.456,2.1829987 14.25,2.0 14.0,2.0l-4.0,0.0C9.75,2.0 9.544,2.1829987 9.506,2.422001L9.131,5.0699997C8.521,5.322998 7.957,5.6570015 7.44,6.054001L4.952,5.0509987C4.726,4.965 4.464,5.052002 4.34,5.269001l-2.0,3.463C2.2150002,8.947998 2.27,9.219002 2.4580002,9.369999l2.112,1.653C4.528,11.344002 4.5,11.668999 4.5,12.0s0.029,0.656 0.071,0.977L2.4580002,14.630001c-0.188,0.151 -0.243,0.422 -0.118,0.639l2.0,3.463c0.125,0.217 0.386,0.304 0.612,0.218l2.489,-1.004c0.516,0.396 1.081,0.731 1.69,0.984l0.375,2.648C9.544,21.817001 9.75,22.0 10.0,22.0l4.0,0.0c0.25,0.0 0.456,-0.183 0.494,-0.422l0.375,-2.648c0.609,-0.253 1.174,-0.588 1.689,-0.984l2.49,1.004c0.226,0.086 0.487,-0.001 0.612,-0.218l2.0,-3.463c0.125,-0.217 0.07,-0.487 -0.118,-0.639L19.429,12.975998zM12.0,16.0c-2.21,0.0 -4.0,-1.791 -4.0,-4.0c0.0,-2.21 1.79,-4.0 4.0,-4.0c2.208,0.0 4.0,1.79 4.0,4.0C16.0,14.209 14.208,16.0 12.0,16.0z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_test01.xml b/tests/DynamicDrawableTest/res/drawable/vector_test01.xml
new file mode 100644
index 0000000..6beb9d8
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_test01.xml
@@ -0,0 +1,31 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="128dp"
+android:height="128dp"/>
+
+ <viewport android:viewportWidth="512"
+ android:viewportHeight="512"/>
+
+<group>
+<path
+ android:name="002b"
+ android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0t-200,299"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="4"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_test02.xml b/tests/DynamicDrawableTest/res/drawable/vector_test02.xml
new file mode 100644
index 0000000..2c1a28e
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/drawable/vector_test02.xml
@@ -0,0 +1,31 @@
+<!-- Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="128dp"
+android:height="128dp"/>
+
+ <viewport android:viewportWidth="512"
+ android:viewportHeight="512"/>
+
+<group>
+<path
+ android:name="002b"
+ android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0T-200,299"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="4"
+ />
+</group>
+</vector>
diff --git a/tests/DynamicDrawableTest/res/values/strings.xml b/tests/DynamicDrawableTest/res/values/strings.xml
new file mode 100644
index 0000000..64163c2
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<resources>
+</resources>
diff --git a/tests/DynamicDrawableTest/res/values/styles.xml b/tests/DynamicDrawableTest/res/values/styles.xml
new file mode 100644
index 0000000..460c0db
--- /dev/null
+++ b/tests/DynamicDrawableTest/res/values/styles.xml
@@ -0,0 +1,16 @@
+<!-- Copyright (C) 2014 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.
+-->
+<resources>
+</resources>
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
new file mode 100644
index 0000000..1060d19
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 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 com.android.test.dynamic;
+
+import android.app.Activity;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.GridLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorCheckbox extends Activity {
+ private static final String LOGCAT = "VectorDrawable1";
+ int[] icon = {
+ R.drawable.vector_drawable01,
+ R.drawable.vector_drawable02,
+ R.drawable.vector_drawable03,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable05,
+ R.drawable.vector_drawable06,
+ R.drawable.vector_drawable07,
+ R.drawable.vector_drawable08,
+ R.drawable.vector_drawable09,
+ R.drawable.vector_drawable10,
+ R.drawable.vector_drawable11,
+ R.drawable.vector_drawable12,
+ R.drawable.vector_drawable13,
+ R.drawable.vector_drawable14,
+ R.drawable.vector_drawable15,
+ R.drawable.vector_drawable16,
+ R.drawable.vector_drawable17,
+ R.drawable.vector_drawable18,
+ R.drawable.vector_drawable19,
+ R.drawable.vector_drawable20
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ GridLayout container = new GridLayout(this);
+ container.setColumnCount(5);
+ container.setBackgroundColor(0xFF888888);
+ final Button []bArray = new Button[icon.length];
+
+ for (int i = 0; i < icon.length; i++) {
+ CheckBox checkBox = new CheckBox(this);
+ bArray[i] = checkBox;
+ checkBox.setWidth(200);
+ checkBox.setWidth(200);
+ checkBox.setButtonDrawable(icon[i]);
+ container.addView(checkBox);
+ }
+ setContentView(container);
+ }
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
new file mode 100644
index 0000000..0ae4b6d
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 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 com.android.test.dynamic;
+
+import android.app.Activity;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.GridLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawable01 extends Activity implements View.OnClickListener {
+ private static final String LOGCAT = "VectorDrawable1";
+ int[] icon = {
+ R.drawable.vector_drawable01,
+ R.drawable.vector_drawable02,
+ R.drawable.vector_drawable03,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable05,
+ R.drawable.vector_drawable06,
+ R.drawable.vector_drawable07,
+ R.drawable.vector_drawable08,
+ R.drawable.vector_drawable09,
+ R.drawable.vector_drawable10,
+ R.drawable.vector_drawable11,
+ R.drawable.vector_drawable12,
+ R.drawable.vector_drawable13,
+ R.drawable.vector_drawable14,
+ R.drawable.vector_drawable15,
+ R.drawable.vector_drawable16,
+ R.drawable.vector_drawable17,
+ R.drawable.vector_drawable18,
+ R.drawable.vector_drawable19,
+ R.drawable.vector_drawable20
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ GridLayout container = new GridLayout(this);
+ container.setColumnCount(5);
+ container.setBackgroundColor(0xFF888888);
+ final Button []bArray = new Button[icon.length];
+
+ for (int i = 0; i < icon.length; i++) {
+ Button button = new Button(this);
+ bArray[i] = button;
+ button.setWidth(200);
+ button.setWidth(200);
+ button.setBackgroundResource(icon[i]);
+ container.addView(button);
+ button.setOnClickListener(this);
+ }
+ Button b = new Button(this);
+ b.setText("Run All");
+ b.setOnClickListener(new View.OnClickListener(){
+
+ @Override
+ public void onClick(View v) {
+ for (int i = 0; i < bArray.length; i++) {
+ VectorDrawable d = (VectorDrawable) bArray[i].getBackground();
+ d.start();
+ }
+ }});
+ container.addView(b);
+ setContentView(container);
+
+ }
+
+ @Override
+ public void onClick(View v) {
+ VectorDrawable d = (VectorDrawable) v.getBackground();
+ d.start();
+ }
+
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java
new file mode 100644
index 0000000..a00bc5e
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 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 com.android.test.dynamic;
+
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawableDupPerf extends VectorDrawablePerformance {
+ {
+ icon = new int[]{
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ };
+ }
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
new file mode 100644
index 0000000..9e8ea75
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 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 com.android.test.dynamic;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Button;
+import android.widget.GridLayout;
+import android.widget.ScrollView;
+import java.text.DecimalFormat;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawablePerformance extends Activity implements View.OnClickListener {
+ private static final String LOGCAT = "VectorDrawable1";
+ protected int[] icon = {
+ R.drawable.vector_drawable01,
+ R.drawable.vector_drawable02,
+ R.drawable.vector_drawable03,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable05,
+ R.drawable.vector_drawable06,
+ R.drawable.vector_drawable07,
+ R.drawable.vector_drawable08,
+ R.drawable.vector_drawable09,
+ R.drawable.vector_drawable10,
+ R.drawable.vector_drawable11,
+ R.drawable.vector_drawable12,
+ R.drawable.vector_drawable13,
+ R.drawable.vector_drawable14,
+ R.drawable.vector_drawable15,
+ R.drawable.vector_drawable16,
+ R.drawable.vector_drawable17,
+ R.drawable.vector_drawable18,
+ R.drawable.vector_drawable19,
+ R.drawable.vector_drawable20
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ScrollView scrollView = new ScrollView(this);
+ GridLayout container = new GridLayout(this);
+ scrollView.addView(container);
+ container.setColumnCount(5);
+ Resources res = this.getResources();
+ container.setBackgroundColor(0xFF888888);
+ VectorDrawable []d = new VectorDrawable[icon.length];
+ long time = android.os.SystemClock.elapsedRealtimeNanos();
+ for (int i = 0; i < icon.length; i++) {
+ d[i] = VectorDrawable.create(res,icon[i]);
+ }
+ time = android.os.SystemClock.elapsedRealtimeNanos()-time;
+ TextView t = new TextView(this);
+ DecimalFormat df = new DecimalFormat("#.##");
+ t.setText("avgL=" + df.format(time / (icon.length * 1000000.)) + " ms");
+ t.setBackgroundColor(0xFF000000);
+ container.addView(t);
+ time = android.os.SystemClock.elapsedRealtimeNanos();
+ for (int i = 0; i < icon.length; i++) {
+ Button button = new Button(this);
+ button.setWidth(200);
+ button.setWidth(200);
+ button.setBackgroundResource(icon[i]);
+ container.addView(button);
+ button.setOnClickListener(this);
+ }
+ setContentView(scrollView);
+ time = android.os.SystemClock.elapsedRealtimeNanos()-time;
+ t = new TextView(this);
+ t.setText("avgS=" + df.format(time / (icon.length * 1000000.)) + " ms");
+ t.setBackgroundColor(0xFF000000);
+ container.addView(t);
+ }
+
+ @Override
+ public void onClick(View v) {
+ VectorDrawable d = (VectorDrawable) v.getBackground();
+ d.start();
+ }
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java
new file mode 100644
index 0000000..9d3eded
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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 com.android.test.dynamic;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Button;
+import android.widget.GridLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawableStaticPerf extends VectorDrawablePerformance {
+ {
+ icon = new int[]{
+ R.drawable.vector_icon_create,
+ R.drawable.vector_icon_delete,
+ R.drawable.vector_icon_heart,
+ R.drawable.vector_icon_schedule,
+ R.drawable.vector_icon_settings,
+ };
+ }
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java
new file mode 100644
index 0000000..704d3d7
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 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 com.android.test.dynamic;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings("UnusedDeclaration")
+public class VectorDrawableTest extends android.app.ListActivity {
+ private static final String EXTRA_PATH = "com.android.test.dynamic.Path";
+ private static final String CATEGORY_HWUI_TEST = "com.android.test.dynamic.TEST";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent = getIntent();
+ String path = intent.getStringExtra("com.android.test.hwui.Path");
+
+ if (path == null) {
+ path = "";
+ }
+
+ setListAdapter(new SimpleAdapter(this, getData(path),
+ android.R.layout.simple_list_item_1, new String[] { "title" },
+ new int[] { android.R.id.text1 }));
+ getListView().setTextFilterEnabled(true);
+ }
+
+ protected List<Map<String, Object>> getData(String prefix) {
+ List<Map<String, Object>> myData = new ArrayList<Map<String, Object>>();
+
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(CATEGORY_HWUI_TEST);
+
+ PackageManager pm = getPackageManager();
+ List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
+
+ if (null == list)
+ return myData;
+
+ String[] prefixPath;
+ String prefixWithSlash = prefix;
+
+ if (prefix.equals("")) {
+ prefixPath = null;
+ } else {
+ prefixPath = prefix.split("/");
+ prefixWithSlash = prefix + "/";
+ }
+
+ int len = list.size();
+
+ Map<String, Boolean> entries = new HashMap<String, Boolean>();
+
+ for (int i = 0; i < len; i++) {
+ ResolveInfo info = list.get(i);
+ CharSequence labelSeq = info.loadLabel(pm);
+ String label = labelSeq != null
+ ? labelSeq.toString()
+ : info.activityInfo.name;
+
+ if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) {
+
+ String[] labelPath = label.split("/");
+
+ String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];
+
+ if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
+ addItem(myData, nextLabel, activityIntent(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name));
+ } else {
+ if (entries.get(nextLabel) == null) {
+ addItem(myData, nextLabel, browseIntent(prefix.equals("") ?
+ nextLabel : prefix + "/" + nextLabel));
+ entries.put(nextLabel, true);
+ }
+ }
+ }
+ }
+
+ Collections.sort(myData, sDisplayNameComparator);
+
+ return myData;
+ }
+
+ private final static Comparator<Map<String, Object>> sDisplayNameComparator =
+ new Comparator<Map<String, Object>>() {
+ private final Collator collator = Collator.getInstance();
+
+ public int compare(Map<String, Object> map1, Map<String, Object> map2) {
+ return collator.compare(map1.get("title"), map2.get("title"));
+ }
+ };
+
+ protected Intent activityIntent(String pkg, String componentName) {
+ Intent result = new Intent();
+ result.setClassName(pkg, componentName);
+ return result;
+ }
+
+ protected Intent browseIntent(String path) {
+ Intent result = new Intent();
+ result.setClass(this, VectorDrawableTest.class);
+ result.putExtra(EXTRA_PATH, path);
+ return result;
+ }
+
+ protected void addItem(List<Map<String, Object>> data, String name, Intent intent) {
+ Map<String, Object> temp = new HashMap<String, Object>();
+ temp.put("title", name);
+ temp.put("intent", intent);
+ data.add(temp);
+ }
+
+ @Override
+ @SuppressWarnings({ "unchecked", "UnusedParameters" })
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position);
+
+ Intent intent = (Intent) map.get("intent");
+ startActivity(intent);
+ }
+}
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java
new file mode 100644
index 0000000..3430192
--- /dev/null
+++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 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 com.android.test.dynamic;
+
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorPathChecking extends VectorDrawablePerformance {
+ {
+ icon = new int[]{
+ R.drawable.vector_test01,
+ R.drawable.vector_test02
+ };
+ }
+}