summaryrefslogtreecommitdiffstats
path: root/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'graphics')
-rw-r--r--graphics/Android.mk16
-rw-r--r--graphics/drawable/Android.mk41
-rw-r--r--graphics/drawable/AndroidManifest.xml4
-rw-r--r--graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java504
-rw-r--r--graphics/drawable/res/values/attrs.xml183
-rwxr-xr-xgraphics/drawable/runavdtest.sh5
-rwxr-xr-xgraphics/drawable/runtest.sh5
-rw-r--r--graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java718
-rw-r--r--graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java1470
-rw-r--r--graphics/drawable/testanimated/Android.mk35
-rw-r--r--graphics/drawable/testanimated/AndroidManifest.xml31
-rw-r--r--graphics/drawable/testanimated/res/anim/alpha_animation_progress_bar.xml24
-rw-r--r--graphics/drawable/testanimated/res/anim/animation_grouping_1_01.xml22
-rw-r--r--graphics/drawable/testanimated/res/anim/trim_path_animation_progress_bar.xml45
-rw-r--r--graphics/drawable/testanimated/res/drawable/animation_vector_drawable_grouping_1.xml27
-rw-r--r--graphics/drawable/testanimated/res/drawable/animation_vector_progress_bar.xml26
-rwxr-xr-xgraphics/drawable/testanimated/res/drawable/app_sample_code.pngbin0 -> 3608 bytes
-rw-r--r--graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml53
-rw-r--r--graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml50
-rw-r--r--graphics/drawable/testanimated/res/values/strings.xml28
-rw-r--r--graphics/drawable/testanimated/src/android/support/test/vectordrawable/TestAVDActivity.java98
-rw-r--r--graphics/drawable/teststatic/Android.mk38
-rw-r--r--graphics/drawable/teststatic/AndroidManifest.xml32
-rwxr-xr-xgraphics/drawable/teststatic/res/drawable/app_sample_code.pngbin0 -> 3608 bytes
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable01.xml34
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable02.xml37
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable03.xml72
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable04.xml58
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable05.xml44
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable06.xml49
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable07.xml30
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable08.xml30
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable09.xml33
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable10.xml43
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable11.xml36
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable12.xml98
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable13.xml38
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable14.xml39
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable15.xml35
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable16.xml48
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable17.xml30
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable18.xml32
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable19.xml34
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable20.xml35
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable21.xml48
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable22.xml69
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable23.xml83
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable24.xml83
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable25.xml83
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable26.xml46
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable27.xml46
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable28.xml47
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable29.xml29
-rw-r--r--graphics/drawable/teststatic/res/drawable/vector_drawable30.xml29
-rw-r--r--graphics/drawable/teststatic/res/raw/vector_drawable01.xml32
-rw-r--r--graphics/drawable/teststatic/res/values/strings.xml28
-rw-r--r--graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java128
57 files changed, 5061 insertions, 0 deletions
diff --git a/graphics/Android.mk b/graphics/Android.mk
new file mode 100644
index 0000000000..365b3b1b9f
--- /dev/null
+++ b/graphics/Android.mk
@@ -0,0 +1,16 @@
+# Copyright (C) 2015 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 $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/graphics/drawable/Android.mk b/graphics/drawable/Android.mk
new file mode 100644
index 0000000000..63e93b7d01
--- /dev/null
+++ b/graphics/drawable/Android.mk
@@ -0,0 +1,41 @@
+# Copyright (C) 2015 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)
+
+#static vector drawable library
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v7-vectordrawable
+LOCAL_SDK_VERSION := 7
+LOCAL_SRC_FILES := $(call all-java-files-under, static)
+
+LOCAL_JAVA_LIBRARIES := android-support-v4
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+#Animated vector drawable library
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v11-animatedvectordrawable
+LOCAL_SDK_VERSION := 11
+LOCAL_SRC_FILES := $(call all-java-files-under, animated)
+
+LOCAL_JAVA_LIBRARIES := android-support-v4
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v7-vectordrawable
+
+include $(BUILD_STATIC_JAVA_LIBRARY) \ No newline at end of file
diff --git a/graphics/drawable/AndroidManifest.xml b/graphics/drawable/AndroidManifest.xml
new file mode 100644
index 0000000000..83124c76cf
--- /dev/null
+++ b/graphics/drawable/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.support.graphics.drawable">
+ <application />
+</manifest>
diff --git a/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java b/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
new file mode 100644
index 0000000000..78ef62d1d6
--- /dev/null
+++ b/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) 2015 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.support.graphics.drawable;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.DrawableRes;
+import android.support.v4.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * This class uses {@link android.animation.ObjectAnimator} and
+ * {@link android.animation.AnimatorSet} to animate the properties of a
+ * {@link android.graphics.drawable.VectorDrawableCompat} to create an animated drawable.
+ * <p>
+ * AnimatedVectorDrawableCompat are normally defined as 3 separate XML files.
+ * </p>
+ * <p>
+ * First is the XML file for {@link android.graphics.drawable.VectorDrawableCompat}. Note that we
+ * allow the animation to happen on the group's attributes and path's attributes, which requires they
+ * are uniquely named in this XML file. Groups and paths without animations do not need names.
+ * </p>
+ * <li>Here is a simple VectorDrawable in this vectordrawable.xml file.
+ * <pre>
+ * &lt;vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+ * android:height=&quot;64dp&quot;
+ * android:width=&quot;64dp&quot;
+ * android:viewportHeight=&quot;600&quot;
+ * android:viewportWidth=&quot;600&quot; &gt;
+ * &lt;group
+ * android:name=&quot;rotationGroup&quot;
+ * android:pivotX=&quot;300.0&quot;
+ * android:pivotY=&quot;300.0&quot;
+ * android:rotation=&quot;45.0&quot; &gt;
+ * &lt;path
+ * android:name=&quot;v&quot;
+ * android:fillColor=&quot;#000000&quot;
+ * android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
+ * &lt;/group&gt;
+ * &lt;/vector&gt;
+ * </pre></li>
+ * <p>
+ * Second is the AnimatedVectorDrawableCompat's XML file, which defines the target
+ * VectorDrawableCompat, the target paths and groups to animate, the properties of the path and
+ * group to animate and the animations defined as the ObjectAnimators or AnimatorSets.
+ * </p>
+ * <li>Here is a simple AnimatedVectorDrawable defined in this avd.xml file.
+ * Note how we use the names to refer to the groups and paths in the vectordrawable.xml.
+ * <pre>
+ * &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+ * android:drawable=&quot;@drawable/vectordrawable&quot; &gt;
+ * &lt;target
+ * android:name=&quot;rotationGroup&quot;
+ * android:animation=&quot;@anim/rotation&quot; /&gt;
+ * &lt;target
+ * android:name=&quot;v&quot;
+ * android:animation=&quot;@anim/path_morph&quot; /&gt;
+ * &lt;/animated-vector&gt;
+ * </pre></li>
+ * <p>
+ * Last is the Animator XML file, which is the same as a normal ObjectAnimator or AnimatorSet. To
+ * complete this example, here are the 2 animator files used in avd.xml: rotation.xml and
+ * path_morph.xml.
+ * </p>
+ * <li>Here is the rotation.xml, which will rotate the target group for 360 degrees.
+ * <pre>
+ * &lt;objectAnimator
+ * android:duration=&quot;6000&quot;
+ * android:propertyName=&quot;rotation&quot;
+ * android:valueFrom=&quot;0&quot;
+ * android:valueTo=&quot;360&quot; /&gt;
+ * </pre></li>
+ * <li>Here is the path_morph.xml, which will morph the path from one shape to
+ * the other. Note that the paths must be compatible for morphing.
+ * In more details, the paths should have exact same length of commands, and
+ * exact same length of parameters for each commands.
+ * Note that the path strings are better stored in strings.xml for reusing.
+ * <pre>
+ * &lt;set xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
+ * &lt;objectAnimator
+ * android:duration=&quot;3000&quot;
+ * android:propertyName=&quot;pathData&quot;
+ * android:valueFrom=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot;
+ * android:valueTo=&quot;M300,70 l 0,-70 70,0 0,140 -70,0 z&quot;
+ * android:valueType=&quot;pathType&quot;/&gt;
+ * &lt;/set&gt;
+ * </pre></li>
+ *
+ * @attr ref android.R.styleable#AnimatedVectorDrawableCompat_drawable
+ * @attr ref android.R.styleable#AnimatedVectorDrawableCompatTarget_name
+ * @attr ref android.R.styleable#AnimatedVectorDrawableCompatTarget_animation
+ */
+public class AnimatedVectorDrawableCompat extends Drawable implements Animatable {
+ private static final String LOGTAG = "AnimatedVectorDrawableCompat";
+
+ private static final String ANIMATED_VECTOR = "animated-vector";
+ private static final String TARGET = "target";
+
+ private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
+
+ private AnimatedVectorDrawableCompatState mAnimatedVectorState;
+
+ private boolean mMutated;
+
+ private Context mContext;
+
+ // Currently the only useful ctor.
+ public AnimatedVectorDrawableCompat(Context context) {
+ this(context, null, null);
+ }
+
+ private AnimatedVectorDrawableCompat(Context context, AnimatedVectorDrawableCompatState state,
+ Resources res) {
+ mContext = context;
+ if (state != null) {
+ mAnimatedVectorState = state;
+ } else {
+ mAnimatedVectorState = new AnimatedVectorDrawableCompatState(context, state, mCallback,
+ res);
+ }
+ }
+
+ @Override
+ public Drawable mutate() {
+ if (!mMutated && super.mutate() == this) {
+ mAnimatedVectorState =
+ new AnimatedVectorDrawableCompatState(null, mAnimatedVectorState, mCallback,
+ null);
+ mMutated = true;
+ }
+ return this;
+ }
+
+
+ /**
+ * Create a AnimatedVectorDrawableCompat object.
+ *
+ * @param context the context for creating the animators.
+ * @param resId the resource ID for AnimatedVectorDrawableCompat object.
+ * @return a new AnimatedVectorDrawableCompat or null if parsing error is found.
+ */
+ @Nullable
+ public static AnimatedVectorDrawableCompat create(@NonNull Context context,
+ @DrawableRes int resId) {
+ Resources resources = context.getResources();
+ try {
+ final XmlPullParser parser = resources.getXml(resId);
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Empty loop
+ }
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ final AnimatedVectorDrawableCompat drawable = new AnimatedVectorDrawableCompat(context);
+ drawable.inflate(resources, parser, attrs, context.getTheme());
+
+ return drawable;
+ } catch (XmlPullParserException e) {
+ Log.e(LOGTAG, "parser error", e);
+ } catch (IOException e) {
+ Log.e(LOGTAG, "parser error", e);
+ }
+ return null;
+ }
+
+ @Override
+ public ConstantState getConstantState() {
+ mAnimatedVectorState.mChangingConfigurations = getChangingConfigurations();
+ return mAnimatedVectorState;
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return super.getChangingConfigurations() | mAnimatedVectorState.mChangingConfigurations;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ mAnimatedVectorState.mVectorDrawable.draw(canvas);
+ if (isStarted()) {
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ mAnimatedVectorState.mVectorDrawable.setBounds(bounds);
+ }
+
+ @Override
+ protected boolean onStateChange(int[] state) {
+ return mAnimatedVectorState.mVectorDrawable.setState(state);
+ }
+
+ @Override
+ protected boolean onLevelChange(int level) {
+ return mAnimatedVectorState.mVectorDrawable.setLevel(level);
+ }
+
+ // @Override
+ public int getAlpha() {
+ return mAnimatedVectorState.mVectorDrawable.getAlpha();
+ }
+
+ // @Override
+ public void setAlpha(int alpha) {
+ mAnimatedVectorState.mVectorDrawable.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ mAnimatedVectorState.mVectorDrawable.setColorFilter(colorFilter);
+ }
+
+ public void setTintList(ColorStateList tint) {
+ mAnimatedVectorState.mVectorDrawable.setTintList(tint);
+ }
+
+ public void setTintMode(Mode tintMode) {
+ mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode);
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ mAnimatedVectorState.mVectorDrawable.setVisible(visible, restart);
+ return super.setVisible(visible, restart);
+ }
+
+ @Override
+ public boolean isStateful() {
+ return mAnimatedVectorState.mVectorDrawable.isStateful();
+ }
+
+ @Override
+ public int getOpacity() {
+ return mAnimatedVectorState.mVectorDrawable.getOpacity();
+ }
+
+ public int getIntrinsicWidth() {
+ return mAnimatedVectorState.mVectorDrawable.getIntrinsicWidth();
+ }
+
+ public int getIntrinsicHeight() {
+ return mAnimatedVectorState.mVectorDrawable.getIntrinsicHeight();
+ }
+
+ /**
+ * Obtains styled attributes from the theme, if available, or unstyled
+ * resources if the theme is null.
+ */
+ static TypedArray obtainAttributes(
+ Resources res, Theme theme, AttributeSet set, int[] attrs) {
+ if (theme == null) {
+ return res.obtainAttributes(set, attrs);
+ }
+ return theme.obtainStyledAttributes(set, attrs, 0, 0);
+ }
+
+ public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
+ throws XmlPullParserException, IOException {
+ int eventType = parser.getEventType();
+ float pathErrorScale = 1;
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ final String tagName = parser.getName();
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.v(LOGTAG, "tagName is " + tagName);
+ }
+ if (ANIMATED_VECTOR.equals(tagName)) {
+ final TypedArray a =
+ obtainAttributes(res, theme, attrs, R.styleable.AnimatedVectorDrawable);
+
+ int drawableRes = a.getResourceId(R.styleable.AnimatedVectorDrawable_drawable,
+ 0);
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.v(LOGTAG, "drawableRes is " + drawableRes);
+ }
+ if (drawableRes != 0) {
+ VectorDrawableCompat vectorDrawable = VectorDrawableCompat.create(res,
+ drawableRes, theme);
+ vectorDrawable.setAllowCaching(false);
+ vectorDrawable.setCallback(mCallback);
+ pathErrorScale = vectorDrawable.getPixelSize();
+ if (mAnimatedVectorState.mVectorDrawable != null) {
+ mAnimatedVectorState.mVectorDrawable.setCallback(null);
+ }
+ mAnimatedVectorState.mVectorDrawable = vectorDrawable;
+ }
+ a.recycle();
+ } else if (TARGET.equals(tagName)) {
+ final TypedArray a =
+ res.obtainAttributes(attrs, R.styleable.AnimatedVectorDrawableTarget);
+ final String target = a.getString(
+ R.styleable.AnimatedVectorDrawableTarget_name);
+
+ int id = a.getResourceId(R.styleable.AnimatedVectorDrawableTarget_animation, 0);
+ if (id != 0) {
+ Animator objectAnimator = AnimatorInflater.loadAnimator(mContext, id);
+ setupAnimatorsForTarget(target, objectAnimator);
+ }
+ a.recycle();
+ }
+ }
+
+ eventType = parser.next();
+ }
+ }
+
+ @Override
+ public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs)
+ throws XmlPullParserException, IOException {
+ inflate(res, parser, attrs, null);
+ }
+
+ public boolean canApplyTheme() {
+ return false;
+ }
+
+ private static class AnimatedVectorDrawableCompatState extends ConstantState {
+ int mChangingConfigurations;
+ VectorDrawableCompat mVectorDrawable;
+ ArrayList<Animator> mAnimators;
+ ArrayMap<Animator, String> mTargetNameMap;
+ Context mContext;
+
+ public AnimatedVectorDrawableCompatState(Context context,
+ AnimatedVectorDrawableCompatState copy, Callback owner, Resources res) {
+ if (copy != null) {
+ mChangingConfigurations = copy.mChangingConfigurations;
+ if (copy.mVectorDrawable != null) {
+ final ConstantState cs = copy.mVectorDrawable.getConstantState();
+ if (res != null) {
+ mVectorDrawable = (VectorDrawableCompat) cs.newDrawable(res);
+ } else {
+ mVectorDrawable = (VectorDrawableCompat) cs.newDrawable();
+ }
+ mVectorDrawable = (VectorDrawableCompat) mVectorDrawable.mutate();
+ mVectorDrawable.setCallback(owner);
+ mVectorDrawable.setBounds(copy.mVectorDrawable.getBounds());
+ mVectorDrawable.setAllowCaching(false);
+ }
+ if (copy.mAnimators != null) {
+ final int numAnimators = copy.mAnimators.size();
+ mAnimators = new ArrayList<Animator>(numAnimators);
+ mTargetNameMap = new ArrayMap<Animator, String>(numAnimators);
+ for (int i = 0; i < numAnimators; ++i) {
+ Animator anim = copy.mAnimators.get(i);
+ Animator animClone = anim.clone();
+ String targetName = copy.mTargetNameMap.get(anim);
+ Object targetObject = mVectorDrawable.getTargetByName(targetName);
+ animClone.setTarget(targetObject);
+ mAnimators.add(animClone);
+ mTargetNameMap.put(animClone, targetName);
+ }
+ }
+ }
+
+ if (context != null) {
+ mContext = context;
+ } else {
+ mContext = copy.mContext;
+ }
+
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new AnimatedVectorDrawableCompat(mContext, this, null);
+ }
+
+ @Override
+ public Drawable newDrawable(Resources res) {
+ return new AnimatedVectorDrawableCompat(mContext, this, res);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return mChangingConfigurations;
+ }
+ }
+
+ private void setupAnimatorsForTarget(String name, Animator animator) {
+ Object target = mAnimatedVectorState.mVectorDrawable.getTargetByName(name);
+ animator.setTarget(target);
+ if (mAnimatedVectorState.mAnimators == null) {
+ mAnimatedVectorState.mAnimators = new ArrayList<Animator>();
+ mAnimatedVectorState.mTargetNameMap = new ArrayMap<Animator, String>();
+ }
+ mAnimatedVectorState.mAnimators.add(animator);
+ mAnimatedVectorState.mTargetNameMap.put(animator, name);
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.v(LOGTAG, "add animator for target " + name + " " + animator);
+ }
+ }
+
+ @Override
+ public boolean isRunning() {
+ final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+ final int size = animators.size();
+ for (int i = 0; i < size; i++) {
+ final Animator animator = animators.get(i);
+ if (animator.isRunning()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isStarted() {
+ final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+ if (animators == null) {
+ return false;
+ }
+ final int size = animators.size();
+ for (int i = 0; i < size; i++) {
+ final Animator animator = animators.get(i);
+ if (animator.isRunning()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void start() {
+ // If any one of the animator has not ended, do nothing.
+ if (isStarted()) {
+ return;
+ }
+ // Otherwise, kick off every animator.
+ final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+ final int size = animators.size();
+ for (int i = 0; i < size; i++) {
+ final Animator animator = animators.get(i);
+ animator.start();
+ }
+ invalidateSelf();
+ }
+
+ @Override
+ public void stop() {
+ final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+ final int size = animators.size();
+ for (int i = 0; i < size; i++) {
+ final Animator animator = animators.get(i);
+ animator.end();
+ }
+ }
+
+ private final Callback mCallback = new Callback() {
+ @Override
+ public void invalidateDrawable(Drawable who) {
+ invalidateSelf();
+ }
+
+ @Override
+ public void scheduleDrawable(Drawable who, Runnable what, long when) {
+ scheduleSelf(what, when);
+ }
+
+ @Override
+ public void unscheduleDrawable(Drawable who, Runnable what) {
+ unscheduleSelf(what);
+ }
+ };
+}
diff --git a/graphics/drawable/res/values/attrs.xml b/graphics/drawable/res/values/attrs.xml
new file mode 100644
index 0000000000..b54c9a69c1
--- /dev/null
+++ b/graphics/drawable/res/values/attrs.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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>
+ <!-- If set, specifies the color to apply to the drawable as a tint. By default,
+ no tint is applied. May be a color state list. -->
+ <attr name="tint" format="color" />
+ <!-- When a tint color is set, specifies its Porter-Duff blending mode. The
+ default value is src_in, which treats the drawable as an alpha mask. -->
+ <attr name="tintMode">
+ <!-- The tint is drawn on top of the drawable.
+ [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
+ <enum name="src_over" value="3" />
+ <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
+ color channels are thrown out. [Sa * Da, Sc * Da] -->
+ <enum name="src_in" value="5" />
+ <!-- The tint is drawn above the drawable, but with the drawable’s alpha
+ channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
+ <enum name="src_atop" value="9" />
+ <!-- Multiplies the color and alpha channels of the drawable with those of
+ the tint. [Sa * Da, Sc * Dc] -->
+ <enum name="multiply" value="14" />
+ <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+ <enum name="screen" value="15" />
+ <!-- Combines the tint and drawable color and alpha channels, clamping the
+ result to valid color values. Saturate(S + D) -->
+ <enum name="add" value="16" />
+ </attr>
+ <!-- Animation to use on each child. -->
+ <attr name="animation" format="reference" />
+ <!-- alpha property of the view, as a value between 0 (completely transparent) and 1
+ (completely opaque). -->
+ <attr name="alpha" format="float" />
+ <attr name="pivotX" format="float|fraction" />
+ <attr name="pivotY" format="float|fraction" />
+ <!-- rotation of the view, in degrees. -->
+ <attr name="rotation" format="float" />
+
+ <!-- scale of the view in the x direction. -->
+ <attr name="scaleX" format="float" />
+
+ <!-- scale of the view in the y direction. -->
+ <attr name="scaleY" format="float" />
+ <!-- Makes the TextView be exactly this many pixels tall.
+ You could get the same effect by specifying this number in the
+ layout parameters. -->
+ <attr name="height" format="dimension" />
+ <!-- Makes the TextView be exactly this many pixels wide.
+ You could get the same effect by specifying this number in the
+ layout parameters. -->
+ <attr name="width" format="dimension" />
+ <!-- A unique name for the given item. This must use a Java-style naming
+ convention to ensure the name is unique, for example
+ "com.mycompany.MyName". -->
+ <attr name="name" format="string" />
+
+ <!-- ========================== -->
+ <!-- VectorDrawable class -->
+ <!-- ========================== -->
+ <eat-comment />
+
+ <!-- Drawable used to draw vector paths. -->
+ <declare-styleable name="VectorDrawable">
+ <!-- If set, specifies the color to apply to the drawable as a tint. By default,
+ no tint is applied. May be a color state list. -->
+ <attr name="tint" />
+ <!-- When a tint color is set, specifies its Porter-Duff blending mode. The
+ default value is src_in, which treats the drawable as an alpha mask. -->
+ <attr name="tintMode" />
+ <!-- Indicates if the drawable needs to be mirrored when its layout direction is
+ RTL (right-to-left). -->
+ <attr name="autoMirrored" format="boolean" />
+ <!-- The intrinsic width of the Vector Drawable. -->
+ <attr name="width" />
+ <!-- The intrinsic height of the Vector Drawable. -->
+ <attr name="height" />
+ <!-- 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"/>
+ <!-- The name of this vector drawable -->
+ <attr name="name" />
+ <!-- The opacity of the whole vector drawable, as a value between 0
+ (completely transparent) and 1 (completely opaque). -->
+ <attr name="alpha" />
+ </declare-styleable>
+
+ <!-- Defines the group used in VectorDrawables. -->
+ <declare-styleable name="VectorDrawableGroup">
+ <!-- The name of this group -->
+ <attr name="name" />
+ <!-- The amount to rotate the group -->
+ <attr name="rotation" />
+ <!-- The X coordinate of the center of rotation of a group -->
+ <attr name="pivotX" />
+ <!-- The Y coordinate of the center of rotation of a group -->
+ <attr name="pivotY" />
+ <!-- The amount to translate the group on X coordinate -->
+ <attr name="translateX" format="float"/>
+ <!-- The amount to translate the group on Y coordinate -->
+ <attr name="translateY" format="float"/>
+ <!-- The amount to scale the group on X coordinate -->
+ <attr name="scaleX" />
+ <!-- The amount to scale the group on X coordinate -->
+ <attr name="scaleY" />
+ </declare-styleable>
+
+ <!-- Defines the path used in VectorDrawables. -->
+ <declare-styleable name="VectorDrawablePath">
+ <!-- The name of this path -->
+ <attr name="name" />
+ <!-- The width a path stroke -->
+ <attr name="strokeWidth" format="float" />
+ <!-- The color to stroke the path if not defined implies no stroke-->
+ <attr name="strokeColor" format="color" />
+ <!-- The opacity of a path stroke, as a value between 0 (completely transparent)
+ and 1 (completely opaque) -->
+ <attr name="strokeAlpha" format="float" />
+ <!-- The color to fill the path if not defined implies no fill-->
+ <attr name="fillColor" format="color" />
+ <!-- The alpha of the path fill, as a value between 0 (completely transparent)
+ and 1 (completely opaque)-->
+ <attr name="fillAlpha" 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" />
+ <!-- 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>
+ <!-- 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>
+ <!-- The Miter limit for a stroked path -->
+ <attr name="strokeMiterLimit" format="float"/>
+ </declare-styleable>
+
+ <!-- Defines the clip path used in VectorDrawables. -->
+ <declare-styleable name="VectorDrawableClipPath">
+ <!-- The Name of this path -->
+ <attr name="name" />
+ <!-- The specification of the operations that define the path -->
+ <attr name="pathData"/>
+ </declare-styleable>
+
+ <!-- ========================== -->
+ <!-- AnimatedVectorDrawable class -->
+ <!-- ========================== -->
+ <eat-comment />
+
+ <!-- Define the AnimatedVectorDrawable. -->
+ <declare-styleable name="AnimatedVectorDrawable">
+ <!-- The static vector drawable. -->
+ <attr name="drawable" format="reference" />
+ </declare-styleable>
+
+ <!-- Defines the target used in the AnimatedVectorDrawable. -->
+ <declare-styleable name="AnimatedVectorDrawableTarget">
+ <!-- The name of the target path, group or vector drawable -->
+ <attr name="name" />
+ <!-- The animation for the target path, group or vector drawable -->
+ <attr name="animation" />
+ </declare-styleable>
+</resources>
diff --git a/graphics/drawable/runavdtest.sh b/graphics/drawable/runavdtest.sh
new file mode 100755
index 0000000000..023ad3e8e9
--- /dev/null
+++ b/graphics/drawable/runavdtest.sh
@@ -0,0 +1,5 @@
+. ../../../../build/envsetup.sh
+mmm -j20 . && mmm -j20 ./testanimated/ && \
+adb install -r $OUT/data/app/AndroidAnimatedVectorDrawableTests/AndroidAnimatedVectorDrawableTests.apk && \
+adb shell am start -n android.support.test.vectordrawable/android.support.test.vectordrawable.TestAVDActivity
+
diff --git a/graphics/drawable/runtest.sh b/graphics/drawable/runtest.sh
new file mode 100755
index 0000000000..6f697801ba
--- /dev/null
+++ b/graphics/drawable/runtest.sh
@@ -0,0 +1,5 @@
+. ../../../../build/envsetup.sh
+mmm -j20 . && mmm -j20 ./teststatic/ && \
+adb install -r $OUT/data/app/AndroidVectorDrawableTests/AndroidVectorDrawableTests.apk && \
+adb shell am start -n android.support.test.vectordrawable/android.support.test.vectordrawable.TestActivity
+
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java b/graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java
new file mode 100644
index 0000000000..a92c3e578d
--- /dev/null
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java
@@ -0,0 +1,718 @@
+/*
+ * Copyright (C) 2015 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.support.graphics.drawable;
+
+import android.graphics.Path;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+// This class is a duplicate from the PathParser.java of frameworks/base, with slight
+// update on incompatible API like copyOfRange().
+class PathParser {
+ private static final String LOGTAG = "PathParser";
+
+ // Copy from Arrays.copyOfRange() which is only available from API level 9.
+ /**
+ * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
+ * end (exclusive). The original order of elements is preserved.
+ * If {@code end} is greater than {@code original.length}, the result is padded
+ * with the value {@code 0.0f}.
+ *
+ * @param original the original array
+ * @param start the start index, inclusive
+ * @param end the end index, exclusive
+ * @return the new array
+ * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
+ * @throws IllegalArgumentException if {@code start > end}
+ * @throws NullPointerException if {@code original == null}
+ */
+ private static float[] copyOfRange(float[] original, int start, int end) {
+ if (start > end) {
+ throw new IllegalArgumentException();
+ }
+ int originalLength = original.length;
+ if (start < 0 || start > originalLength) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ int resultLength = end - start;
+ int copyLength = Math.min(resultLength, originalLength - start);
+ float[] result = new float[resultLength];
+ System.arraycopy(original, start, result, 0, copyLength);
+ return result;
+ }
+
+ /**
+ * @param pathData The string representing a path, the same as "d" string in svg file.
+ * @return the generated Path object.
+ */
+ public static Path createPathFromPathData(String pathData) {
+ Path path = new Path();
+ PathDataNode[] nodes = createNodesFromPathData(pathData);
+ if (nodes != null) {
+ try {
+ PathDataNode.nodesToPath(nodes, path);
+ } catch (RuntimeException e) {
+ throw new RuntimeException("Error in parsing " + pathData, e);
+ }
+ return path;
+ }
+ return null;
+ }
+
+ /**
+ * @param pathData The string representing a path, the same as "d" string in svg file.
+ * @return an array of the PathDataNode.
+ */
+ public static PathDataNode[] createNodesFromPathData(String pathData) {
+ if (pathData == null) {
+ return null;
+ }
+ int start = 0;
+ int end = 1;
+
+ ArrayList<PathDataNode> list = new ArrayList<PathDataNode>();
+ while (end < pathData.length()) {
+ end = nextStart(pathData, end);
+ String s = pathData.substring(start, end).trim();
+ if (s.length() > 0) {
+ float[] val = getFloats(s);
+ addNode(list, s.charAt(0), val);
+ }
+
+ start = end;
+ end++;
+ }
+ if ((end - start) == 1 && start < pathData.length()) {
+ addNode(list, pathData.charAt(start), new float[0]);
+ }
+ return list.toArray(new PathDataNode[list.size()]);
+ }
+
+ /**
+ * @param source The array of PathDataNode to be duplicated.
+ * @return a deep copy of the <code>source</code>.
+ */
+ public static PathDataNode[] deepCopyNodes(PathDataNode[] source) {
+ if (source == null) {
+ return null;
+ }
+ PathDataNode[] copy = new PathParser.PathDataNode[source.length];
+ for (int i = 0; i < source.length; i ++) {
+ copy[i] = new PathDataNode(source[i]);
+ }
+ return copy;
+ }
+
+ /**
+ * @param nodesFrom The source path represented in an array of PathDataNode
+ * @param nodesTo The target path represented in an array of PathDataNode
+ * @return whether the <code>nodesFrom</code> can morph into <code>nodesTo</code>
+ */
+ public static boolean canMorph(PathDataNode[] nodesFrom, PathDataNode[] nodesTo) {
+ if (nodesFrom == null || nodesTo == null) {
+ return false;
+ }
+
+ if (nodesFrom.length != nodesTo.length) {
+ return false;
+ }
+
+ for (int i = 0; i < nodesFrom.length; i ++) {
+ if (nodesFrom[i].mType != nodesTo[i].mType
+ || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Update the target's data to match the source.
+ * Before calling this, make sure canMorph(target, source) is true.
+ *
+ * @param target The target path represented in an array of PathDataNode
+ * @param source The source path represented in an array of PathDataNode
+ */
+ public static void updateNodes(PathDataNode[] target, PathDataNode[] source) {
+ for (int i = 0; i < source.length; i ++) {
+ target[i].mType = source[i].mType;
+ for (int j = 0; j < source[i].mParams.length; j ++) {
+ target[i].mParams[j] = source[i].mParams[j];
+ }
+ }
+ }
+
+ private static int nextStart(String s, int end) {
+ char c;
+
+ while (end < s.length()) {
+ c = s.charAt(end);
+ // Note that 'e' or 'E' are not valid path commands, but could be
+ // used for floating point numbers' scientific notation.
+ // Therefore, when searching for next command, we should ignore 'e'
+ // and 'E'.
+ if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0))
+ && c != 'e' && c != 'E') {
+ return end;
+ }
+ end++;
+ }
+ return end;
+ }
+
+ private static void addNode(ArrayList<PathDataNode> list, char cmd, float[] val) {
+ list.add(new PathDataNode(cmd, val));
+ }
+
+ private static class ExtractFloatResult {
+ // We need to return the position of the next separator and whether the
+ // next float starts with a '-' or a '.'.
+ int mEndPosition;
+ boolean mEndWithNegOrDot;
+ }
+
+ /**
+ * 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[] results = new float[s.length()];
+ int count = 0;
+ int startPosition = 1;
+ int endPosition = 0;
+
+ ExtractFloatResult result = new ExtractFloatResult();
+ int totalLength = s.length();
+
+ // The startPosition should always be the first character of the
+ // current number, and endPosition is the character after the current
+ // number.
+ while (startPosition < totalLength) {
+ extract(s, startPosition, result);
+ endPosition = result.mEndPosition;
+
+ if (startPosition < endPosition) {
+ results[count++] = Float.parseFloat(
+ s.substring(startPosition, endPosition));
+ }
+
+ if (result.mEndWithNegOrDot) {
+ // Keep the '-' or '.' sign with next number.
+ startPosition = endPosition;
+ } else {
+ startPosition = endPosition + 1;
+ }
+ }
+ return copyOfRange(results, 0, count);
+ } catch (NumberFormatException e) {
+ throw new RuntimeException("error in parsing \"" + s + "\"", e);
+ }
+ }
+
+ /**
+ * Calculate the position of the next comma or space or negative sign
+ * @param s the string to search
+ * @param start the position to start searching
+ * @param result the result of the extraction, including the position of the
+ * the starting position of next number, whether it is ending with a '-'.
+ */
+ private static void extract(String s, int start, ExtractFloatResult result) {
+ // Now looking for ' ', ',', '.' or '-' from the start.
+ int currentIndex = start;
+ boolean foundSeparator = false;
+ result.mEndWithNegOrDot = false;
+ boolean secondDot = false;
+ boolean isExponential = false;
+ for (; currentIndex < s.length(); currentIndex++) {
+ boolean isPrevExponential = isExponential;
+ isExponential = false;
+ char currentChar = s.charAt(currentIndex);
+ switch (currentChar) {
+ case ' ':
+ case ',':
+ foundSeparator = true;
+ break;
+ case '-':
+ // The negative sign following a 'e' or 'E' is not a separator.
+ if (currentIndex != start && !isPrevExponential) {
+ foundSeparator = true;
+ result.mEndWithNegOrDot = true;
+ }
+ break;
+ case '.':
+ if (!secondDot) {
+ secondDot = true;
+ } else {
+ // This is the second dot, and it is considered as a separator.
+ foundSeparator = true;
+ result.mEndWithNegOrDot = true;
+ }
+ break;
+ case 'e':
+ case 'E':
+ isExponential = true;
+ break;
+ }
+ if (foundSeparator) {
+ break;
+ }
+ }
+ // When there is nothing found, then we put the end position to the end
+ // of the string.
+ result.mEndPosition = currentIndex;
+ }
+
+ /**
+ * Each PathDataNode represents one command in the "d" attribute of the svg
+ * file.
+ * An array of PathDataNode can represent the whole "d" attribute.
+ */
+ public static class PathDataNode {
+ private char mType;
+ private float[] mParams;
+
+ private PathDataNode(char type, float[] params) {
+ mType = type;
+ mParams = params;
+ }
+
+ private PathDataNode(PathDataNode n) {
+ mType = n.mType;
+ mParams = copyOfRange(n.mParams, 0, n.mParams.length);
+ }
+
+ /**
+ * Convert an array of PathDataNode to Path.
+ *
+ * @param node The source array of PathDataNode.
+ * @param path The target Path object.
+ */
+ public static void nodesToPath(PathDataNode[] node, Path path) {
+ float[] current = new float[6];
+ char previousCommand = 'm';
+ for (int i = 0; i < node.length; i++) {
+ addCommand(path, current, previousCommand, node[i].mType, node[i].mParams);
+ previousCommand = node[i].mType;
+ }
+ }
+
+ /**
+ * The current PathDataNode will be interpolated between the
+ * <code>nodeFrom</code> and <code>nodeTo</code> according to the
+ * <code>fraction</code>.
+ *
+ * @param nodeFrom The start value as a PathDataNode.
+ * @param nodeTo The end value as a PathDataNode
+ * @param fraction The fraction to interpolate.
+ */
+ public void interpolatePathDataNode(PathDataNode nodeFrom,
+ PathDataNode nodeTo, float fraction) {
+ for (int i = 0; i < nodeFrom.mParams.length; i++) {
+ mParams[i] = nodeFrom.mParams[i] * (1 - fraction)
+ + nodeTo.mParams[i] * fraction;
+ }
+ }
+
+ private static void addCommand(Path path, float[] current,
+ char previousCmd, char cmd, float[] val) {
+
+ int incr = 2;
+ float currentX = current[0];
+ float currentY = current[1];
+ float ctrlPointX = current[2];
+ float ctrlPointY = current[3];
+ float currentSegmentStartX = current[4];
+ float currentSegmentStartY = current[5];
+ float reflectiveCtrlPointX;
+ float reflectiveCtrlPointY;
+
+ switch (cmd) {
+ case 'z':
+ case 'Z':
+ path.close();
+ // Path is closed here, but we need to move the pen to the
+ // closed position. So we cache the segment's starting position,
+ // and restore it here.
+ currentX = currentSegmentStartX;
+ currentY = currentSegmentStartY;
+ ctrlPointX = currentSegmentStartX;
+ ctrlPointY = currentSegmentStartY;
+ path.moveTo(currentX, currentY);
+ break;
+ 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) {
+ 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];
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
+ 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];
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
+ 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 '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)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ 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)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ break;
+ case 'q': // Draws a quadratic Bézier (relative)
+ path.rQuadTo(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 'Q': // Draws a quadratic Bézier
+ path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ break;
+ case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = currentX + reflectiveCtrlPointX;
+ ctrlPointY = currentY + reflectiveCtrlPointY;
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+ break;
+ case 'T': // Draws a quadratic Bézier curve (reflective control point)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = reflectiveCtrlPointX;
+ ctrlPointY = reflectiveCtrlPointY;
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+ 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;
+ }
+ previousCmd = cmd;
+ }
+ current[0] = currentX;
+ current[1] = currentY;
+ current[2] = ctrlPointX;
+ current[3] = ctrlPointY;
+ current[4] = currentSegmentStartX;
+ current[5] = currentSegmentStartY;
+ }
+
+ 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/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
new file mode 100644
index 0000000000..d33c20496c
--- /dev/null
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
@@ -0,0 +1,1470 @@
+/*
+ * Copyright (C) 2015 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.support.graphics.drawable;
+
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+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.PorterDuff;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.DrawableRes;
+import android.support.v4.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Stack;
+
+/**
+ * This lets you create a drawable based on an XML vector graphic. It can be defined in an XML file
+ * with the <code>&lt;vector></code> element.
+ * <p/>
+ * The vector drawable has the following elements:
+ * <p/>
+ * <dt><code>&lt;vector></code></dt>
+ * <dl>
+ * <dd>Used to define a vector drawable
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of this vector drawable.</dd>
+ * <dt><code>android:width</code></dt>
+ * <dd>Used to define the intrinsic width of the drawable. This support all the dimension units,
+ * normally specified with dp.</dd>
+ * <dt><code>android:height</code></dt>
+ * <dd>Used to define the intrinsic height the drawable. This support all the dimension units,
+ * normally specified with dp.</dd>
+ * <dt><code>android:viewportWidth</code></dt>
+ * <dd>Used to define the width of the viewport space. Viewport is basically the virtual canvas
+ * where the paths are drawn on.</dd>
+ * <dt><code>android:viewportHeight</code></dt>
+ * <dd>Used to define the height of the viewport space. Viewport is basically the virtual canvas
+ * where the paths are drawn on.</dd>
+ * <dt><code>android:tint</code></dt>
+ * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
+ * <dt><code>android:tintMode</code></dt>
+ * <dd>The Porter-Duff blending mode for the tint color. The default value is src_in.</dd>
+ * <dt><code>android:autoMirrored</code></dt>
+ * <dd>Indicates if the drawable needs to be mirrored when its layout direction is RTL
+ * (right-to-left).</dd>
+ * <dt><code>android:alpha</code></dt>
+ * <dd>The opacity of this drawable.</dd>
+ * </dl>
+ * </dd>
+ * </dl>
+ * <dl>
+ * <dt><code>&lt;group></code></dt>
+ * <dd>Defines a group of paths or subgroups, plus transformation information. The transformations
+ * are defined in the same coordinates as the viewport. And the transformations are applied in the
+ * order of scale, rotate then translate.
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of the group.</dd>
+ * <dt><code>android:rotation</code></dt>
+ * <dd>The degrees of rotation of the group.</dd>
+ * <dt><code>android:pivotX</code></dt>
+ * <dd>The X coordinate of the pivot for the scale and rotation of the group. This is defined in the
+ * viewport space.</dd>
+ * <dt><code>android:pivotY</code></dt>
+ * <dd>The Y coordinate of the pivot for the scale and rotation of the group. This is defined in the
+ * viewport space.</dd>
+ * <dt><code>android:scaleX</code></dt>
+ * <dd>The amount of scale on the X Coordinate.</dd>
+ * <dt><code>android:scaleY</code></dt>
+ * <dd>The amount of scale on the Y coordinate.</dd>
+ * <dt><code>android:translateX</code></dt>
+ * <dd>The amount of translation on the X coordinate. This is defined in the viewport space.</dd>
+ * <dt><code>android:translateY</code></dt>
+ * <dd>The amount of translation on the Y coordinate. This is defined in the viewport space.</dd>
+ * </dl>
+ * </dd>
+ * </dl>
+ * <dl>
+ * <dt><code>&lt;path></code></dt>
+ * <dd>Defines paths to be drawn.
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of the path.</dd>
+ * <dt><code>android:pathData</code></dt>
+ * <dd>Defines path data using exactly same format as "d" attribute in the SVG's path
+ * data. This is defined in the viewport space.</dd>
+ * <dt><code>android:fillColor</code></dt>
+ * <dd>Defines the color to fill the path (none if not present).</dd>
+ * <dt><code>android:strokeColor</code></dt>
+ * <dd>Defines the color to draw the path outline (none if not present).</dd>
+ * <dt><code>android:strokeWidth</code></dt>
+ * <dd>The width a path stroke.</dd>
+ * <dt><code>android:strokeAlpha</code></dt>
+ * <dd>The opacity of a path stroke.</dd>
+ * <dt><code>android:fillAlpha</code></dt>
+ * <dd>The opacity to fill the path with.</dd>
+ * <dt><code>android:trimPathStart</code></dt>
+ * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd>
+ * <dt><code>android:trimPathEnd</code></dt>
+ * <dd>The fraction of the path to trim from the end, in the range from 0 to 1.</dd>
+ * <dt><code>android:trimPathOffset</code></dt>
+ * <dd>Shift trim region (allows showed region to include the start and end), in the range from 0 to
+ * 1.</dd>
+ * <dt><code>android:strokeLineCap</code></dt>
+ * <dd>Sets the linecap for a stroked path: butt, round, square.</dd>
+ * <dt><code>android:strokeLineJoin</code></dt>
+ * <dd>Sets the lineJoin for a stroked path: miter,round,bevel.</dd>
+ * <dt><code>android:strokeMiterLimit</code></dt>
+ * <dd>Sets the Miter limit for a stroked path.</dd>
+ * </dl>
+ * </dd>
+ * </dl>
+ * <dl>
+ * <dt><code>&lt;clip-path></code></dt>
+ * <dd>Defines path to be the current clip.
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of the clip path.</dd>
+ * <dt><code>android:pathData</code></dt>
+ * <dd>Defines clip path data using the same format as "d" attribute in the SVG's
+ * path data.</dd>
+ * </dl>
+ * </dd>
+ * </dl>
+ * <li>Here is a simple VectorDrawable in this vectordrawable.xml file.
+ * <pre>
+ * &lt;vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+ * android:height=&quot;64dp&quot;
+ * android:width=&quot;64dp&quot;
+ * android:viewportHeight=&quot;600&quot;
+ * android:viewportWidth=&quot;600&quot; &gt;
+ * &lt;group
+ * android:name=&quot;rotationGroup&quot;
+ * android:pivotX=&quot;300.0&quot;
+ * android:pivotY=&quot;300.0&quot;
+ * android:rotation=&quot;45.0&quot; &gt;
+ * &lt;path
+ * android:name=&quot;v&quot;
+ * android:fillColor=&quot;#000000&quot;
+ * android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
+ * &lt;/group&gt;
+ * &lt;/vector&gt;
+ * </pre></li>
+ */
+public class VectorDrawableCompat extends Drawable {
+ static final String LOGTAG = "VectorDrawableCompat";
+
+ static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN;
+
+ private static final String SHAPE_CLIP_PATH = "clip-path";
+ private static final String SHAPE_GROUP = "group";
+ private static final String SHAPE_PATH = "path";
+ 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 boolean DBG_VECTOR_DRAWABLE = true;
+
+ private VectorDrawableState mVectorState;
+
+ private PorterDuffColorFilter mTintFilter;
+ private ColorFilter mColorFilter;
+
+ private boolean mMutated;
+
+ // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise,
+ // caching the bitmap by default is allowed.
+ private boolean mAllowCaching = true;
+
+ private VectorDrawableCompat() {
+ mVectorState = new VectorDrawableState();
+ }
+
+ private VectorDrawableCompat(VectorDrawableState state) {
+ mVectorState = state;
+ mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
+ }
+
+ @Override
+ public Drawable mutate() {
+ if (!mMutated && super.mutate() == this) {
+ mVectorState = new VectorDrawableState(mVectorState);
+ mMutated = true;
+ }
+ return this;
+ }
+
+ Object getTargetByName(String name) {
+ return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
+ }
+
+ @Override
+ public ConstantState getConstantState() {
+ mVectorState.mChangingConfigurations = getChangingConfigurations();
+ return mVectorState;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final Rect bounds = getBounds();
+ if (bounds.width() == 0 || bounds.height() == 0) {
+ // too small to draw
+ return;
+ }
+
+ final int saveCount = canvas.save();
+ final boolean needMirroring = needMirroring();
+
+ canvas.translate(bounds.left, bounds.top);
+ if (needMirroring) {
+ canvas.translate(bounds.width(), 0);
+ canvas.scale(-1.0f, 1.0f);
+ }
+
+ // Color filters always override tint filters.
+ final ColorFilter colorFilter = mColorFilter == null ? mTintFilter : mColorFilter;
+
+ if (!mAllowCaching) {
+ // AnimatedVectorDrawable
+ if (!mVectorState.hasTranslucentRoot()) {
+ mVectorState.mVPathRenderer.draw(
+ canvas, bounds.width(), bounds.height(), colorFilter);
+ } else {
+ mVectorState.createCachedBitmapIfNeeded(bounds);
+ mVectorState.updateCachedBitmap(bounds);
+ mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
+ }
+ } else {
+ // Static Vector Drawable case.
+ mVectorState.createCachedBitmapIfNeeded(bounds);
+ if (!mVectorState.canReuseCache()) {
+ mVectorState.updateCachedBitmap(bounds);
+ mVectorState.updateCacheStates();
+ }
+ mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
+ }
+
+ canvas.restoreToCount(saveCount);
+ }
+
+ public int getAlpha() {
+ return mVectorState.mVPathRenderer.getRootAlpha();
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
+ mVectorState.mVPathRenderer.setRootAlpha(alpha);
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ mColorFilter = colorFilter;
+ invalidateSelf();
+ }
+
+ /**
+ * Ensures the tint filter is consistent with the current tint color and
+ * mode.
+ */
+ PorterDuffColorFilter updateTintFilter(PorterDuffColorFilter tintFilter, ColorStateList tint,
+ PorterDuff.Mode tintMode) {
+ if (tint == null || tintMode == null) {
+ return null;
+ }
+ // setMode, setColor of PorterDuffColorFilter are not public method in SDK v7.
+ // Therefore we create a new one all the time here. Don't expect this is called often.
+ final int color = tint.getColorForState(getState(), Color.TRANSPARENT);
+ return new PorterDuffColorFilter(color, tintMode);
+ }
+
+ public void setTint(int tint) {
+ setTintList(ColorStateList.valueOf(tint));
+ }
+
+ public void setTintList(ColorStateList tint) {
+ final VectorDrawableState state = mVectorState;
+ if (state.mTint != tint) {
+ state.mTint = tint;
+ mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode);
+ invalidateSelf();
+ }
+ }
+
+ public void setTintMode(Mode tintMode) {
+ final VectorDrawableState state = mVectorState;
+ if (state.mTintMode != tintMode) {
+ state.mTintMode = tintMode;
+ mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode);
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ public boolean isStateful() {
+ return super.isStateful() || (mVectorState != null && mVectorState.mTint != null
+ && mVectorState.mTint.isStateful());
+ }
+
+ @Override
+ protected boolean onStateChange(int[] stateSet) {
+ final VectorDrawableState state = mVectorState;
+ if (state.mTint != null && state.mTintMode != null) {
+ // mTintFilter = updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode);
+ invalidateSelf();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return (int) mVectorState.mVPathRenderer.mBaseWidth;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return (int) mVectorState.mVPathRenderer.mBaseHeight;
+ }
+
+ // Don't support re-applying themes. The initial theme loading is working.
+ public boolean canApplyTheme() {
+ return false;
+ }
+
+ /**
+ * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension. This
+ * is used to calculate the path animation accuracy.
+ *
+ * @hide
+ */
+ public float getPixelSize() {
+ if (mVectorState == null && mVectorState.mVPathRenderer == null ||
+ mVectorState.mVPathRenderer.mBaseWidth == 0 ||
+ mVectorState.mVPathRenderer.mBaseHeight == 0 ||
+ mVectorState.mVPathRenderer.mViewportHeight == 0 ||
+ mVectorState.mVPathRenderer.mViewportWidth == 0) {
+ return 1; // fall back to 1:1 pixel mapping.
+ }
+ float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth;
+ float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight;
+ float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth;
+ float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight;
+ float scaleX = viewportWidth / intrinsicWidth;
+ float scaleY = viewportHeight / intrinsicHeight;
+ return Math.min(scaleX, scaleY);
+ }
+
+ /**
+ * Create a VectorDrawableCompat object.
+ *
+ * @param res the resources.
+ * @param resId the resource ID for VectorDrawableCompat object.
+ * @param theme the theme of this vector drawable, it can be null.
+ * @return a new VectorDrawableCompat or null if parsing error is found.
+ */
+ @Nullable
+ public static VectorDrawableCompat create(@NonNull Resources res, @DrawableRes int resId,
+ @Nullable Theme theme) {
+ try {
+ final XmlPullParser parser = res.getXml(resId);
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG &&
+ type != XmlPullParser.END_DOCUMENT) {
+ // Empty loop
+ }
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ final VectorDrawableCompat drawable = new VectorDrawableCompat();
+ drawable.inflate(res, parser, attrs, theme);
+
+ return drawable;
+ } catch (XmlPullParserException e) {
+ Log.e(LOGTAG, "parser error", e);
+ } catch (IOException e) {
+ Log.e(LOGTAG, "parser error", e);
+ }
+ return null;
+ }
+
+ private static int applyAlpha(int color, float alpha) {
+ int alphaBytes = Color.alpha(color);
+ color &= 0x00FFFFFF;
+ color |= ((int) (alphaBytes * alpha)) << 24;
+ return color;
+ }
+
+ /**
+ * Obtains styled attributes from the theme, if available, or unstyled
+ * resources if the theme is null.
+ */
+ static TypedArray obtainAttributes(
+ Resources res, Theme theme, AttributeSet set, int[] attrs) {
+ if (theme == null) {
+ return res.obtainAttributes(set, attrs);
+ }
+ return theme.obtainStyledAttributes(set, attrs, 0, 0);
+ }
+
+
+ @Override
+ public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs)
+ throws XmlPullParserException, IOException {
+ inflate(res, parser, attrs, null);
+ }
+
+ public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
+ throws XmlPullParserException, IOException {
+ final VectorDrawableState state = mVectorState;
+ final VPathRenderer pathRenderer = new VPathRenderer();
+ state.mVPathRenderer = pathRenderer;
+
+ final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawable);
+ updateStateFromTypedArray(a);
+ a.recycle();
+ state.mChangingConfigurations = getChangingConfigurations();
+ state.mCacheDirty = true;
+ inflateInternal(res, parser, attrs, theme);
+
+ mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
+ }
+
+ private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
+ final VectorDrawableState state = mVectorState;
+ final VPathRenderer pathRenderer = state.mVPathRenderer;
+
+ // Account for any configuration changes.
+ // state.mChangingConfigurations |= Utils.getChangingConfigurations(a);
+
+ final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1);
+ // if (tintMode != -1) {
+ // state.mTintMode = Utils.parseTintMode(tintMode, DEFAULT_TINT_MODE);
+ // }
+
+ final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint);
+ if (tint != null) {
+ state.mTint = tint;
+ }
+
+ state.mAutoMirrored = a.getBoolean(
+ R.styleable.VectorDrawable_autoMirrored, state.mAutoMirrored);
+
+ pathRenderer.mViewportWidth = a.getFloat(
+ R.styleable.VectorDrawable_viewportWidth, pathRenderer.mViewportWidth);
+ pathRenderer.mViewportHeight = a.getFloat(
+ R.styleable.VectorDrawable_viewportHeight, pathRenderer.mViewportHeight);
+
+ if (pathRenderer.mViewportWidth <= 0) {
+ throw new XmlPullParserException(a.getPositionDescription() +
+ "<vector> tag requires viewportWidth > 0");
+ } else if (pathRenderer.mViewportHeight <= 0) {
+ throw new XmlPullParserException(a.getPositionDescription() +
+ "<vector> tag requires viewportHeight > 0");
+ }
+
+ pathRenderer.mBaseWidth = a.getDimension(
+ R.styleable.VectorDrawable_width, pathRenderer.mBaseWidth);
+ pathRenderer.mBaseHeight = a.getDimension(
+ R.styleable.VectorDrawable_height, pathRenderer.mBaseHeight);
+
+ if (pathRenderer.mBaseWidth <= 0) {
+ throw new XmlPullParserException(a.getPositionDescription() +
+ "<vector> tag requires width > 0");
+ } else if (pathRenderer.mBaseHeight <= 0) {
+ throw new XmlPullParserException(a.getPositionDescription() +
+ "<vector> tag requires height > 0");
+ }
+
+ final float alphaInFloat = a.getFloat(R.styleable.VectorDrawable_alpha,
+ pathRenderer.getAlpha());
+ pathRenderer.setAlpha(alphaInFloat);
+
+ final String name = a.getString(R.styleable.VectorDrawable_name);
+ if (name != null) {
+ pathRenderer.mRootName = name;
+ pathRenderer.mVGTargetsMap.put(name, pathRenderer);
+ }
+ }
+
+ private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
+ final VectorDrawableState state = mVectorState;
+ final VPathRenderer pathRenderer = state.mVPathRenderer;
+ boolean noPathTag = true;
+
+ // Use a stack to help to build the group tree.
+ // The top of the stack is always the current group.
+ final Stack<VGroup> groupStack = new Stack<VGroup>();
+ groupStack.push(pathRenderer.mRootGroup);
+
+ int eventType = parser.getEventType();
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ final String tagName = parser.getName();
+ final VGroup currentGroup = groupStack.peek();
+ Log.v(LOGTAG, tagName);
+ if (SHAPE_PATH.equals(tagName)) {
+ final VFullPath path = new VFullPath();
+ path.inflate(res, attrs, theme);
+ currentGroup.mChildren.add(path);
+ if (path.getPathName() != null) {
+ pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
+ }
+ noPathTag = false;
+ state.mChangingConfigurations |= path.mChangingConfigurations;
+ } else if (SHAPE_CLIP_PATH.equals(tagName)) {
+ final VClipPath path = new VClipPath();
+ path.inflate(res, attrs, theme);
+ currentGroup.mChildren.add(path);
+ if (path.getPathName() != null) {
+ pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
+ }
+ state.mChangingConfigurations |= path.mChangingConfigurations;
+ } else if (SHAPE_GROUP.equals(tagName)) {
+ VGroup newChildGroup = new VGroup();
+ newChildGroup.inflate(res, attrs, theme);
+ currentGroup.mChildren.add(newChildGroup);
+ groupStack.push(newChildGroup);
+ if (newChildGroup.getGroupName() != null) {
+ pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
+ newChildGroup);
+ }
+ state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
+ }
+ } else if (eventType == XmlPullParser.END_TAG) {
+ final String tagName = parser.getName();
+ if (SHAPE_GROUP.equals(tagName)) {
+ groupStack.pop();
+ }
+ }
+ eventType = parser.next();
+ }
+
+ // Print the tree out for debug.
+ if (DBG_VECTOR_DRAWABLE) {
+ printGroupTree(pathRenderer.mRootGroup, 0);
+ }
+
+ if (noPathTag) {
+ final StringBuffer tag = new StringBuffer();
+
+ if (tag.length() > 0) {
+ tag.append(" or ");
+ }
+ tag.append(SHAPE_PATH);
+
+ throw new XmlPullParserException("no " + tag + " defined");
+ }
+ }
+
+ private void printGroupTree(VGroup currentGroup, int level) {
+ String indent = "";
+ for (int i = 0; i < level; i++) {
+ indent += " ";
+ }
+ // Print the current node
+ Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
+ + " rotation is " + currentGroup.mRotate);
+ Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
+ // Then print all the children groups
+ for (int i = 0; i < currentGroup.mChildren.size(); i++) {
+ Object child = currentGroup.mChildren.get(i);
+ if (child instanceof VGroup) {
+ printGroupTree((VGroup) child, level + 1);
+ }
+ }
+ }
+
+ void setAllowCaching(boolean allowCaching) {
+ mAllowCaching = allowCaching;
+ }
+
+ // We don't support RTL auto mirroring since the getLayoutDirection() is for API 17+.
+ private boolean needMirroring() {
+ return false;
+ }
+
+ private static class VectorDrawableState extends ConstantState {
+ int mChangingConfigurations;
+ VPathRenderer mVPathRenderer;
+ ColorStateList mTint = null;
+ Mode mTintMode = DEFAULT_TINT_MODE;
+ boolean mAutoMirrored;
+
+ Bitmap mCachedBitmap;
+ int[] mCachedThemeAttrs;
+ ColorStateList mCachedTint;
+ Mode mCachedTintMode;
+ int mCachedRootAlpha;
+ boolean mCachedAutoMirrored;
+ boolean mCacheDirty;
+
+ /** Temporary paint object used to draw cached bitmaps. */
+ Paint mTempPaint;
+
+ // Deep copy for mutate() or implicitly mutate.
+ public VectorDrawableState(VectorDrawableState copy) {
+ if (copy != null) {
+ mChangingConfigurations = copy.mChangingConfigurations;
+ mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
+ if (copy.mVPathRenderer.mFillPaint != null) {
+ mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint);
+ }
+ if (copy.mVPathRenderer.mStrokePaint != null) {
+ mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint);
+ }
+ mTint = copy.mTint;
+ mTintMode = copy.mTintMode;
+ mAutoMirrored = copy.mAutoMirrored;
+ }
+ }
+
+ public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter) {
+ // The bitmap's size is the same as the bounds.
+ final Paint p = getPaint(filter);
+ canvas.drawBitmap(mCachedBitmap, 0, 0, p);
+ }
+
+ public boolean hasTranslucentRoot() {
+ return mVPathRenderer.getRootAlpha() < 255;
+ }
+
+ /**
+ * @return null when there is no need for alpha paint.
+ */
+ public Paint getPaint(ColorFilter filter) {
+ if (!hasTranslucentRoot() && filter == null) {
+ return null;
+ }
+
+ if (mTempPaint == null) {
+ mTempPaint = new Paint();
+ mTempPaint.setFilterBitmap(true);
+ }
+ mTempPaint.setAlpha(mVPathRenderer.getRootAlpha());
+ mTempPaint.setColorFilter(filter);
+ return mTempPaint;
+ }
+
+ public void updateCachedBitmap(Rect bounds) {
+ mCachedBitmap.eraseColor(Color.TRANSPARENT);
+ Canvas tmpCanvas = new Canvas(mCachedBitmap);
+ mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height(), null);
+ }
+
+ public void createCachedBitmapIfNeeded(Rect bounds) {
+ if (mCachedBitmap == null || !canReuseBitmap(bounds.width(),
+ bounds.height())) {
+ mCachedBitmap = Bitmap.createBitmap(bounds.width(), bounds.height(),
+ Bitmap.Config.ARGB_8888);
+ mCacheDirty = true;
+ }
+
+ }
+
+ public boolean canReuseBitmap(int width, int height) {
+ if (width == mCachedBitmap.getWidth()
+ && height == mCachedBitmap.getHeight()) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canReuseCache() {
+ if (!mCacheDirty
+ && mCachedTint == mTint
+ && mCachedTintMode == mTintMode
+ && mCachedAutoMirrored == mAutoMirrored
+ && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
+ return true;
+ }
+ return false;
+ }
+
+ public void updateCacheStates() {
+ // Use shallow copy here and shallow comparison in canReuseCache(),
+ // likely hit cache miss more, but practically not much difference.
+ mCachedTint = mTint;
+ mCachedTintMode = mTintMode;
+ mCachedRootAlpha = mVPathRenderer.getRootAlpha();
+ mCachedAutoMirrored = mAutoMirrored;
+ mCacheDirty = false;
+ }
+
+ public VectorDrawableState() {
+ mVPathRenderer = new VPathRenderer();
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new VectorDrawableCompat(this);
+ }
+
+ @Override
+ public Drawable newDrawable(Resources res) {
+ return new VectorDrawableCompat(this);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return mChangingConfigurations;
+ }
+ }
+
+ private static class VPathRenderer {
+ /* Right now the internal data structure is organized as a tree.
+ * Each node can be a group node, or a path.
+ * A group node can have groups or paths as children, but a path node has
+ * no children.
+ * One example can be:
+ * Root Group
+ * / | \
+ * Group Path Group
+ * / \ |
+ * Path Path Path
+ *
+ */
+ // Variables that only used temporarily inside the draw() call, so there
+ // is no need for deep copying.
+ private final Path mPath;
+ private final Path mRenderPath;
+ private static final Matrix IDENTITY_MATRIX = new Matrix();
+ private final Matrix mFinalPathMatrix = new Matrix();
+
+ private Paint mStrokePaint;
+ private Paint mFillPaint;
+ private PathMeasure mPathMeasure;
+
+ /////////////////////////////////////////////////////
+ // Variables below need to be copied (deep copy if applicable) for mutation.
+ private int mChangingConfigurations;
+ private final VGroup mRootGroup;
+ float mBaseWidth = 0;
+ float mBaseHeight = 0;
+ float mViewportWidth = 0;
+ float mViewportHeight = 0;
+ int mRootAlpha = 0xFF;
+ String mRootName = null;
+
+ final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
+
+ public VPathRenderer() {
+ mRootGroup = new VGroup();
+ mPath = new Path();
+ mRenderPath = new Path();
+ }
+
+ public void setRootAlpha(int alpha) {
+ mRootAlpha = alpha;
+ }
+
+ public int getRootAlpha() {
+ return mRootAlpha;
+ }
+
+ // setAlpha() and getAlpha() are used mostly for animation purpose, since
+ // Animator like to use alpha from 0 to 1.
+ public void setAlpha(float alpha) {
+ setRootAlpha((int) (alpha * 255));
+ }
+
+ @SuppressWarnings("unused")
+ public float getAlpha() {
+ return getRootAlpha() / 255.0f;
+ }
+
+ public VPathRenderer(VPathRenderer copy) {
+ mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
+ mPath = new Path(copy.mPath);
+ mRenderPath = new Path(copy.mRenderPath);
+ mBaseWidth = copy.mBaseWidth;
+ mBaseHeight = copy.mBaseHeight;
+ mViewportWidth = copy.mViewportWidth;
+ mViewportHeight = copy.mViewportHeight;
+ mChangingConfigurations = copy.mChangingConfigurations;
+ mRootAlpha = copy.mRootAlpha;
+ mRootName = copy.mRootName;
+ if (copy.mRootName != null) {
+ mVGTargetsMap.put(copy.mRootName, this);
+ }
+ }
+
+ private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
+ Canvas canvas, int w, int h, ColorFilter filter) {
+ // Calculate current group's matrix by preConcat the parent's and
+ // and the current one on the top of the stack.
+ // Basically the Mfinal = Mviewport * M0 * M1 * M2;
+ // Mi the local matrix at level i of the group tree.
+ currentGroup.mStackedMatrix.set(currentMatrix);
+
+ currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
+
+ // Draw the group tree in the same order as the XML file.
+ for (int i = 0; i < currentGroup.mChildren.size(); i++) {
+ Object child = currentGroup.mChildren.get(i);
+ if (child instanceof VGroup) {
+ VGroup childGroup = (VGroup) child;
+ drawGroupTree(childGroup, currentGroup.mStackedMatrix,
+ canvas, w, h, filter);
+ } else if (child instanceof VPath) {
+ VPath childPath = (VPath) child;
+ drawPath(currentGroup, childPath, canvas, w, h, filter);
+ }
+ }
+ }
+
+ public void draw(Canvas canvas, int w, int h, ColorFilter filter) {
+ // Travese the tree in pre-order to draw.
+ drawGroupTree(mRootGroup, IDENTITY_MATRIX, canvas, w, h, filter);
+ }
+
+ private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h,
+ ColorFilter filter) {
+ final float scaleX = w / mViewportWidth;
+ final float scaleY = h / mViewportHeight;
+ final float minScale = Math.min(scaleX, scaleY);
+
+ mFinalPathMatrix.set(vGroup.mStackedMatrix);
+ mFinalPathMatrix.postScale(scaleX, scaleY);
+
+ vPath.toPath(mPath);
+ final Path path = mPath;
+
+ mRenderPath.reset();
+
+ if (vPath.isClipPath()) {
+ mRenderPath.addPath(path, mFinalPathMatrix);
+ canvas.clipPath(mRenderPath, Region.Op.REPLACE);
+ } else {
+ VFullPath fullPath = (VFullPath) vPath;
+ if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
+ float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
+ float end = (fullPath.mTrimPathEnd + fullPath.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.addPath(path, mFinalPathMatrix);
+
+ if (fullPath.mFillColor != Color.TRANSPARENT) {
+ if (mFillPaint == null) {
+ mFillPaint = new Paint();
+ mFillPaint.setStyle(Paint.Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ }
+
+ final Paint fillPaint = mFillPaint;
+ fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
+ fillPaint.setColorFilter(filter);
+ canvas.drawPath(mRenderPath, fillPaint);
+ }
+
+ if (fullPath.mStrokeColor != Color.TRANSPARENT) {
+ if (mStrokePaint == null) {
+ mStrokePaint = new Paint();
+ mStrokePaint.setStyle(Paint.Style.STROKE);
+ mStrokePaint.setAntiAlias(true);
+ }
+
+ final Paint strokePaint = mStrokePaint;
+ if (fullPath.mStrokeLineJoin != null) {
+ strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
+ }
+
+ if (fullPath.mStrokeLineCap != null) {
+ strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
+ }
+
+ strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
+ strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
+ strokePaint.setColorFilter(filter);
+ strokePaint.setStrokeWidth(fullPath.mStrokeWidth * minScale);
+ canvas.drawPath(mRenderPath, strokePaint);
+ }
+ }
+ }
+ }
+
+ private static class VGroup {
+ // mStackedMatrix is only used temporarily when drawing, it combines all
+ // the parents' local matrices with the current one.
+ private final Matrix mStackedMatrix = new Matrix();
+
+ /////////////////////////////////////////////////////
+ // Variables below need to be copied (deep copy if applicable) for mutation.
+ final ArrayList<Object> mChildren = new ArrayList<Object>();
+
+ private float mRotate = 0;
+ private float mPivotX = 0;
+ private float mPivotY = 0;
+ private float mScaleX = 1;
+ private float mScaleY = 1;
+ private float mTranslateX = 0;
+ private float mTranslateY = 0;
+
+ // mLocalMatrix is updated based on the update of transformation information,
+ // either parsed from the XML or by animation.
+ private final Matrix mLocalMatrix = new Matrix();
+ private int mChangingConfigurations;
+ private int[] mThemeAttrs;
+ private String mGroupName = null;
+
+ public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
+ mRotate = copy.mRotate;
+ mPivotX = copy.mPivotX;
+ mPivotY = copy.mPivotY;
+ mScaleX = copy.mScaleX;
+ mScaleY = copy.mScaleY;
+ mTranslateX = copy.mTranslateX;
+ mTranslateY = copy.mTranslateY;
+ mThemeAttrs = copy.mThemeAttrs;
+ mGroupName = copy.mGroupName;
+ mChangingConfigurations = copy.mChangingConfigurations;
+ if (mGroupName != null) {
+ targetsMap.put(mGroupName, this);
+ }
+
+ mLocalMatrix.set(copy.mLocalMatrix);
+
+ final ArrayList<Object> children = copy.mChildren;
+ for (int i = 0; i < children.size(); i++) {
+ Object copyChild = children.get(i);
+ if (copyChild instanceof VGroup) {
+ VGroup copyGroup = (VGroup) copyChild;
+ mChildren.add(new VGroup(copyGroup, targetsMap));
+ } else {
+ VPath newPath = null;
+ if (copyChild instanceof VFullPath) {
+ newPath = new VFullPath((VFullPath) copyChild);
+ } else if (copyChild instanceof VClipPath) {
+ newPath = new VClipPath((VClipPath) copyChild);
+ } else {
+ throw new IllegalStateException("Unknown object in the tree!");
+ }
+ mChildren.add(newPath);
+ if (newPath.mPathName != null) {
+ targetsMap.put(newPath.mPathName, newPath);
+ }
+ }
+ }
+ }
+
+ public VGroup() {
+ }
+
+ public String getGroupName() {
+ return mGroupName;
+ }
+
+ public Matrix getLocalMatrix() {
+ return mLocalMatrix;
+ }
+
+ public void inflate(Resources res, AttributeSet attrs, Theme theme) {
+ final TypedArray a = obtainAttributes(res, theme, attrs,
+ R.styleable.VectorDrawableGroup);
+ updateStateFromTypedArray(a);
+ a.recycle();
+ }
+
+ private void updateStateFromTypedArray(TypedArray a) {
+ // Account for any configuration changes.
+ // mChangingConfigurations |= Utils.getChangingConfigurations(a);
+
+ // Extract the theme attributes, if any.
+ mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
+
+ mRotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, mRotate);
+ mPivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mPivotX);
+ mPivotY = a.getFloat(R.styleable.VectorDrawableGroup_pivotY, mPivotY);
+ mScaleX = a.getFloat(R.styleable.VectorDrawableGroup_scaleX, mScaleX);
+ mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY);
+ mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
+ mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
+
+ final String groupName = a.getString(R.styleable.VectorDrawableGroup_name);
+ if (groupName != null) {
+ mGroupName = groupName;
+ }
+
+ updateLocalMatrix();
+ }
+
+ private void updateLocalMatrix() {
+ // The order we apply is the same as the
+ // RenderNode.cpp::applyViewPropertyTransforms().
+ mLocalMatrix.reset();
+ mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
+ mLocalMatrix.postScale(mScaleX, mScaleY);
+ mLocalMatrix.postRotate(mRotate, 0, 0);
+ mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
+ }
+
+ /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+ @SuppressWarnings("unused")
+ public float getRotation() {
+ return mRotate;
+ }
+
+ @SuppressWarnings("unused")
+ public void setRotation(float rotation) {
+ if (rotation != mRotate) {
+ mRotate = rotation;
+ updateLocalMatrix();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public float getPivotX() {
+ return mPivotX;
+ }
+
+ @SuppressWarnings("unused")
+ public void setPivotX(float pivotX) {
+ if (pivotX != mPivotX) {
+ mPivotX = pivotX;
+ updateLocalMatrix();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public float getPivotY() {
+ return mPivotY;
+ }
+
+ @SuppressWarnings("unused")
+ public void setPivotY(float pivotY) {
+ if (pivotY != mPivotY) {
+ mPivotY = pivotY;
+ updateLocalMatrix();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public float getScaleX() {
+ return mScaleX;
+ }
+
+ @SuppressWarnings("unused")
+ public void setScaleX(float scaleX) {
+ if (scaleX != mScaleX) {
+ mScaleX = scaleX;
+ updateLocalMatrix();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public float getScaleY() {
+ return mScaleY;
+ }
+
+ @SuppressWarnings("unused")
+ public void setScaleY(float scaleY) {
+ if (scaleY != mScaleY) {
+ mScaleY = scaleY;
+ updateLocalMatrix();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public float getTranslateX() {
+ return mTranslateX;
+ }
+
+ @SuppressWarnings("unused")
+ public void setTranslateX(float translateX) {
+ if (translateX != mTranslateX) {
+ mTranslateX = translateX;
+ updateLocalMatrix();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public float getTranslateY() {
+ return mTranslateY;
+ }
+
+ @SuppressWarnings("unused")
+ public void setTranslateY(float translateY) {
+ if (translateY != mTranslateY) {
+ mTranslateY = translateY;
+ updateLocalMatrix();
+ }
+ }
+ }
+
+ /**
+ * Common Path information for clip path and normal path.
+ */
+ private static class VPath {
+ protected PathParser.PathDataNode[] mNodes = null;
+ String mPathName;
+ int mChangingConfigurations;
+
+ public VPath() {
+ // Empty constructor.
+ }
+
+ public VPath(VPath copy) {
+ mPathName = copy.mPathName;
+ mChangingConfigurations = copy.mChangingConfigurations;
+ mNodes = PathParser.deepCopyNodes(copy.mNodes);
+ }
+
+ public void toPath(Path path) {
+ path.reset();
+ if (mNodes != null) {
+ PathParser.PathDataNode.nodesToPath(mNodes, path);
+ }
+ }
+
+ public String getPathName() {
+ return mPathName;
+ }
+
+ public boolean canApplyTheme() {
+ return false;
+ }
+
+ public void applyTheme(Theme t) {
+ }
+
+ public boolean isClipPath() {
+ return false;
+ }
+
+ /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+ @SuppressWarnings("unused")
+ public PathParser.PathDataNode[] getPathData() {
+ return mNodes;
+ }
+
+ @SuppressWarnings("unused")
+ public void setPathData(PathParser.PathDataNode[] nodes) {
+ if (!PathParser.canMorph(mNodes, nodes)) {
+ // This should not happen in the middle of animation.
+ mNodes = PathParser.deepCopyNodes(nodes);
+ } else {
+ PathParser.updateNodes(mNodes, nodes);
+ }
+ }
+ }
+
+ /**
+ * Clip path, which only has name and pathData.
+ */
+ private static class VClipPath extends VPath {
+ public VClipPath() {
+ // Empty constructor.
+ }
+
+ public VClipPath(VClipPath copy) {
+ super(copy);
+ }
+
+ public void inflate(Resources r, AttributeSet attrs, Theme theme) {
+ // TODO TINT THEME Not supported yet
+ final TypedArray a = obtainAttributes(r, theme, attrs,
+ R.styleable.VectorDrawableClipPath);
+ updateStateFromTypedArray(a);
+ a.recycle();
+ }
+
+ private void updateStateFromTypedArray(TypedArray a) {
+ // Account for any configuration changes.
+ // mChangingConfigurations |= Utils.getChangingConfigurations(a);;
+
+ final String pathName = a.getString(R.styleable.VectorDrawableClipPath_name);
+ if (pathName != null) {
+ mPathName = pathName;
+ }
+
+ final String pathData = a.getString(R.styleable.VectorDrawableClipPath_pathData);
+ if (pathData != null) {
+ mNodes = PathParser.createNodesFromPathData(pathData);
+ }
+ }
+
+ @Override
+ public boolean isClipPath() {
+ return true;
+ }
+ }
+
+ /**
+ * Normal path, which contains all the fill / paint information.
+ */
+ private static class VFullPath extends VPath {
+ /////////////////////////////////////////////////////
+ // Variables below need to be copied (deep copy if applicable) for mutation.
+ private int[] mThemeAttrs;
+
+ int mStrokeColor = Color.TRANSPARENT;
+ float mStrokeWidth = 0;
+
+ int mFillColor = Color.TRANSPARENT;
+ float mStrokeAlpha = 1.0f;
+ int mFillRule;
+ float mFillAlpha = 1.0f;
+ float mTrimPathStart = 0;
+ float mTrimPathEnd = 1;
+ float mTrimPathOffset = 0;
+
+ Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
+ Paint.Join mStrokeLineJoin = Paint.Join.MITER;
+ float mStrokeMiterlimit = 4;
+
+ public VFullPath() {
+ // Empty constructor.
+ }
+
+ public VFullPath(VFullPath copy) {
+ super(copy);
+ mThemeAttrs = copy.mThemeAttrs;
+
+ mStrokeColor = copy.mStrokeColor;
+ mStrokeWidth = copy.mStrokeWidth;
+ mStrokeAlpha = copy.mStrokeAlpha;
+ mFillColor = copy.mFillColor;
+ mFillRule = copy.mFillRule;
+ mFillAlpha = copy.mFillAlpha;
+ mTrimPathStart = copy.mTrimPathStart;
+ mTrimPathEnd = copy.mTrimPathEnd;
+ mTrimPathOffset = copy.mTrimPathOffset;
+
+ mStrokeLineCap = copy.mStrokeLineCap;
+ mStrokeLineJoin = copy.mStrokeLineJoin;
+ mStrokeMiterlimit = copy.mStrokeMiterlimit;
+ }
+
+ private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
+ switch (id) {
+ case LINECAP_BUTT:
+ return Paint.Cap.BUTT;
+ case LINECAP_ROUND:
+ return Paint.Cap.ROUND;
+ case LINECAP_SQUARE:
+ return Paint.Cap.SQUARE;
+ default:
+ return defValue;
+ }
+ }
+
+ private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
+ switch (id) {
+ case LINEJOIN_MITER:
+ return Paint.Join.MITER;
+ case LINEJOIN_ROUND:
+ return Paint.Join.ROUND;
+ case LINEJOIN_BEVEL:
+ return Paint.Join.BEVEL;
+ default:
+ return defValue;
+ }
+ }
+
+ @Override
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null;
+ }
+
+ public void inflate(Resources r, AttributeSet attrs, Theme theme) {
+ final TypedArray a = obtainAttributes(r, theme, attrs,
+ R.styleable.VectorDrawablePath);
+ updateStateFromTypedArray(a);
+ a.recycle();
+ }
+
+ private void updateStateFromTypedArray(TypedArray a) {
+ // Account for any configuration changes.
+ // mChangingConfigurations |= Utils.getChangingConfigurations(a);
+
+ // Extract the theme attributes, if any.
+ mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
+
+ final String pathName = a.getString(R.styleable.VectorDrawablePath_name);
+ if (pathName != null) {
+ mPathName = pathName;
+ }
+
+ final String pathData = a.getString(R.styleable.VectorDrawablePath_pathData);
+ if (pathData != null) {
+ mNodes = PathParser.createNodesFromPathData(pathData);
+ }
+
+ mFillColor = a.getColor(R.styleable.VectorDrawablePath_fillColor,
+ mFillColor);
+ mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha,
+ mFillAlpha);
+ mStrokeLineCap = getStrokeLineCap(a.getInt(
+ R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
+ mStrokeLineJoin = getStrokeLineJoin(a.getInt(
+ R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
+ mStrokeMiterlimit = a.getFloat(
+ R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
+ mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_strokeColor,
+ mStrokeColor);
+ mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha,
+ mStrokeAlpha);
+ mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth,
+ mStrokeWidth);
+ mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd,
+ mTrimPathEnd);
+ mTrimPathOffset = a.getFloat(
+ R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
+ mTrimPathStart = a.getFloat(
+ R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
+ }
+
+ @Override
+ public void applyTheme(Theme t) {
+ if (mThemeAttrs == null) {
+ return;
+ }
+
+ /*
+ * TODO TINT THEME Not supported yet final TypedArray a =
+ * t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
+ * updateStateFromTypedArray(a); a.recycle();
+ */
+ }
+
+ /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+ @SuppressWarnings("unused")
+ int getStrokeColor() {
+ return mStrokeColor;
+ }
+
+ @SuppressWarnings("unused")
+ void setStrokeColor(int strokeColor) {
+ mStrokeColor = strokeColor;
+ }
+
+ @SuppressWarnings("unused")
+ float getStrokeWidth() {
+ return mStrokeWidth;
+ }
+
+ @SuppressWarnings("unused")
+ void setStrokeWidth(float strokeWidth) {
+ mStrokeWidth = strokeWidth;
+ }
+
+ @SuppressWarnings("unused")
+ float getStrokeAlpha() {
+ return mStrokeAlpha;
+ }
+
+ @SuppressWarnings("unused")
+ void setStrokeAlpha(float strokeAlpha) {
+ mStrokeAlpha = strokeAlpha;
+ }
+
+ @SuppressWarnings("unused")
+ int getFillColor() {
+ return mFillColor;
+ }
+
+ @SuppressWarnings("unused")
+ void setFillColor(int fillColor) {
+ mFillColor = fillColor;
+ }
+
+ @SuppressWarnings("unused")
+ float getFillAlpha() {
+ return mFillAlpha;
+ }
+
+ @SuppressWarnings("unused")
+ void setFillAlpha(float fillAlpha) {
+ mFillAlpha = fillAlpha;
+ }
+
+ @SuppressWarnings("unused")
+ float getTrimPathStart() {
+ return mTrimPathStart;
+ }
+
+ @SuppressWarnings("unused")
+ void setTrimPathStart(float trimPathStart) {
+ mTrimPathStart = trimPathStart;
+ }
+
+ @SuppressWarnings("unused")
+ float getTrimPathEnd() {
+ return mTrimPathEnd;
+ }
+
+ @SuppressWarnings("unused")
+ void setTrimPathEnd(float trimPathEnd) {
+ mTrimPathEnd = trimPathEnd;
+ }
+
+ @SuppressWarnings("unused")
+ float getTrimPathOffset() {
+ return mTrimPathOffset;
+ }
+
+ @SuppressWarnings("unused")
+ void setTrimPathOffset(float trimPathOffset) {
+ mTrimPathOffset = trimPathOffset;
+ }
+ }
+}
diff --git a/graphics/drawable/testanimated/Android.mk b/graphics/drawable/testanimated/Android.mk
new file mode 100644
index 0000000000..c888d9e220
--- /dev/null
+++ b/graphics/drawable/testanimated/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2015 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_MODULE_TAGS := tests
+
+LOCAL_SDK_VERSION := 11
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_RESOURCE_DIR = \
+ $(LOCAL_PATH)/res \
+ frameworks/support/graphics/drawable/res \
+
+LOCAL_PACKAGE_NAME := AndroidAnimatedVectorDrawableTests
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v11-animatedvectordrawable android-support-v4
+
+LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages android.support.graphics.drawable
+
+include $(BUILD_PACKAGE)
diff --git a/graphics/drawable/testanimated/AndroidManifest.xml b/graphics/drawable/testanimated/AndroidManifest.xml
new file mode 100644
index 0000000000..16171f27eb
--- /dev/null
+++ b/graphics/drawable/testanimated/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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="android.support.test.vectordrawable" >
+
+ <uses-sdk android:minSdkVersion="11" />
+
+ <application android:icon="@drawable/app_sample_code" android:label="AnimatedVectorDrawableCompatTest" >
+ <activity android:name="android.support.test.vectordrawable.TestAVDActivity" />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/anim/alpha_animation_progress_bar.xml b/graphics/drawable/testanimated/res/anim/alpha_animation_progress_bar.xml
new file mode 100644
index 0000000000..2463a8940d
--- /dev/null
+++ b/graphics/drawable/testanimated/res/anim/alpha_animation_progress_bar.xml
@@ -0,0 +1,24 @@
+<!-- Copyright (C) 2015 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <objectAnimator
+ android:duration="3350"
+ android:propertyName="alpha"
+ android:valueFrom="1"
+ android:valueTo="0.2" />
+
+</set> \ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/anim/animation_grouping_1_01.xml b/graphics/drawable/testanimated/res/anim/animation_grouping_1_01.xml
new file mode 100644
index 0000000000..36c297fbe9
--- /dev/null
+++ b/graphics/drawable/testanimated/res/anim/animation_grouping_1_01.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="3300"
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="450" />
diff --git a/graphics/drawable/testanimated/res/anim/trim_path_animation_progress_bar.xml b/graphics/drawable/testanimated/res/anim/trim_path_animation_progress_bar.xml
new file mode 100644
index 0000000000..388c759a77
--- /dev/null
+++ b/graphics/drawable/testanimated/res/anim/trim_path_animation_progress_bar.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <objectAnimator
+ android:duration="1300"
+ android:interpolator="@android:anim/linear_interpolator"
+ android:propertyName="trimPathStart"
+ android:repeatCount="-1"
+ android:valueFrom="0"
+ android:valueTo="0.75"
+ android:valueType="floatType" />
+ <objectAnimator
+ android:duration="1300"
+ android:interpolator="@android:anim/linear_interpolator"
+ android:propertyName="trimPathEnd"
+ android:repeatCount="-1"
+ android:valueFrom="0.25"
+ android:valueTo="1.0"
+ android:valueType="floatType" />
+ <objectAnimator
+ android:duration="1300"
+ android:interpolator="@android:anim/linear_interpolator"
+ android:propertyName="trimPathOffset"
+ android:repeatCount="-1"
+ android:valueFrom="0"
+ android:valueTo="0.25"
+ android:valueType="floatType" />
+
+</set> \ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/drawable/animation_vector_drawable_grouping_1.xml b/graphics/drawable/testanimated/res/drawable/animation_vector_drawable_grouping_1.xml
new file mode 100644
index 0000000000..7c3b1de076
--- /dev/null
+++ b/graphics/drawable/testanimated/res/drawable/animation_vector_drawable_grouping_1.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (C) 2015 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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:drawable="@drawable/vector_drawable_grouping_1" >
+
+ <target
+ auto:name="sun"
+ auto:animation="@anim/animation_grouping_1_01" />
+ <target
+ auto:name="earth"
+ auto:animation="@anim/animation_grouping_1_01" />
+
+</animated-vector> \ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/drawable/animation_vector_progress_bar.xml b/graphics/drawable/testanimated/res/drawable/animation_vector_progress_bar.xml
new file mode 100644
index 0000000000..e37d2a1afe
--- /dev/null
+++ b/graphics/drawable/testanimated/res/drawable/animation_vector_progress_bar.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2015 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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:drawable="@drawable/vector_drawable_progress_bar" >
+
+ <target
+ auto:name="pie1"
+ auto:animation="@anim/trim_path_animation_progress_bar" />
+ <target
+ auto:name="root_bar"
+ auto:animation="@anim/alpha_animation_progress_bar" />
+</animated-vector> \ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/drawable/app_sample_code.png b/graphics/drawable/testanimated/res/drawable/app_sample_code.png
new file mode 100755
index 0000000000..66a198496c
--- /dev/null
+++ b/graphics/drawable/testanimated/res/drawable/app_sample_code.png
Binary files differ
diff --git a/graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml b/graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml
new file mode 100644
index 0000000000..eceda711fa
--- /dev/null
+++ b/graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml
@@ -0,0 +1,53 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="256"
+ auto:viewportWidth="256" >
+
+ <group
+ auto:name="shape_layer_1"
+ auto:translateX="128"
+ auto:translateY="128" >
+ <group auto:name="sun" >
+ <path
+ auto:name="ellipse_path_1"
+ auto:fillColor="#ffff8000"
+ auto:pathData="m -25 0 a 25,25 0 1,0 50,0 a 25,25 0 1,0 -50,0" />
+
+ <group
+ auto:name="earth"
+ auto:translateX="75" >
+ <path
+ auto:name="ellipse_path_1_1"
+ auto:fillColor="#ff5656ea"
+ auto:pathData="m -10 0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0" />
+
+ <group
+ auto:name="moon"
+ auto:translateX="25" >
+ <path
+ auto:name="ellipse_path_1_2"
+ auto:fillColor="#ffadadad"
+ auto:pathData="m -5 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0" />
+ </group>
+ </group>
+ </group>
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml b/graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml
new file mode 100644
index 0000000000..0b8884b487
--- /dev/null
+++ b/graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml
@@ -0,0 +1,50 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="64"
+ auto:viewportWidth="64"
+ auto:name="root_bar" >
+
+ <group
+ auto:name="root"
+ auto:pivotX="0.0"
+ auto:pivotY="0.0"
+ auto:rotation="0"
+ auto:translateX="32.0"
+ auto:translateY="32.0" >
+ <group
+ auto:name="rotationGroup"
+ auto:pivotX="0.0"
+ auto:pivotY="0.0"
+ auto:rotation="0" >
+ <path
+ auto:name="pie1"
+ auto:fillColor="#00000000"
+ auto:pathData="M0, 0 m 0, -9.5 a 9.5,9.5 0 1,1 0,19 a 9.5,9.5 0 1,1 0,-19"
+ auto:strokeColor="#FF00FFFF"
+ auto:strokeLineCap="round"
+ auto:strokeLineJoin="miter"
+ auto:strokeWidth="2"
+ auto:trimPathEnd="0.1"
+ auto:trimPathOffset="0"
+ auto:trimPathStart="0" />
+ </group>
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/values/strings.xml b/graphics/drawable/testanimated/res/values/strings.xml
new file mode 100644
index 0000000000..c5451c8845
--- /dev/null
+++ b/graphics/drawable/testanimated/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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>
+
+ <string name="twoLinePathData">"M 0,0 v 100 M 0,0 h 100"</string>
+ <string name="triangle"> "M300,70 l 0,-70 70,70 0,0 -70,70z"</string>
+ <string name="rectangle">"M300,70 l 0,-70 70,0 0,140 -70,0 z"</string>
+ <string name="rectangle2">"M300,70 l 0,-70 70,0 0,70z M300,70 l 70,0 0,70 -70,0z"</string>
+ <string name="equal2"> "M300,35 l 0,-35 70,0 0,35z M300,105 l 70,0 0,35 -70,0z"</string>
+ <string name="round_box">"m2.10001,-6c-1.9551,0 -0.5,0.02499 -2.10001,0.02499c-1.575,0 0.0031,-0.02499 -1.95,-0.02499c-2.543,0 -4,2.2816 -4,4.85001c0,3.52929 0.25,6.25 5.95,6.25c5.7,0 6,-2.72071 6,-6.25c0,-2.56841 -1.35699,-4.85001 -3.89999,-4.85001"</string>
+ <string name="heart"> "m4.5,-7c-1.95509,0 -3.83009,1.26759 -4.5,3c-0.66991,-1.73241 -2.54691,-3 -4.5,-3c-2.543,0 -4.5,1.93159 -4.5,4.5c0,3.5293 3.793,6.2578 9,11.5c5.207,-5.2422 9,-7.9707 9,-11.5c0,-2.56841 -1.957,-4.5 -4.5,-4.5"</string>
+ <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+</resources> \ No newline at end of file
diff --git a/graphics/drawable/testanimated/src/android/support/test/vectordrawable/TestAVDActivity.java b/graphics/drawable/testanimated/src/android/support/test/vectordrawable/TestAVDActivity.java
new file mode 100644
index 0000000000..c63c69f947
--- /dev/null
+++ b/graphics/drawable/testanimated/src/android/support/test/vectordrawable/TestAVDActivity.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2015 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.support.test.vectordrawable;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import java.text.DecimalFormat;
+
+public class TestAVDActivity extends Activity implements View.OnClickListener{
+ private static final String LOG_TAG = "TestActivity";
+
+ private static final String LOGCAT = "VectorDrawable1";
+ protected int[] icon = {
+ R.drawable.animation_vector_drawable_grouping_1,
+ R.drawable.animation_vector_progress_bar,
+ };
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ ObjectAnimator oa = new ObjectAnimator();
+ super.onCreate(savedInstanceState);
+ ScrollView scrollView = new ScrollView(this);
+ LinearLayout container = new LinearLayout(this);
+ scrollView.addView(container);
+ container.setOrientation(LinearLayout.VERTICAL);
+ Resources res = this.getResources();
+ container.setBackgroundColor(0xFF888888);
+ AnimatedVectorDrawableCompat []d = new AnimatedVectorDrawableCompat[icon.length];
+ long time = android.os.SystemClock.currentThreadTimeMillis();
+ for (int i = 0; i < icon.length; i++) {
+ d[i] = AnimatedVectorDrawableCompat.create(this, icon[i]);
+ }
+ time = android.os.SystemClock.currentThreadTimeMillis()-time;
+ TextView t = new TextView(this);
+ DecimalFormat df = new DecimalFormat("#.##");
+ t.setText("avgL=" + df.format(time / (icon.length)) + " ms");
+ container.addView(t);
+
+ addDrawableButtons(container, d);
+
+ // Now test constant state and mutate a bit.
+ AnimatedVectorDrawableCompat []copies = new AnimatedVectorDrawableCompat[3];
+ copies[0] = (AnimatedVectorDrawableCompat) d[0].getConstantState().newDrawable();
+ copies[1] = (AnimatedVectorDrawableCompat) d[0].getConstantState().newDrawable();
+ copies[2] = (AnimatedVectorDrawableCompat) d[0].getConstantState().newDrawable();
+ copies[0].setAlpha(128);
+
+ // Expect to see the copies[0, 1] are showing alpha 128, and [2] are showing 255.
+ copies[2].mutate();
+ copies[2].setAlpha(255);
+
+ addDrawableButtons(container, copies);
+
+ setContentView(scrollView);
+ }
+
+ private void addDrawableButtons(LinearLayout container, AnimatedVectorDrawableCompat[] d) {
+ for (int i = 0; i < d.length; i++) {
+ Button button = new Button(this);
+ button.setWidth(200);
+ button.setHeight(200);
+ button.setBackgroundDrawable(d[i]);
+ container.addView(button);
+ button.setOnClickListener(this);
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ AnimatedVectorDrawableCompat d = (AnimatedVectorDrawableCompat) v.getBackground();
+ d.start();
+ }
+}
diff --git a/graphics/drawable/teststatic/Android.mk b/graphics/drawable/teststatic/Android.mk
new file mode 100644
index 0000000000..d8a0fd743f
--- /dev/null
+++ b/graphics/drawable/teststatic/Android.mk
@@ -0,0 +1,38 @@
+# Copyright (C) 2015 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_MODULE_TAGS := tests
+
+LOCAL_SDK_VERSION := 7
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_RESOURCE_DIR = \
+ $(LOCAL_PATH)/res \
+ frameworks/support/graphics/drawable/res \
+
+LOCAL_PACKAGE_NAME := AndroidVectorDrawableTests
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v7-vectordrawable android-support-v4
+
+LOCAL_AAPT_FLAGS := \
+ --auto-add-overlay \
+ --extra-packages android.support.graphics.drawable
+
+include $(BUILD_PACKAGE)
+
diff --git a/graphics/drawable/teststatic/AndroidManifest.xml b/graphics/drawable/teststatic/AndroidManifest.xml
new file mode 100644
index 0000000000..19586fb5d0
--- /dev/null
+++ b/graphics/drawable/teststatic/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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="android.support.test.vectordrawable" >
+
+ <uses-sdk android:minSdkVersion="7" />
+
+ <application android:icon="@drawable/app_sample_code" android:label="VectorDrawableCompatTest" >
+ <activity android:name="android.support.test.vectordrawable.TestActivity" />
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/app_sample_code.png b/graphics/drawable/teststatic/res/drawable/app_sample_code.png
new file mode 100755
index 0000000000..66a198496c
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/app_sample_code.png
Binary files differ
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable01.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable01.xml
new file mode 100644
index 0000000000..12357ef442
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable01.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="48dp"
+ auto:viewportHeight="480"
+ auto:viewportWidth="480"
+ auto:width="48dp" >
+
+ <group>
+ <path
+ auto:name="box1"
+ auto:fillColor="?android:attr/textColorPrimary"
+ auto:pathData="m20,200l100,90l180-180l-35-35l-145,145l-60-60l-40,40z"
+ auto:strokeColor="?android:attr/colorBackground"
+ auto:strokeLineCap="round"
+ auto:strokeLineJoin="round" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable02.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable02.xml
new file mode 100644
index 0000000000..cb6b9dffbd
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable02.xml
@@ -0,0 +1,37 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:viewportHeight="320"
+ auto:viewportWidth="320"
+ auto:width="64dp" >
+
+ <group
+ auto:pivotX="70"
+ auto:pivotY="120"
+ auto:rotation="180" >
+ <path
+ auto:name="house"
+ auto:fillColor="#ff440000"
+ auto:pathData="M 130,225 L 130,115 L 130,115 L 70,15 L 10,115 L 10,115 L 10,225 z"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeWidth="10"
+ auto:trimPathEnd=".9"
+ auto:trimPathStart=".1" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable03.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable03.xml
new file mode 100644
index 0000000000..37d00863c4
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable03.xml
@@ -0,0 +1,72 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:viewportHeight="12.25"
+ auto:viewportWidth="7.30625"
+ auto:width="64dp" >
+
+ <group
+ auto:pivotX="3.65"
+ auto:pivotY="6.125"
+ auto:rotation="-30" >
+ <clip-path
+ auto:name="clip1"
+ auto:pathData="
+ M 0, 6.125
+ l 7.3, 0
+ l 0, 12.25
+ l-7.3, 0
+ z" />
+ </group>
+ <group>
+ <path
+ auto:name="one"
+ auto:fillColor="#ff88ff"
+ auto: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" />
+ </group>
+ <group
+ auto:pivotX="3.65"
+ auto:pivotY="6.125"
+ auto:rotation="-30" >
+ <clip-path
+ auto:name="clip2"
+ auto:pathData="
+ M 0, 0
+ l 7.3, 0
+ l 0, 6.125
+ l-7.3, 0
+ z" />
+ </group>
+ <group>
+ <path
+ auto:name="two"
+ auto:fillColor="#ff88ff"
+ auto: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" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable04.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable04.xml
new file mode 100644
index 0000000000..4e2086f858
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable04.xml
@@ -0,0 +1,58 @@
+<!-- Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:width="64dp"
+ auto:height="64dp"
+ auto:viewportWidth="7.30625"
+ auto:viewportHeight="12.25"
+ auto:autoMirrored="true">
+
+ <group>
+ <clip-path
+ auto:name="clip1"
+ auto: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"/>
+ <path
+ auto:name="one"
+ auto: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"
+ auto:fillColor="#ff88ff"/>
+
+ <clip-path
+ auto:name="clip2"
+ auto: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"/>
+ <path
+ auto:name="two"
+ auto: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"
+ auto:fillColor="#ff88ff"/>
+ </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable05.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable05.xml
new file mode 100644
index 0000000000..48801e3232
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable05.xml
@@ -0,0 +1,44 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="12.25"
+ auto:viewportWidth="7.30625" >
+
+ <group>
+ <path
+ auto:name="one"
+ auto:fillColor="#ffff00"
+ auto: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" />
+ <path
+ auto:name="two"
+ auto:fillColor="#ffff00"
+ auto:fillAlpha="0"
+ auto: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" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable06.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable06.xml
new file mode 100644
index 0000000000..24173e2fc3
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable06.xml
@@ -0,0 +1,49 @@
+<!-- Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:width="64dp"
+ auto:height="64dp"
+ auto:viewportWidth="700"
+ auto:viewportHeight="700">
+
+ <group>
+ <path auto:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
+ auto:name="path2451"
+ auto:fillColor="#00000000"
+ auto:strokeColor="#FF000000"
+ auto:strokeWidth="30.65500000000000"/>
+ <path auto:pathData="M 365.015 311.066"
+ auto:name="path2453"
+ auto:fillColor="#00000000"
+ auto:strokeColor="#FF000000"
+ auto:strokeWidth="30.655000000000001"/>
+ <path auto: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"
+ auto:name="path2455"
+ auto:strokeColor="#FF000000"
+ auto:fillColor="#FFFFFFFF"
+ auto:strokeWidth="30.655000000000001"/>
+ <path auto:pathData="M 170.515 451.566L 305.61 313.46"
+ auto:name="path2457"
+ auto:fillColor="#00000000"
+ auto:strokeColor="#000000"
+ auto:strokeWidth="30.655000000000001"/>
+ <path auto:pathData="M 557.968 449.974L 426.515 315.375"
+ auto:name="path2459"
+ auto:fillColor="#00000000"
+ auto:strokeColor="#000000"
+ auto:strokeWidth="30.655000000000001"/>
+ </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable07.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable07.xml
new file mode 100644
index 0000000000..90435d3bf9
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable07.xml
@@ -0,0 +1,30 @@
+<!-- Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:width="64dp"
+ auto:height="64dp" auto:viewportWidth="140"
+ auto:viewportHeight="110">
+
+ <group>
+ <path
+ auto:name="back"
+ auto: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"
+ auto:fillColor="#ffffffff"
+ />
+ </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable08.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable08.xml
new file mode 100644
index 0000000000..251d694d72
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable08.xml
@@ -0,0 +1,30 @@
+<!-- Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:width="64dp"
+ auto:height="64dp" auto:viewportWidth="600"
+ auto:viewportHeight="600">
+
+ <group>
+ <path
+ auto:name="pie1"
+ auto:pathData="M535.441,412.339A280.868,280.868 0 1,1 536.186,161.733L284.493,286.29Z"
+ auto:fillColor="#ffffcc00"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeWidth="1"/>
+ </group>
+
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable09.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable09.xml
new file mode 100644
index 0000000000..eccb0d092c
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable09.xml
@@ -0,0 +1,33 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="200"
+ auto:viewportWidth="200" >
+
+ <group
+ auto:pivotX="100"
+ auto:pivotY="100"
+ auto:rotation="90">
+ <path
+ auto:name="house"
+ auto:fillColor="#ffffffff"
+ auto:pathData="M 100,20 l 0,0 0,140-80,0 z M 100,20 l 0,0 80,140-80,0 z"/>
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable10.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable10.xml
new file mode 100644
index 0000000000..b26d30d087
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable10.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportWidth="200"
+ auto:viewportHeight="200">
+
+ <group>
+ <path
+ auto:name="bar3"
+ auto:fillColor="#FFFFFFFF"
+ auto: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" />
+ <path
+ auto:name="bar2"
+ auto:fillColor="#FFFFFFFF"
+ auto: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" />
+ <path
+ auto:name="bar1"
+ auto:fillColor="#FF555555"
+ auto: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" />
+ <path
+ auto:name="bar0"
+ auto:fillColor="#FF555555"
+ auto: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" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable11.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable11.xml
new file mode 100644
index 0000000000..eb440f5d31
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable11.xml
@@ -0,0 +1,36 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="80"
+ auto:viewportWidth="40" >
+
+ <group>
+ <path
+ auto:name="battery"
+ auto:fillColor="#3388ff"
+ auto: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"
+ auto:strokeColor="#ff8833"
+ auto:strokeWidth="1" />
+ <path
+ auto:name="spark"
+ auto:fillColor="#FFFF0000"
+ auto: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" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable12.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable12.xml
new file mode 100644
index 0000000000..94a23e8b23
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable12.xml
@@ -0,0 +1,98 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:name="rootGroup"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="600"
+ auto:viewportWidth="600"
+ auto:alpha="0.5" >
+
+ <group
+ auto:name="rotationGroup"
+ auto:pivotX="300.0"
+ auto:pivotY="300.0"
+ auto:rotation="45.0" >
+ <path
+ auto:name="pie1"
+ auto:fillColor="#00000000"
+ auto:pathData="M300,70 a230,230 0 1,0 1,0 z"
+ auto:strokeColor="#FF777777"
+ auto:strokeWidth="70"
+ auto:trimPathEnd=".75"
+ auto:trimPathOffset="0"
+ auto:trimPathStart="0" />
+ <path
+ auto:name="v"
+ auto:fillColor="#000000"
+ auto:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
+
+ <group
+ auto:name="translateToCenterGroup"
+ auto:rotation="0.0"
+ auto:translateX="200.0"
+ auto:translateY="200.0" >
+ <group
+ auto:name="rotationGroup2"
+ auto:pivotX="0.0"
+ auto:pivotY="0.0"
+ auto:rotation="-45.0" >
+ <path
+ auto:name="twoLines1"
+ auto:pathData="@string/twoLinePathData"
+ auto:strokeColor="#FFFF0000"
+ auto:strokeWidth="20" />
+
+ <group
+ auto:name="translateGroupHalf"
+ auto:translateX="65.0"
+ auto:translateY="80.0" >
+ <group
+ auto:name="rotationGroup3"
+ auto:pivotX="-65.0"
+ auto:pivotY="-80.0"
+ auto:rotation="-45.0" >
+ <path
+ auto:name="twoLines2"
+ auto:fillColor="#FF00FF00"
+ auto:pathData="@string/twoLinePathData"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeWidth="20" />
+
+ <group
+ auto:name="translateGroup"
+ auto:translateX="65.0"
+ auto:translateY="80.0" >
+ <group
+ auto:name="rotationGroupBlue"
+ auto:pivotX="-65.0"
+ auto:pivotY="-80.0"
+ auto:rotation="-45.0" >
+ <path
+ auto:name="twoLines3"
+ auto:pathData="@string/twoLinePathData"
+ auto:strokeColor="#FF0000FF"
+ auto:strokeWidth="20" />
+ </group>
+ </group>
+ </group>
+ </group>
+ </group>
+ </group>
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable13.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable13.xml
new file mode 100644
index 0000000000..43fc7eadd2
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable13.xml
@@ -0,0 +1,38 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="400"
+ auto:viewportWidth="600" >
+
+ <group>
+ <path
+ auto:name="pie1"
+ auto:fillColor="#ffffffff"
+ auto:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeWidth="1" />
+ <path
+ auto:name="half"
+ auto:fillColor="#FFFF0000"
+ auto:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
+ auto:strokeColor="#FF0000FF"
+ auto:strokeWidth="5" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable14.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable14.xml
new file mode 100644
index 0000000000..5b4fdd1851
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable14.xml
@@ -0,0 +1,39 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="500"
+ auto:viewportWidth="800" >
+
+ <group
+ auto:pivotX="90"
+ auto:pivotY="100"
+ auto:rotation="20">
+ <path
+ auto:name="pie2"
+ auto: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"
+ auto:fillColor="#00000000"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeWidth="10" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable15.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable15.xml
new file mode 100644
index 0000000000..f4ef87fc3f
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable15.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="400"
+ auto:viewportWidth="500" >
+
+ <group
+ auto:pivotX="250"
+ auto:pivotY="200"
+ auto:rotation="180">
+ <path
+ auto:name="house"
+ auto:fillColor="#ff440000"
+ auto:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ auto:strokeColor="#FFFF0000"
+ auto:strokeWidth="10" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable16.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable16.xml
new file mode 100644
index 0000000000..0c64bca831
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable16.xml
@@ -0,0 +1,48 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="200"
+ auto:viewportWidth="200" >
+
+ <group>
+ <path
+ auto:name="background1"
+ auto:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z"
+ auto:fillColor="#FF000000"/>
+ <path
+ auto:name="background2"
+ auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
+ auto:fillColor="#FF000000"/>
+ </group>
+ <group
+ auto:pivotX="100"
+ auto:pivotY="100"
+ auto:rotation="90"
+ auto:scaleX="0.75"
+ auto:scaleY="0.5"
+ auto:translateX="0.0"
+ auto:translateY="100.0">
+ <path
+ auto:name="twoLines"
+ auto:pathData="M 100,10 v 90 M 10,100 h 90"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeWidth="10" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable17.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable17.xml
new file mode 100644
index 0000000000..28cf09a1ee
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable17.xml
@@ -0,0 +1,30 @@
+<!-- Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:width="64dp"
+ auto:height="64dp" auto:viewportWidth="1200"
+ auto:viewportHeight="600">
+
+ <group>
+ <path
+ auto:name="house"
+ auto:pathData="M200,300 Q400,50 600,300 T1000,300"
+ auto:fillColor="#00000000"
+ auto:strokeColor="#FFFF0000"
+ auto:strokeWidth="10"/>
+ </group>
+
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable18.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable18.xml
new file mode 100644
index 0000000000..d66d4ff4c1
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable18.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="400"
+ auto:viewportWidth="500" >
+
+ <group>
+ <path
+ auto:name="house"
+ auto:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ auto:fillColor="#00000000"
+ auto:strokeColor="#FFFFFF00"
+ auto:strokeWidth="10" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable19.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable19.xml
new file mode 100644
index 0000000000..3a6559d818
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable19.xml
@@ -0,0 +1,34 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="800"
+ auto:viewportWidth="1000" >
+
+ <group>
+ <path
+ auto:name="house"
+ auto:pathData="M10,300 Q400,550 600,300 T1000,300"
+ auto:pivotX="90"
+ auto:pivotY="100"
+ auto:fillColor="#00000000"
+ auto:strokeColor="#FFFF0000"
+ auto:strokeWidth="60" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable20.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable20.xml
new file mode 100644
index 0000000000..d6fd7043eb
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable20.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="480"
+ auto:viewportWidth="480" >
+
+ <group>
+ <path
+ auto:name="edit"
+ auto:fillColor="#FF00FFFF"
+ auto: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"
+ auto:strokeColor="#FF000000"
+ auto:strokeWidth="10" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable21.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable21.xml
new file mode 100644
index 0000000000..9136b73417
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable21.xml
@@ -0,0 +1,48 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="200"
+ auto:viewportWidth="200" >
+
+ <group>
+ <path
+ auto:name="background1"
+ auto:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z"
+ auto:fillColor="#FF000000"/>
+ <path
+ auto:name="background2"
+ auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
+ auto:fillColor="#FF000000"/>
+ </group>
+ <group
+ auto:pivotX="0"
+ auto:pivotY="0"
+ auto:rotation="90"
+ auto:scaleX="0.75"
+ auto:scaleY="0.5"
+ auto:translateX="100.0"
+ auto:translateY="100.0">
+ <path
+ auto:name="twoLines"
+ auto:pathData="M 100,10 v 90 M 10,100 h 90"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeWidth="10" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable22.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable22.xml
new file mode 100644
index 0000000000..2b33a8903a
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable22.xml
@@ -0,0 +1,69 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="400"
+ auto:viewportWidth="400" >
+
+ <group auto:name="backgroundGroup" >
+ <path
+ auto:name="background1"
+ auto:fillColor="#80000000"
+ auto:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+ <path
+ auto:name="background2"
+ auto:fillColor="#80000000"
+ auto:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+ </group>
+ <group
+ auto:name="translateToCenterGroup"
+ auto:translateX="50.0"
+ auto:translateY="90.0" >
+ <path
+ auto:name="twoLines"
+ auto:pathData="M 0,0 v 100 M 0,0 h 100"
+ auto:strokeColor="#FFFF0000"
+ auto:strokeWidth="20" />
+
+ <group
+ auto:name="rotationGroup"
+ auto:pivotX="0.0"
+ auto:pivotY="0.0"
+ auto:rotation="-45.0" >
+ <path
+ auto:name="twoLines1"
+ auto:pathData="M 0,0 v 100 M 0,0 h 100"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeWidth="20" />
+
+ <group
+ auto:name="translateGroup"
+ auto:translateX="130.0"
+ auto:translateY="160.0" >
+ <group auto:name="scaleGroup" >
+ <path
+ auto:name="twoLines2"
+ auto:pathData="M 0,0 v 100 M 0,0 h 100"
+ auto:strokeColor="#FF0000FF"
+ auto:strokeWidth="20" />
+ </group>
+ </group>
+ </group>
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable23.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable23.xml
new file mode 100644
index 0000000000..d5759f99f9
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable23.xml
@@ -0,0 +1,83 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="400"
+ auto:viewportWidth="400" >
+
+ <group auto:name="backgroundGroup" >
+ <path
+ auto:name="background1"
+ auto:fillColor="#80000000"
+ auto:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+ <path
+ auto:name="background2"
+ auto:fillColor="#80000000"
+ auto:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+ </group>
+ <group
+ auto:name="translateToCenterGroup"
+ auto:translateX="50.0"
+ auto:translateY="90.0" >
+ <path
+ auto:name="twoLines"
+ auto:pathData="@string/twoLinePathData"
+ auto:strokeColor="#FFFF0000"
+ auto:strokeWidth="20" />
+
+ <group
+ auto:name="rotationGroup"
+ auto:pivotX="0.0"
+ auto:pivotY="0.0"
+ auto:rotation="-45.0" >
+ <path
+ auto:name="twoLines1"
+ auto:pathData="@string/twoLinePathData"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeWidth="20" />
+
+ <group
+ auto:name="translateGroup"
+ auto:translateX="130.0"
+ auto:translateY="160.0" >
+ <group auto:name="scaleGroup" >
+ <path
+ auto:name="twoLines3"
+ auto:pathData="@string/twoLinePathData"
+ auto:strokeColor="#FF0000FF"
+ auto:strokeWidth="20" />
+ </group>
+ </group>
+
+ <group
+ auto:name="translateGroupHalf"
+ auto:translateX="65.0"
+ auto:translateY="80.0" >
+ <group auto:name="scaleGroup" >
+ <path
+ auto:name="twoLines2"
+ auto:pathData="@string/twoLinePathData"
+ auto:fillColor="#FFFFFFFF"
+ auto:strokeColor="#FFFFFFFF"
+ auto:strokeWidth="20" />
+ </group>
+ </group>
+ </group>
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable24.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable24.xml
new file mode 100644
index 0000000000..b05469281c
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable24.xml
@@ -0,0 +1,83 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="400"
+ auto:viewportWidth="400" >
+
+ <group auto:name="backgroundGroup">
+ <path
+ auto:name="background1"
+ auto:fillColor="#FF000000"
+ auto:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+ <path
+ auto:name="background2"
+ auto:fillColor="#FF000000"
+ auto:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+ </group>
+ <group
+ auto:name="translateToCenterGroup"
+ auto:translateX="50.0"
+ auto:translateY="90.0" >
+ <path
+ auto:name="twoLines"
+ auto:pathData="@string/twoLinePathData"
+ auto:strokeColor="#FFFF0000"
+ auto:strokeWidth="20" />
+
+ <group
+ auto:name="rotationGroup"
+ auto:pivotX="0.0"
+ auto:pivotY="0.0"
+ auto:rotation="-45.0">
+ <path
+ auto:name="twoLines1"
+ auto:pathData="@string/twoLinePathData"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeWidth="20" />
+
+ <group
+ auto:name="translateGroup"
+ auto:translateX="130.0"
+ auto:translateY="160.0">
+ <group auto:name="scaleGroup" >
+ <path
+ auto:name="twoLines3"
+ auto:pathData="@string/twoLinePathData"
+ auto:strokeColor="#FF0000FF"
+ auto:strokeWidth="20" />
+ </group>
+ </group>
+
+ <group
+ auto:name="translateGroupHalf"
+ auto:translateX="65.0"
+ auto:translateY="80.0">
+ <group auto:name="scaleGroup" >
+ <path
+ auto:name="twoLines2"
+ auto:pathData="@string/twoLinePathData"
+ auto:fillColor="#FFFFFFFF"
+ auto:strokeColor="#FFFFFFFF"
+ auto:strokeWidth="20" />
+ </group>
+ </group>
+ </group>
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable25.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable25.xml
new file mode 100644
index 0000000000..7a94ed6ca3
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable25.xml
@@ -0,0 +1,83 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:width="64dp"
+ auto:viewportHeight="400"
+ auto:viewportWidth="400" >
+
+ <group
+ auto:name="FirstLevelGroup"
+ auto:translateX="100.0"
+ auto:translateY="0.0" >
+ <group
+ auto:name="SecondLevelGroup1"
+ auto:translateX="-100.0"
+ auto:translateY="50.0" >
+ <path
+ auto:fillColor="#FF00FF00"
+ auto:pathData="@string/rectangle200" />
+
+ <group
+ auto:name="ThridLevelGroup1"
+ auto:translateX="-100.0"
+ auto:translateY="50.0" >
+ <path
+ auto:fillColor="#FF0000FF"
+ auto:pathData="@string/rectangle200" />
+ </group>
+ <group
+ auto:name="ThridLevelGroup2"
+ auto:translateX="100.0"
+ auto:translateY="50.0" >
+ <path
+ auto:fillColor="#FF000000"
+ auto:pathData="@string/rectangle200" />
+ </group>
+ </group>
+ <group
+ auto:name="SecondLevelGroup2"
+ auto:translateX="100.0"
+ auto:translateY="50.0" >
+ <path
+ auto:fillColor="#FF0000FF"
+ auto:pathData="@string/rectangle200" />
+
+ <group
+ auto:name="ThridLevelGroup3"
+ auto:translateX="-100.0"
+ auto:translateY="50.0" >
+ <path
+ auto:fillColor="#FFFF0000"
+ auto:pathData="@string/rectangle200" />
+ </group>
+ <group
+ auto:name="ThridLevelGroup4"
+ auto:translateX="100.0"
+ auto:translateY="50.0" >
+ <path
+ auto:fillColor="#FF00FF00"
+ auto:pathData="@string/rectangle200" />
+ </group>
+ </group>
+
+ <path
+ auto:fillColor="#FFFF0000"
+ auto:pathData="@string/rectangle200" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable26.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable26.xml
new file mode 100644
index 0000000000..b2dd4a3947
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable26.xml
@@ -0,0 +1,46 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:viewportHeight="200"
+ auto:viewportWidth="200"
+ auto:width="64dp" >
+
+ <group>
+ <path
+ auto:name="background1"
+ auto:fillColor="#FF000000"
+ auto:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+ <path
+ auto:name="background2"
+ auto:fillColor="#FF000000"
+ auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+ </group>
+ <group
+ auto:translateX="50"
+ auto:translateY="50" >
+ <path
+ auto:name="twoLines"
+ auto:pathData="M 100,20 l 0 80 l -30 -80"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeLineCap="butt"
+ auto:strokeLineJoin="miter"
+ auto:strokeMiterLimit="5"
+ auto:strokeWidth="20" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable27.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable27.xml
new file mode 100644
index 0000000000..b8f88cee1c
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable27.xml
@@ -0,0 +1,46 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:viewportHeight="200"
+ auto:viewportWidth="200"
+ auto:width="64dp" >
+
+ <group>
+ <path
+ auto:name="background1"
+ auto:fillColor="#FF000000"
+ auto:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+ <path
+ auto:name="background2"
+ auto:fillColor="#FF000000"
+ auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+ </group>
+ <group
+ auto:translateX="50"
+ auto:translateY="50" >
+ <path
+ auto:name="twoLines"
+ auto:pathData="M 100,20 l 0 80 l -30 -80"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeLineCap="round"
+ auto:strokeLineJoin="round"
+ auto:strokeMiterLimit="10"
+ auto:strokeWidth="20" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable28.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable28.xml
new file mode 100644
index 0000000000..30c7fce346
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable28.xml
@@ -0,0 +1,47 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="64dp"
+ auto:viewportHeight="200"
+ auto:viewportWidth="200"
+ auto:width="64dp"
+ auto:autoMirrored="true" >
+
+ <group>
+ <path
+ auto:name="background1"
+ auto:fillColor="#FF000000"
+ auto:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+ <path
+ auto:name="background2"
+ auto:fillColor="#FF000000"
+ auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+ </group>
+ <group
+ auto:translateX="50"
+ auto:translateY="50" >
+ <path
+ auto:name="twoLines"
+ auto:pathData="M 100,20 l 0 80 l -30 -80"
+ auto:strokeColor="#FF00FF00"
+ auto:strokeLineCap="square"
+ auto:strokeLineJoin="bevel"
+ auto:strokeMiterLimit="10"
+ auto:strokeWidth="20" />
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable29.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable29.xml
new file mode 100644
index 0000000000..2ac1d428f4
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable29.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="48dp"
+ auto:width="48dp"
+ auto:viewportHeight="1"
+ auto:viewportWidth="1" >
+
+ <group>
+ <path
+ auto:name="box1"
+ auto:pathData="l0.0.0.5.0.0.5-0.5.0.0-.5z"
+ auto:fillColor="#ff00ff00"/>
+ </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable30.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable30.xml
new file mode 100644
index 0000000000..6abb4552c8
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable30.xml
@@ -0,0 +1,29 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ auto:height="48dp"
+ auto:width="48dp"
+ auto:viewportHeight="48"
+ auto:viewportWidth="48" >
+
+ <group>
+ <path
+ auto:name="plus1"
+ auto:pathData="M20 16h-4v8h-8v4h8v8h4v-8h8v-4h-8zm9-3.84v3.64l5-1v21.2h4v-26z"
+ auto:fillColor="#ff00ff00"/>
+ </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/raw/vector_drawable01.xml b/graphics/drawable/teststatic/res/raw/vector_drawable01.xml
new file mode 100644
index 0000000000..baa3fc7162
--- /dev/null
+++ b/graphics/drawable/teststatic/res/raw/vector_drawable01.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright (C) 2015 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"
+ xmlns:auto="http://schemas.android.com/apk/res-auto"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="480"
+ android:viewportWidth="480" >
+
+ <group>
+ <path
+ android:name="box1"
+ android:pathData="m20,200l100,90l180-180l-35-35l-145,145l-60-60l-40,40z"
+ android:fillColor="?android:attr/colorControlActivated"
+ android:strokeColor="?android:attr/colorControlActivated"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round" />
+ </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/values/strings.xml b/graphics/drawable/teststatic/res/values/strings.xml
new file mode 100644
index 0000000000..c5451c8845
--- /dev/null
+++ b/graphics/drawable/teststatic/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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>
+
+ <string name="twoLinePathData">"M 0,0 v 100 M 0,0 h 100"</string>
+ <string name="triangle"> "M300,70 l 0,-70 70,70 0,0 -70,70z"</string>
+ <string name="rectangle">"M300,70 l 0,-70 70,0 0,140 -70,0 z"</string>
+ <string name="rectangle2">"M300,70 l 0,-70 70,0 0,70z M300,70 l 70,0 0,70 -70,0z"</string>
+ <string name="equal2"> "M300,35 l 0,-35 70,0 0,35z M300,105 l 70,0 0,35 -70,0z"</string>
+ <string name="round_box">"m2.10001,-6c-1.9551,0 -0.5,0.02499 -2.10001,0.02499c-1.575,0 0.0031,-0.02499 -1.95,-0.02499c-2.543,0 -4,2.2816 -4,4.85001c0,3.52929 0.25,6.25 5.95,6.25c5.7,0 6,-2.72071 6,-6.25c0,-2.56841 -1.35699,-4.85001 -3.89999,-4.85001"</string>
+ <string name="heart"> "m4.5,-7c-1.95509,0 -3.83009,1.26759 -4.5,3c-0.66991,-1.73241 -2.54691,-3 -4.5,-3c-2.543,0 -4.5,1.93159 -4.5,4.5c0,3.5293 3.793,6.2578 9,11.5c5.207,-5.2422 9,-7.9707 9,-11.5c0,-2.56841 -1.957,-4.5 -4.5,-4.5"</string>
+ <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+</resources> \ No newline at end of file
diff --git a/graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java b/graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java
new file mode 100644
index 0000000000..8bb766e511
--- /dev/null
+++ b/graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 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.support.test.vectordrawable;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.os.Bundle;
+import android.support.graphics.drawable.VectorDrawableCompat;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import java.text.DecimalFormat;
+
+public class TestActivity extends Activity {
+ private static final String LOG_TAG = "TestActivity";
+
+ 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,
+ R.drawable.vector_drawable21,
+ R.drawable.vector_drawable22,
+ R.drawable.vector_drawable23,
+ R.drawable.vector_drawable24,
+ R.drawable.vector_drawable25,
+ R.drawable.vector_drawable26,
+ R.drawable.vector_drawable27,
+ R.drawable.vector_drawable28,
+ R.drawable.vector_drawable29,
+ R.drawable.vector_drawable30,
+ };
+
+ private static final int EXTRA_TESTS = 2;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ScrollView scrollView = new ScrollView(this);
+ LinearLayout container = new LinearLayout(this);
+ scrollView.addView(container);
+ container.setOrientation(LinearLayout.VERTICAL);
+ Resources res = this.getResources();
+ container.setBackgroundColor(0xFF888888);
+ VectorDrawableCompat []d = new VectorDrawableCompat[icon.length];
+ long time = android.os.SystemClock.currentThreadTimeMillis();
+ for (int i = 0; i < icon.length; i++) {
+ d[i] = VectorDrawableCompat.create(res, icon[i], getTheme());
+ }
+ time = android.os.SystemClock.currentThreadTimeMillis()-time;
+
+ // Testing Tint on one particular case.
+ d[3].setTint(0x8000FF00);
+ d[3].setTintMode(Mode.MULTIPLY);
+
+ // Testing Constant State like operation by creating the first 2 icons
+ // from the 3rd one's constant state.
+ VectorDrawableCompat []extras = new VectorDrawableCompat[EXTRA_TESTS];
+ ConstantState state = d[0].getConstantState();
+ extras[0] = (VectorDrawableCompat) state.newDrawable();
+ extras[1] = (VectorDrawableCompat) state.newDrawable();
+
+ // This alpha change is expected to affect both extra 0, 1, and d0.
+ extras[0].setAlpha(128);
+
+ d[0].mutate();
+ d[0].setAlpha(255);
+
+ // Just show the average create time as the first view.
+ TextView t = new TextView(this);
+ DecimalFormat df = new DecimalFormat("#.##");
+ t.setText("avgL=" + df.format(time / (icon.length)) + " ms");
+ container.addView(t);
+
+ addDrawableButtons(container, extras);
+
+ addDrawableButtons(container, d);
+
+ setContentView(scrollView);
+ }
+
+ private void addDrawableButtons(LinearLayout container, VectorDrawableCompat[] d) {
+ // Add the VD into consequent views.
+ for (int i = 0; i < d.length; i++) {
+ Button button = new Button(this);
+ button.setWidth(200);
+ // Note that setBackgroundResource() will fail b/c createFromXmlInner() failed
+ // to recognize <vector> pre-L.
+ button.setBackgroundDrawable(d[i]);
+ container.addView(button);
+ }
+ }
+}