diff options
author | John Hoford <hoford@google.com> | 2014-03-27 00:14:14 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-03-27 00:14:14 +0000 |
commit | 49224acd789b2aae60bd0ec03cbf60cb9c712917 (patch) | |
tree | 3e48aa1b464017331b580e25f85381e7c83efae7 | |
parent | 2cd84701fe3df4ad65fc1c794ba403e6c9d88923 (diff) | |
parent | abb7d134c02ac60091108c491dafb00877093170 (diff) | |
download | frameworks_base-49224acd789b2aae60bd0ec03cbf60cb9c712917.zip frameworks_base-49224acd789b2aae60bd0ec03cbf60cb9c712917.tar.gz frameworks_base-49224acd789b2aae60bd0ec03cbf60cb9c712917.tar.bz2 |
Merge "add Dynamic Drawable (vector graphics for Icons)"
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><vector></code> element. + * <p/> + * The vector drawable has 6 elements: + * <p/> + * <dl> + * <dt><code><vector></code></dt><dd> + * The attribute <code>android:trigger</code> which defines a state change that + * will drive the animation </dd> + * <dt><code><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><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><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><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><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 Binary files differnew file mode 100644 index 0000000..60fbdf5 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png diff --git a/tests/DynamicDrawableTest/res/drawable/icon.png b/tests/DynamicDrawableTest/res/drawable/icon.png Binary files differnew file mode 100644 index 0000000..cb40a19 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/icon.png 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 + }; + } +} |