diff options
36 files changed, 1739 insertions, 102 deletions
diff --git a/api/current.txt b/api/current.txt index bfbb17e94cea..6c7b5b886502 100644 --- a/api/current.txt +++ b/api/current.txt @@ -506,6 +506,8 @@ package android { field public static final int encryptionAware = 16844038; // 0x1010506 field public static final int end = 16843996; // 0x10104dc field public static final int endColor = 16843166; // 0x101019e + field public static final int endX = 16844051; // 0x1010513 + field public static final int endY = 16844052; // 0x1010514 field public static final deprecated int endYear = 16843133; // 0x101017d field public static final int enterFadeDuration = 16843532; // 0x101030c field public static final int entries = 16842930; // 0x10100b2 @@ -881,6 +883,7 @@ package android { field public static final int numbersTextColor = 16843937; // 0x10104a1 field public static final deprecated int numeric = 16843109; // 0x1010165 field public static final int numericShortcut = 16843236; // 0x10101e4 + field public static final int offset = 16844053; // 0x1010515 field public static final int onClick = 16843375; // 0x101026f field public static final int oneshot = 16843159; // 0x1010197 field public static final int opacity = 16843550; // 0x101031e @@ -1128,6 +1131,8 @@ package android { field public static final int startColor = 16843165; // 0x101019d field public static final int startDelay = 16843746; // 0x10103e2 field public static final int startOffset = 16843198; // 0x10101be + field public static final int startX = 16844049; // 0x1010511 + field public static final int startY = 16844050; // 0x1010512 field public static final deprecated int startYear = 16843132; // 0x101017c field public static final int stateListAnimator = 16843848; // 0x1010448 field public static final int stateNotNeeded = 16842774; // 0x1010016 @@ -9949,7 +9954,7 @@ package android.content.res { method public final long skip(long) throws java.io.IOException; } - public class ColorStateList implements android.os.Parcelable { + public class ColorStateList extends android.content.res.ComplexColor implements android.os.Parcelable { ctor public ColorStateList(int[][], int[]); method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; @@ -9958,13 +9963,18 @@ package android.content.res { method public int getColorForState(int[], int); method public int getDefaultColor(); method public boolean isOpaque(); - method public boolean isStateful(); method public static android.content.res.ColorStateList valueOf(int); method public android.content.res.ColorStateList withAlpha(int); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.content.res.ColorStateList> CREATOR; } + public abstract class ComplexColor { + ctor public ComplexColor(); + method public abstract int getDefaultColor(); + method public boolean isStateful(); + } + public final class Configuration implements java.lang.Comparable android.os.Parcelable { ctor public Configuration(); ctor public Configuration(android.content.res.Configuration); @@ -10068,6 +10078,11 @@ package android.content.res { field public int uiMode; } + public class GradientColor extends android.content.res.ComplexColor { + method public static android.content.res.GradientColor createFromXml(android.content.res.Resources, android.content.res.XmlResourceParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public int getDefaultColor(); + } + public class ObbInfo implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); @@ -10127,6 +10142,7 @@ package android.content.res { method public void getValue(java.lang.String, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException; method public void getValueForDensity(int, int, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException; method public android.content.res.XmlResourceParser getXml(int) throws android.content.res.Resources.NotFoundException; + method public android.content.res.ComplexColor loadComplexColor(android.util.TypedValue, int, android.content.res.Resources.Theme); method public final android.content.res.Resources.Theme newTheme(); method public android.content.res.TypedArray obtainAttributes(android.util.AttributeSet, int[]); method public android.content.res.TypedArray obtainTypedArray(int) throws android.content.res.Resources.NotFoundException; @@ -10162,6 +10178,7 @@ package android.content.res { method public int getChangingConfigurations(); method public int getColor(int, int); method public android.content.res.ColorStateList getColorStateList(int); + method public android.content.res.ComplexColor getComplexColor(int); method public float getDimension(int, float); method public int getDimensionPixelOffset(int, int); method public int getDimensionPixelSize(int, int); diff --git a/api/system-current.txt b/api/system-current.txt index c10954c2da4c..16c189c9c43a 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -601,6 +601,8 @@ package android { field public static final int encryptionAware = 16844038; // 0x1010506 field public static final int end = 16843996; // 0x10104dc field public static final int endColor = 16843166; // 0x101019e + field public static final int endX = 16844051; // 0x1010513 + field public static final int endY = 16844052; // 0x1010514 field public static final deprecated int endYear = 16843133; // 0x101017d field public static final int enterFadeDuration = 16843532; // 0x101030c field public static final int entries = 16842930; // 0x10100b2 @@ -976,6 +978,7 @@ package android { field public static final int numbersTextColor = 16843937; // 0x10104a1 field public static final deprecated int numeric = 16843109; // 0x1010165 field public static final int numericShortcut = 16843236; // 0x10101e4 + field public static final int offset = 16844053; // 0x1010515 field public static final int onClick = 16843375; // 0x101026f field public static final int oneshot = 16843159; // 0x1010197 field public static final int opacity = 16843550; // 0x101031e @@ -1227,6 +1230,8 @@ package android { field public static final int startColor = 16843165; // 0x101019d field public static final int startDelay = 16843746; // 0x10103e2 field public static final int startOffset = 16843198; // 0x10101be + field public static final int startX = 16844049; // 0x1010511 + field public static final int startY = 16844050; // 0x1010512 field public static final deprecated int startYear = 16843132; // 0x101017c field public static final int stateListAnimator = 16843848; // 0x1010448 field public static final int stateNotNeeded = 16842774; // 0x1010016 @@ -10349,7 +10354,7 @@ package android.content.res { method public final long skip(long) throws java.io.IOException; } - public class ColorStateList implements android.os.Parcelable { + public class ColorStateList extends android.content.res.ComplexColor implements android.os.Parcelable { ctor public ColorStateList(int[][], int[]); method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; @@ -10358,13 +10363,18 @@ package android.content.res { method public int getColorForState(int[], int); method public int getDefaultColor(); method public boolean isOpaque(); - method public boolean isStateful(); method public static android.content.res.ColorStateList valueOf(int); method public android.content.res.ColorStateList withAlpha(int); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.content.res.ColorStateList> CREATOR; } + public abstract class ComplexColor { + ctor public ComplexColor(); + method public abstract int getDefaultColor(); + method public boolean isStateful(); + } + public final class Configuration implements java.lang.Comparable android.os.Parcelable { ctor public Configuration(); ctor public Configuration(android.content.res.Configuration); @@ -10468,6 +10478,11 @@ package android.content.res { field public int uiMode; } + public class GradientColor extends android.content.res.ComplexColor { + method public static android.content.res.GradientColor createFromXml(android.content.res.Resources, android.content.res.XmlResourceParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public int getDefaultColor(); + } + public class ObbInfo implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); @@ -10527,6 +10542,7 @@ package android.content.res { method public void getValue(java.lang.String, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException; method public void getValueForDensity(int, int, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException; method public android.content.res.XmlResourceParser getXml(int) throws android.content.res.Resources.NotFoundException; + method public android.content.res.ComplexColor loadComplexColor(android.util.TypedValue, int, android.content.res.Resources.Theme); method public final android.content.res.Resources.Theme newTheme(); method public android.content.res.TypedArray obtainAttributes(android.util.AttributeSet, int[]); method public android.content.res.TypedArray obtainTypedArray(int) throws android.content.res.Resources.NotFoundException; @@ -10562,6 +10578,7 @@ package android.content.res { method public int getChangingConfigurations(); method public int getColor(int, int); method public android.content.res.ColorStateList getColorStateList(int); + method public android.content.res.ComplexColor getComplexColor(int); method public float getDimension(int, float); method public int getDimensionPixelOffset(int, int); method public int getDimensionPixelSize(int, int); diff --git a/api/test-current.txt b/api/test-current.txt index c076ad6e20e7..8fc63fe2c783 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -506,6 +506,8 @@ package android { field public static final int encryptionAware = 16844038; // 0x1010506 field public static final int end = 16843996; // 0x10104dc field public static final int endColor = 16843166; // 0x101019e + field public static final int endX = 16844051; // 0x1010513 + field public static final int endY = 16844052; // 0x1010514 field public static final deprecated int endYear = 16843133; // 0x101017d field public static final int enterFadeDuration = 16843532; // 0x101030c field public static final int entries = 16842930; // 0x10100b2 @@ -881,6 +883,7 @@ package android { field public static final int numbersTextColor = 16843937; // 0x10104a1 field public static final deprecated int numeric = 16843109; // 0x1010165 field public static final int numericShortcut = 16843236; // 0x10101e4 + field public static final int offset = 16844053; // 0x1010515 field public static final int onClick = 16843375; // 0x101026f field public static final int oneshot = 16843159; // 0x1010197 field public static final int opacity = 16843550; // 0x101031e @@ -1128,6 +1131,8 @@ package android { field public static final int startColor = 16843165; // 0x101019d field public static final int startDelay = 16843746; // 0x10103e2 field public static final int startOffset = 16843198; // 0x10101be + field public static final int startX = 16844049; // 0x1010511 + field public static final int startY = 16844050; // 0x1010512 field public static final deprecated int startYear = 16843132; // 0x101017c field public static final int stateListAnimator = 16843848; // 0x1010448 field public static final int stateNotNeeded = 16842774; // 0x1010016 @@ -9957,7 +9962,7 @@ package android.content.res { method public final long skip(long) throws java.io.IOException; } - public class ColorStateList implements android.os.Parcelable { + public class ColorStateList extends android.content.res.ComplexColor implements android.os.Parcelable { ctor public ColorStateList(int[][], int[]); method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; @@ -9966,13 +9971,18 @@ package android.content.res { method public int getColorForState(int[], int); method public int getDefaultColor(); method public boolean isOpaque(); - method public boolean isStateful(); method public static android.content.res.ColorStateList valueOf(int); method public android.content.res.ColorStateList withAlpha(int); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.content.res.ColorStateList> CREATOR; } + public abstract class ComplexColor { + ctor public ComplexColor(); + method public abstract int getDefaultColor(); + method public boolean isStateful(); + } + public final class Configuration implements java.lang.Comparable android.os.Parcelable { ctor public Configuration(); ctor public Configuration(android.content.res.Configuration); @@ -10076,6 +10086,11 @@ package android.content.res { field public int uiMode; } + public class GradientColor extends android.content.res.ComplexColor { + method public static android.content.res.GradientColor createFromXml(android.content.res.Resources, android.content.res.XmlResourceParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public int getDefaultColor(); + } + public class ObbInfo implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); @@ -10135,6 +10150,7 @@ package android.content.res { method public void getValue(java.lang.String, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException; method public void getValueForDensity(int, int, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException; method public android.content.res.XmlResourceParser getXml(int) throws android.content.res.Resources.NotFoundException; + method public android.content.res.ComplexColor loadComplexColor(android.util.TypedValue, int, android.content.res.Resources.Theme); method public final android.content.res.Resources.Theme newTheme(); method public android.content.res.TypedArray obtainAttributes(android.util.AttributeSet, int[]); method public android.content.res.TypedArray obtainTypedArray(int) throws android.content.res.Resources.NotFoundException; @@ -10170,6 +10186,7 @@ package android.content.res { method public int getChangingConfigurations(); method public int getColor(int, int); method public android.content.res.ColorStateList getColorStateList(int); + method public android.content.res.ComplexColor getComplexColor(int); method public float getDimension(int, float); method public int getDimensionPixelOffset(int, int); method public int getDimensionPixelSize(int, int); diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java index 19921b548aac..9e1b312c8372 100644 --- a/core/java/android/content/res/ColorStateList.java +++ b/core/java/android/content/res/ColorStateList.java @@ -69,7 +69,7 @@ import java.util.Arrays; * href="{@docRoot}guide/topics/resources/color-list-resource.html">Color State * List Resource</a>.</p> */ -public class ColorStateList implements Parcelable { +public class ColorStateList extends ComplexColor implements Parcelable { private static final String TAG = "ColorStateList"; private static final int DEFAULT_COLOR = Color.RED; @@ -209,7 +209,7 @@ public class ColorStateList implements Parcelable { * @return A new color state list for the current tag. */ @NonNull - private static ColorStateList createFromXmlInner(@NonNull Resources r, + static ColorStateList createFromXmlInner(@NonNull Resources r, @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme) throws XmlPullParserException, IOException { final String name = parser.getName(); @@ -340,6 +340,7 @@ public class ColorStateList implements Parcelable { * @return whether a theme can be applied to this color state list * @hide only for resource preloading */ + @Override public boolean canApplyTheme() { return mThemeAttrs != null; } @@ -419,6 +420,7 @@ public class ColorStateList implements Parcelable { * attributes * @hide only for resource preloading */ + @Override public ColorStateList obtainForTheme(Theme t) { if (t == null || !canApplyTheme()) { return this; @@ -460,6 +462,7 @@ public class ColorStateList implements Parcelable { * otherwise. * @see #getColorForState(int[], int) */ + @Override public boolean isStateful() { return mStateSpecs.length > 1; } @@ -602,14 +605,14 @@ public class ColorStateList implements Parcelable { * @return a factory that can create new instances of this ColorStateList * @hide only for resource preloading */ - public ConstantState<ColorStateList> getConstantState() { + public ConstantState<ComplexColor> getConstantState() { if (mFactory == null) { mFactory = new ColorStateListFactory(this); } return mFactory; } - private static class ColorStateListFactory extends ConstantState<ColorStateList> { + private static class ColorStateListFactory extends ConstantState<ComplexColor> { private final ColorStateList mSrc; public ColorStateListFactory(ColorStateList src) { @@ -628,7 +631,7 @@ public class ColorStateList implements Parcelable { @Override public ColorStateList newInstance(Resources res, Theme theme) { - return mSrc.obtainForTheme(theme); + return (ColorStateList) mSrc.obtainForTheme(theme); } } diff --git a/core/java/android/content/res/ComplexColor.java b/core/java/android/content/res/ComplexColor.java new file mode 100644 index 000000000000..d96ec62749f0 --- /dev/null +++ b/core/java/android/content/res/ComplexColor.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 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.content.res; + +import android.annotation.ColorInt; +import android.content.res.Resources.Theme; +import android.graphics.Color; + +/** + * Defines an abstract class for the complex color information, like + * {@link android.content.res.ColorStateList} or {@link android.content.res.GradientColor} + */ +public abstract class ComplexColor { + /** + * @return {@code true} if this ComplexColor changes color based on state, {@code false} + * otherwise. + */ + public boolean isStateful() { return false; } + + /** + * @return the default color. + */ + @ColorInt + public abstract int getDefaultColor(); + + /** + * @hide only for resource preloading + * + */ + public abstract ConstantState<ComplexColor> getConstantState(); + + /** + * @hide only for resource preloading + */ + public abstract boolean canApplyTheme(); + + /** + * @hide only for resource preloading + */ + public abstract ComplexColor obtainForTheme(Theme t); +} diff --git a/core/java/android/content/res/GradientColor.java b/core/java/android/content/res/GradientColor.java new file mode 100644 index 000000000000..98ef2eaa5e6d --- /dev/null +++ b/core/java/android/content/res/GradientColor.java @@ -0,0 +1,523 @@ +/* + * Copyright (C) 2016 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.content.res; + +import android.annotation.ColorInt; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.res.Resources.Theme; + +import com.android.internal.R; +import com.android.internal.util.GrowingArrayUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.graphics.LinearGradient; +import android.graphics.RadialGradient; +import android.graphics.Shader; +import android.graphics.SweepGradient; +import android.graphics.drawable.GradientDrawable; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Xml; + +import java.io.IOException; + + +public class GradientColor extends ComplexColor { + private static final String TAG = "GradientColor"; + + private static final boolean DBG_GRADIENT = false; + + /** Lazily-created factory for this GradientColor. */ + private GradientColorFactory mFactory; + + private int mChangingConfigurations; + private int mDefaultColor; + + // After parsing all the attributes from XML, this shader is the ultimate result containing + // all the XML information. + private Shader mShader = null; + + // Below are the attributes at the root element <gradient> + private int mGradientType = GradientDrawable.LINEAR_GRADIENT; + + private float mCenterX = 0f; + private float mCenterY = 0f; + + private float mStartX = 0f; + private float mStartY = 0f; + private float mEndX = 0f; + private float mEndY = 0f; + + private int mStartColor = 0; + private int mCenterColor = 0; + private int mEndColor = 0; + private boolean mHasCenterColor = false; + + private float mGradientRadius = 0f; + + // Below are the attributes for the <item> element. + private int[] mItemColors; + private float[] mItemOffsets; + + // Theme attributes for the root and item elements. + private int[] mThemeAttrs; + private int[][] mItemsThemeAttrs; + + private GradientColor() { + } + + private GradientColor(GradientColor copy) { + if (copy != null) { + mChangingConfigurations = copy.mChangingConfigurations; + mDefaultColor = copy.mDefaultColor; + mShader = copy.mShader; + mGradientType = copy.mGradientType; + mCenterX = copy.mCenterX; + mCenterY = copy.mCenterY; + mStartX = copy.mStartX; + mStartY = copy.mStartY; + mEndX = copy.mEndX; + mEndY = copy.mEndY; + mStartColor = copy.mStartColor; + mCenterColor = copy.mCenterColor; + mEndColor = copy.mEndColor; + mHasCenterColor = copy.mHasCenterColor; + mGradientRadius = copy.mGradientRadius; + + if (copy.mItemColors != null) { + mItemColors = copy.mItemColors.clone(); + } + if (copy.mItemOffsets != null) { + mItemOffsets = copy.mItemOffsets.clone(); + } + + if (copy.mThemeAttrs != null) { + mThemeAttrs = copy.mThemeAttrs.clone(); + } + if (copy.mItemsThemeAttrs != null) { + mItemsThemeAttrs = copy.mItemsThemeAttrs.clone(); + } + } + } + + /** + * Update the root level's attributes, either for inflate or applyTheme. + */ + private void updateRootElementState(TypedArray a) { + // Extract the theme attributes, if any. + mThemeAttrs = a.extractThemeAttrs(); + + mStartX = a.getFloat( + R.styleable.GradientColor_startX, mStartX); + mStartY = a.getFloat( + R.styleable.GradientColor_startY, mStartY); + mEndX = a.getFloat( + R.styleable.GradientColor_endX, mEndX); + mEndY = a.getFloat( + R.styleable.GradientColor_endY, mEndY); + + mCenterX = a.getFloat( + R.styleable.GradientColor_centerX, mCenterX); + mCenterY = a.getFloat( + R.styleable.GradientColor_centerY, mCenterY); + + mGradientType = a.getInt( + R.styleable.GradientColor_type, mGradientType); + + mStartColor = a.getColor( + R.styleable.GradientColor_startColor, mStartColor); + mHasCenterColor |= a.hasValue( + R.styleable.GradientColor_centerColor); + mCenterColor = a.getColor( + R.styleable.GradientColor_centerColor, mCenterColor); + mEndColor = a.getColor( + R.styleable.GradientColor_endColor, mEndColor); + + if (DBG_GRADIENT) { + Log.v(TAG, "hasCenterColor is " + mHasCenterColor); + if (mHasCenterColor) { + Log.v(TAG, "centerColor:" + mCenterColor); + } + Log.v(TAG, "startColor: " + mStartColor); + Log.v(TAG, "endColor: " + mEndColor); + } + + mGradientRadius = a.getFloat(R.styleable.GradientColor_gradientRadius, + mGradientRadius); + } + + /** + * Check if the XML content is valid. + * + * @throws XmlPullParserException if errors were found. + */ + private void validateXmlContent() throws XmlPullParserException { + if (mGradientRadius <= 0 + && mGradientType == GradientDrawable.RADIAL_GRADIENT) { + throw new XmlPullParserException( + "<gradient> tag requires 'gradientRadius' " + + "attribute with radial type"); + } + } + + /** + * The shader information will be applied to the native VectorDrawable's path. + * @hide + */ + public Shader getShader() { + return mShader; + } + + /** + * A public method to create GradientColor from a XML resource. + */ + public static GradientColor createFromXml(Resources r, XmlResourceParser parser, Theme theme) + throws XmlPullParserException, IOException { + final AttributeSet attrs = Xml.asAttributeSet(parser); + + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + // Seek parser to start tag. + } + + if (type != XmlPullParser.START_TAG) { + throw new XmlPullParserException("No start tag found"); + } + + return createFromXmlInner(r, parser, attrs, theme); + } + + /** + * Create from inside an XML document. Called on a parser positioned at a + * tag in an XML document, tries to create a GradientColor from that tag. + * + * @return A new GradientColor for the current tag. + * @throws XmlPullParserException if the current tag is not <gradient> + */ + @NonNull + static GradientColor createFromXmlInner(@NonNull Resources r, + @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme) + throws XmlPullParserException, IOException { + final String name = parser.getName(); + if (!name.equals("gradient")) { + throw new XmlPullParserException( + parser.getPositionDescription() + ": invalid gradient color tag " + name); + } + + final GradientColor gradientColor = new GradientColor(); + gradientColor.inflate(r, parser, attrs, theme); + return gradientColor; + } + + /** + * Fill in this object based on the contents of an XML "gradient" element. + */ + private void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, + @NonNull AttributeSet attrs, @Nullable Theme theme) + throws XmlPullParserException, IOException { + final TypedArray a = Resources.obtainAttributes(r, theme, attrs, R.styleable.GradientColor); + updateRootElementState(a); + mChangingConfigurations |= a.getChangingConfigurations(); + a.recycle(); + + // Check correctness and throw exception if errors found. + validateXmlContent(); + + inflateChildElements(r, parser, attrs, theme); + + onColorsChange(); + } + + /** + * Inflates child elements "item"s for each color stop. + * + * Note that at root level, we need to save ThemeAttrs for theme applied later. + * Here similarly, at each child item, we need to save the theme's attributes, and apply theme + * later as applyItemsAttrsTheme(). + */ + private void inflateChildElements(@NonNull Resources r, @NonNull XmlPullParser parser, + @NonNull AttributeSet attrs, @NonNull Theme theme) + throws XmlPullParserException, IOException { + final int innerDepth = parser.getDepth() + 1; + int type; + int depth; + + // Pre-allocate the array with some size, for better performance. + float[] offsetList = new float[20]; + int[] colorList = new int[offsetList.length]; + int[][] themeAttrsList = new int[offsetList.length][]; + + int listSize = 0; + boolean hasUnresolvedAttrs = false; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth + || type != XmlPullParser.END_TAG)) { + if (type != XmlPullParser.START_TAG) { + continue; + } + if (depth > innerDepth || !parser.getName().equals("item")) { + continue; + } + + final TypedArray a = Resources.obtainAttributes(r, theme, attrs, + R.styleable.GradientColorItem); + boolean hasColor = a.hasValue(R.styleable.GradientColorItem_color); + boolean hasOffset = a.hasValue(R.styleable.GradientColorItem_offset); + if (!hasColor || !hasOffset) { + throw new XmlPullParserException( + parser.getPositionDescription() + + ": <item> tag requires a 'color' attribute and a 'offset' " + + "attribute!"); + } + + final int[] themeAttrs = a.extractThemeAttrs(); + int color = a.getColor(R.styleable.GradientColorItem_color, 0); + float offset = a.getFloat(R.styleable.GradientColorItem_offset, 0); + + if (DBG_GRADIENT) { + Log.v(TAG, "new item color " + color + " " + Integer.toHexString(color)); + Log.v(TAG, "offset" + offset); + } + mChangingConfigurations |= a.getChangingConfigurations(); + a.recycle(); + + if (themeAttrs != null) { + hasUnresolvedAttrs = true; + } + + colorList = GrowingArrayUtils.append(colorList, listSize, color); + offsetList = GrowingArrayUtils.append(offsetList, listSize, offset); + themeAttrsList = GrowingArrayUtils.append(themeAttrsList, listSize, themeAttrs); + listSize++; + } + if (listSize > 0) { + if (hasUnresolvedAttrs) { + mItemsThemeAttrs = new int[listSize][]; + System.arraycopy(themeAttrsList, 0, mItemsThemeAttrs, 0, listSize); + } else { + mItemsThemeAttrs = null; + } + + mItemColors = new int[listSize]; + mItemOffsets = new float[listSize]; + System.arraycopy(colorList, 0, mItemColors, 0, listSize); + System.arraycopy(offsetList, 0, mItemOffsets, 0, listSize); + } + } + + /** + * Apply theme to all the items. + */ + private void applyItemsAttrsTheme(Theme t) { + if (mItemsThemeAttrs == null) { + return; + } + + boolean hasUnresolvedAttrs = false; + + final int[][] themeAttrsList = mItemsThemeAttrs; + final int N = themeAttrsList.length; + for (int i = 0; i < N; i++) { + if (themeAttrsList[i] != null) { + final TypedArray a = t.resolveAttributes(themeAttrsList[i], + R.styleable.GradientColorItem); + + // Extract the theme attributes, if any, before attempting to + // read from the typed array. This prevents a crash if we have + // unresolved attrs. + themeAttrsList[i] = a.extractThemeAttrs(themeAttrsList[i]); + if (themeAttrsList[i] != null) { + hasUnresolvedAttrs = true; + } + + mItemColors[i] = a.getColor(R.styleable.GradientColorItem_color, mItemColors[i]); + mItemOffsets[i] = a.getFloat(R.styleable.GradientColorItem_offset, mItemOffsets[i]); + if (DBG_GRADIENT) { + Log.v(TAG, "applyItemsAttrsTheme Colors[i] " + i + " " + + Integer.toHexString(mItemColors[i])); + Log.v(TAG, "Offsets[i] " + i + " " + mItemOffsets[i]); + } + + // Account for any configuration changes. + mChangingConfigurations |= a.getChangingConfigurations(); + + a.recycle(); + } + } + + if (!hasUnresolvedAttrs) { + mItemsThemeAttrs = null; + } + } + + private void onColorsChange() { + int[] tempColors = null; + float[] tempOffsets = null; + + if (mItemColors != null) { + int length = mItemColors.length; + tempColors = new int[length]; + tempOffsets = new float[length]; + + for (int i = 0; i < length; i++) { + tempColors[i] = mItemColors[i]; + tempOffsets[i] = mItemOffsets[i]; + } + } else { + if (mHasCenterColor) { + tempColors = new int[3]; + tempColors[0] = mStartColor; + tempColors[1] = mCenterColor; + tempColors[2] = mEndColor; + + tempOffsets = new float[3]; + tempOffsets[0] = 0.0f; + // Since 0.5f is default value, try to take the one that isn't 0.5f + tempOffsets[1] = 0.5f; + tempOffsets[2] = 1f; + } else { + tempColors = new int[2]; + tempColors[0] = mStartColor; + tempColors[1] = mEndColor; + } + } + if (tempColors.length < 2) { + Log.w(TAG, "<gradient> tag requires 2 color values specified!" + tempColors.length + + " " + tempColors); + } + + if (mGradientType == GradientDrawable.LINEAR_GRADIENT) { + mShader = new LinearGradient(mStartX, mStartY, mEndX, mEndY, tempColors, tempOffsets, + Shader.TileMode.CLAMP); + } else { + if (mGradientType == GradientDrawable.RADIAL_GRADIENT) { + mShader = new RadialGradient(mCenterX, mCenterY, mGradientRadius, tempColors, + tempOffsets, Shader.TileMode.CLAMP); + } else { + mShader = new SweepGradient(mCenterX, mCenterY, tempColors, tempOffsets); + } + } + mDefaultColor = tempColors[0]; + } + + /** + * For Gradient color, the default color is not very useful, since the gradient will override + * the color information anyway. + */ + @Override + @ColorInt + public int getDefaultColor() { + return mDefaultColor; + } + + /** + * Similar to ColorStateList, setup constant state and its factory. + * @hide only for resource preloading + */ + @Override + public ConstantState<ComplexColor> getConstantState() { + if (mFactory == null) { + mFactory = new GradientColorFactory(this); + } + return mFactory; + } + + private static class GradientColorFactory extends ConstantState<ComplexColor> { + private final GradientColor mSrc; + + public GradientColorFactory(GradientColor src) { + mSrc = src; + } + + @Override + public int getChangingConfigurations() { + return mSrc.mChangingConfigurations; + } + + @Override + public GradientColor newInstance() { + return mSrc; + } + + @Override + public GradientColor newInstance(Resources res, Theme theme) { + return mSrc.obtainForTheme(theme); + } + } + + /** + * Returns an appropriately themed gradient color. + * + * @param t the theme to apply + * @return a copy of the gradient color the theme applied, or the + * gradient itself if there were no unresolved theme + * attributes + * @hide only for resource preloading + */ + @Override + public GradientColor obtainForTheme(Theme t) { + if (t == null || !canApplyTheme()) { + return this; + } + + final GradientColor clone = new GradientColor(this); + clone.applyTheme(t); + return clone; + } + + private void applyTheme(Theme t) { + if (mThemeAttrs != null) { + applyRootAttrsTheme(t); + } + if (mItemsThemeAttrs != null) { + applyItemsAttrsTheme(t); + } + onColorsChange(); + } + + private void applyRootAttrsTheme(Theme t) { + final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.GradientColor); + // mThemeAttrs will be set to null if if there are no theme attributes in the + // typed array. + mThemeAttrs = a.extractThemeAttrs(mThemeAttrs); + // merging the attributes update inside the updateRootElementState(). + updateRootElementState(a); + + // Account for any configuration changes. + mChangingConfigurations |= a.getChangingConfigurations(); + a.recycle(); + } + + + /** + * Returns whether a theme can be applied to this gradient color, which + * usually indicates that the gradient color has unresolved theme + * attributes. + * + * @return whether a theme can be applied to this gradient color. + * @hide only for resource preloading + */ + @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || mItemsThemeAttrs != null; + } + +} diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index e4044296dac4..4967d05e2727 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -56,6 +56,7 @@ import android.util.LongSparseArray; import android.util.Pools.SynchronizedPool; import android.util.Slog; import android.util.TypedValue; +import android.util.Xml; import android.view.ViewDebug; import android.view.ViewHierarchyEncoder; @@ -115,8 +116,8 @@ public class Resources { private static final LongSparseArray<ConstantState>[] sPreloadedDrawables; private static final LongSparseArray<ConstantState> sPreloadedColorDrawables = new LongSparseArray<>(); - private static final LongSparseArray<android.content.res.ConstantState<ColorStateList>> - sPreloadedColorStateLists = new LongSparseArray<>(); + private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>> + sPreloadedComplexColors = new LongSparseArray<>(); // Pool of TypedArrays targeted to this Resources object. final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5); @@ -133,7 +134,7 @@ public class Resources { private final Configuration mTmpConfig = new Configuration(); private final DrawableCache mDrawableCache = new DrawableCache(this); private final DrawableCache mColorDrawableCache = new DrawableCache(this); - private final ConfigurationBoundResourceCache<ColorStateList> mColorStateListCache = + private final ConfigurationBoundResourceCache<ComplexColor> mComplexColorCache = new ConfigurationBoundResourceCache<>(this); private final ConfigurationBoundResourceCache<Animator> mAnimatorCache = new ConfigurationBoundResourceCache<>(this); @@ -1987,7 +1988,7 @@ public class Resources { mDrawableCache.onConfigurationChange(configChanges); mColorDrawableCache.onConfigurationChange(configChanges); - mColorStateListCache.onConfigurationChange(configChanges); + mComplexColorCache.onConfigurationChange(configChanges); mAnimatorCache.onConfigurationChange(configChanges); mStateListAnimatorCache.onConfigurationChange(configChanges); @@ -2613,76 +2614,146 @@ public class Resources { return dr; } + /** + * Given the value and id, we can get the XML filename as in value.data, based on that, we + * first try to load CSL from the cache. If not found, try to get from the constant state. + * Last, parse the XML and generate the CSL. + */ + private ComplexColor loadComplexColorFromName(Theme theme, TypedValue value, int id) { + final long key = (((long) value.assetCookie) << 32) | value.data; + final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache; + ComplexColor complexColor = cache.getInstance(key, theme); + if (complexColor != null) { + return complexColor; + } + + final android.content.res.ConstantState<ComplexColor> factory = + sPreloadedComplexColors.get(key); + + if (factory != null) { + complexColor = factory.newInstance(this, theme); + } + if (complexColor == null) { + complexColor = loadComplexColorForCookie(value, id, theme); + } + + if (complexColor != null) { + if (mPreloading) { + if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId, + "color")) { + sPreloadedComplexColors.put(key, complexColor.getConstantState()); + } + } else { + cache.put(key, theme, complexColor.getConstantState()); + } + } + return complexColor; + } + @Nullable - ColorStateList loadColorStateList(TypedValue value, int id, Theme theme) - throws NotFoundException { + public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, Theme theme) { if (TRACE_FOR_PRELOAD) { // Log only framework resources if ((id >>> 24) == 0x1) { final String name = getResourceName(id); - if (name != null) android.util.Log.d("PreloadColorStateList", name); + if (name != null) android.util.Log.d("loadComplexColor", name); } } final long key = (((long) value.assetCookie) << 32) | value.data; - ColorStateList csl; - // Handle inline color definitions. if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT) { - final android.content.res.ConstantState<ColorStateList> factory = - sPreloadedColorStateLists.get(key); - if (factory != null) { - return factory.newInstance(); + return getColorStateListFromInt(value, key); + } + + final String file = value.string.toString(); + + ComplexColor complexColor; + if (file.endsWith(".xml")) { + try { + complexColor = loadComplexColorFromName(theme, value, id); + } catch (Exception e) { + final NotFoundException rnf = new NotFoundException( + "File " + file + " from complex color resource ID #0x" + + Integer.toHexString(id)); + rnf.initCause(e); + throw rnf; } + } else { + throw new NotFoundException( + "File " + file + " from drawable resource ID #0x" + + Integer.toHexString(id) + ": .xml extension required"); + } - csl = ColorStateList.valueOf(value.data); + return complexColor; + } - if (mPreloading) { - if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId, - "color")) { - sPreloadedColorStateLists.put(key, csl.getConstantState()); - } + @Nullable + ColorStateList loadColorStateList(TypedValue value, int id, Theme theme) + throws NotFoundException { + if (TRACE_FOR_PRELOAD) { + // Log only framework resources + if ((id >>> 24) == 0x1) { + final String name = getResourceName(id); + if (name != null) android.util.Log.d("PreloadColorStateList", name); } + } - return csl; + final long key = (((long) value.assetCookie) << 32) | value.data; + + // Handle inline color definitions. + if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT + && value.type <= TypedValue.TYPE_LAST_COLOR_INT) { + return getColorStateListFromInt(value, key); } - final ConfigurationBoundResourceCache<ColorStateList> cache = mColorStateListCache; - csl = cache.getInstance(key, theme); - if (csl != null) { - return csl; + ComplexColor complexColor = loadComplexColorFromName(theme, value, id); + if (complexColor != null && complexColor instanceof ColorStateList) { + return (ColorStateList) complexColor; } - final android.content.res.ConstantState<ColorStateList> factory = - sPreloadedColorStateLists.get(key); + throw new NotFoundException( + "Can't find ColorStateList from drawable resource ID #0x" + + Integer.toHexString(id)); + } + + @NonNull + private ColorStateList getColorStateListFromInt(@NonNull TypedValue value, long key) { + ColorStateList csl; + final android.content.res.ConstantState<ComplexColor> factory = + sPreloadedComplexColors.get(key); if (factory != null) { - csl = factory.newInstance(this, theme); + return (ColorStateList) factory.newInstance(); } - if (csl == null) { - csl = loadColorStateListForCookie(value, id, theme); - } + csl = ColorStateList.valueOf(value.data); - if (csl != null) { - if (mPreloading) { - if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId, - "color")) { - sPreloadedColorStateLists.put(key, csl.getConstantState()); - } - } else { - cache.put(key, theme, csl.getConstantState()); + if (mPreloading) { + if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId, + "color")) { + sPreloadedComplexColors.put(key, csl.getConstantState()); } } return csl; } - private ColorStateList loadColorStateListForCookie(TypedValue value, int id, Theme theme) { + /** + * Load a ComplexColor based on the XML file content. The result can be a GradientColor or + * ColorStateList. Note that pure color will be wrapped into a ColorStateList. + * + * We deferred the parser creation to this function b/c we need to differentiate b/t gradient + * and selector tag. + * + * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content. + */ + @Nullable + private ComplexColor loadComplexColorForCookie(TypedValue value, int id, Theme theme) { if (value.string == null) { throw new UnsupportedOperationException( - "Can't convert to color state list: type=0x" + value.type); + "Can't convert to ComplexColor: type=0x" + value.type); } final String file = value.string.toString(); @@ -2692,29 +2763,45 @@ public class Resources { if ((id >>> 24) == 0x1) { final String name = getResourceName(id); if (name != null) { - Log.d(TAG, "Loading framework color state list #" + Integer.toHexString(id) + Log.d(TAG, "Loading framework ComplexColor #" + Integer.toHexString(id) + ": " + name + " at " + file); } } } if (DEBUG_LOAD) { - Log.v(TAG, "Loading color state list for cookie " + value.assetCookie + ": " + file); + Log.v(TAG, "Loading ComplexColor for cookie " + value.assetCookie + ": " + file); } - final ColorStateList csl; + ComplexColor complexColor = null; Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file); if (file.endsWith(".xml")) { try { - final XmlResourceParser rp = loadXmlResourceParser( - file, id, value.assetCookie, "colorstatelist"); - csl = ColorStateList.createFromXml(this, rp, theme); - rp.close(); + final XmlResourceParser parser = loadXmlResourceParser( + file, id, value.assetCookie, "ComplexColor"); + + final AttributeSet attrs = Xml.asAttributeSet(parser); + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + // Seek parser to start tag. + } + if (type != XmlPullParser.START_TAG) { + throw new XmlPullParserException("No start tag found"); + } + + final String name = parser.getName(); + if (name.equals("gradient")) { + complexColor = GradientColor.createFromXmlInner(this, parser, attrs, theme); + } else if (name.equals("selector")) { + complexColor = ColorStateList.createFromXmlInner(this, parser, attrs, theme); + } + parser.close(); } catch (Exception e) { Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); final NotFoundException rnf = new NotFoundException( - "File " + file + " from color state list resource ID #0x" + "File " + file + " from ComplexColor resource ID #0x" + Integer.toHexString(id)); rnf.initCause(e); throw rnf; @@ -2727,7 +2814,7 @@ public class Resources { } Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); - return csl; + return complexColor; } /** diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index cc65e1e4f710..6067577453c9 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -454,6 +454,39 @@ public class TypedArray { } /** + * Retrieve the ComplexColor for the attribute at <var>index</var>. + * The value may be either a {@link android.content.res.ColorStateList} which can wrap a simple + * color value or a {@link android.content.res.GradientColor} + * <p> + * This method will return {@code null} if the attribute is not defined or + * is not an integer color, color state list or GradientColor. + * + * @param index Index of attribute to retrieve. + * + * @return ComplexColor for the attribute, or {@code null} if not defined. + * @throws RuntimeException if the attribute if the TypedArray has already + * been recycled. + * @throws UnsupportedOperationException if the attribute is defined but is + * not an integer color, color state list or GradientColor. + */ + @Nullable + public ComplexColor getComplexColor(@StyleableRes int index) { + if (mRecycled) { + throw new RuntimeException("Cannot make calls to a recycled instance!"); + } + + final TypedValue value = mValue; + if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { + if (value.type == TypedValue.TYPE_ATTRIBUTE) { + throw new UnsupportedOperationException( + "Failed to resolve attribute at index " + index + ": " + value); + } + return mResources.loadComplexColor(value, value.resourceId, mTheme); + } + return null; + } + + /** * Retrieve the ColorStateList for the attribute at <var>index</var>. * The value may be either a single solid color or a reference to * a color or complex {@link android.content.res.ColorStateList} diff --git a/core/java/com/android/internal/util/GrowingArrayUtils.java b/core/java/com/android/internal/util/GrowingArrayUtils.java index b4d2d73066dd..968d9204b106 100644 --- a/core/java/com/android/internal/util/GrowingArrayUtils.java +++ b/core/java/com/android/internal/util/GrowingArrayUtils.java @@ -97,6 +97,21 @@ public final class GrowingArrayUtils { } /** + * Primitive float version of {@link #append(Object[], int, Object)}. + */ + public static float[] append(float[] array, int currentSize, float element) { + assert currentSize <= array.length; + + if (currentSize + 1 > array.length) { + float[] newArray = ArrayUtils.newUnpaddedFloatArray(growSize(currentSize)); + System.arraycopy(array, 0, newArray, 0, currentSize); + array = newArray; + } + array[currentSize] = element; + return array; + } + + /** * Inserts an element into the array at the specified index, growing the array if there is no * more room. * diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp index 53d4c6a1cb78..563ec8bd9834 100644 --- a/core/jni/android_graphics_drawable_VectorDrawable.cpp +++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp @@ -90,6 +90,18 @@ static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong full strokeLineJoin); } +static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) { + VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr); + SkShader* fillShader = reinterpret_cast<SkShader*>(fillGradientPtr); + path->setFillGradient(fillShader); +} + +static void updateFullPathStrokeGradient(JNIEnv*, jobject, jlong pathPtr, jlong strokeGradientPtr) { + VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr); + SkShader* strokeShader = reinterpret_cast<SkShader*>(strokeGradientPtr); + path->setStrokeGradient(strokeShader); +} + static jboolean getFullPathProperties(JNIEnv* env, jobject, jlong fullPathPtr, jbyteArray outProperties, jint length) { VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr); @@ -331,6 +343,8 @@ static const JNINativeMethod gMethods[] = { {"nCreateFullPath", "!()J", (void*)createEmptyFullPath}, {"nCreateFullPath", "!(J)J", (void*)createFullPath}, {"nUpdateFullPathProperties", "!(JFIFIFFFFFII)V", (void*)updateFullPathPropertiesAndStrokeStyles}, + {"nUpdateFullPathFillGradient", "!(JJ)V", (void*)updateFullPathFillGradient}, + {"nUpdateFullPathStrokeGradient", "!(JJ)V", (void*)updateFullPathStrokeGradient}, {"nGetFullPathProperties", "(J[BI)Z", (void*)getFullPathProperties}, {"nGetGroupProperties", "(J[FI)Z", (void*)getGroupProperties}, diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 713038b60d89..1f7206eeecee 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3727,7 +3727,7 @@ i <!-- Controls how the image should be resized or moved to match the size of this ImageView. See {@link android.widget.ImageView.ScaleType} --> <attr name="scaleType"> - <!-- Scale using the image matrix when drawing. See + <!-- Scale using the image matrix when drawing. See {@link android.widget.ImageView#setImageMatrix(Matrix)}. --> <enum name="matrix" value="0" /> <!-- Scale the image using {@link android.graphics.Matrix.ScaleToFit#FILL}. --> @@ -3740,7 +3740,7 @@ i <enum name="fitEnd" value="4" /> <!-- Center the image in the view, but perform no scaling. --> <enum name="center" value="5" /> - <!-- Scale the image uniformly (maintain the image's aspect ratio) so both dimensions + <!-- Scale the image uniformly (maintain the image's aspect ratio) so both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding). The image is then centered in the view. --> <enum name="centerCrop" value="6" /> @@ -8135,4 +8135,52 @@ i <attr name="entries" /> <attr name="entryValues" /> </declare-styleable> + + <!-- Used to describe the gradient for fill or stroke in a path of VectorDrawable. --> + <declare-styleable name="GradientColor"> + <!-- Start color of the gradient. --> + <attr name="startColor" /> + <!-- Optional center color. --> + <attr name="centerColor" /> + <!-- End color of the gradient. --> + <attr name="endColor" /> + <!-- Type of gradient. The default type is linear. --> + <attr name="type" /> + + <!-- Only applied to RadialGradient--> + <!-- Radius of the gradient, used only with radial gradient. --> + <attr name="gradientRadius" /> + + <!-- Only applied to SweepGradient / RadialGradient--> + <!-- X coordinate of the center of the gradient within the path. --> + <attr name="centerX" /> + <!-- Y coordinate of the center of the gradient within the path. --> + <attr name="centerY" /> + + <!-- LinearGradient specific --> + <!-- X coordinate of the start point origin of the gradient. + Defined in same coordinates as the path itself --> + <attr name="startX" format="float" /> + <!-- Y coordinate of the start point of the gradient within the shape. + Defined in same coordinates as the path itself --> + <attr name="startY" format="float" /> + <!-- X coordinate of the end point origin of the gradient. + Defined in same coordinates as the path itself --> + <attr name="endX" format="float" /> + <!-- Y coordinate of the end point of the gradient within the shape. + Defined in same coordinates as the path itself --> + <attr name="endY" format="float" /> + + </declare-styleable> + + <!-- Describes an item of a GradientColor. Minimally need 2 items to define the gradient + Colors defined in <item> override the simple color attributes such as + "startColor / centerColor / endColor" are ignored --> + <declare-styleable name="GradientColorItem"> + <!-- The offset (or ratio) of this current color item inside the gradient. + The value is only meaningful when it is between 0 and 1. --> + <attr name="offset" format="float" /> + <!-- The current color for the offset inside the gradient. --> + <attr name="color" /> + </declare-styleable> </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 57132ea82977..a2ad09b248c3 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2691,6 +2691,11 @@ <public type="attr" name="canPerformGestures" /> <public type="attr" name="externalService" /> <public type="attr" name="supportsLocalInteraction" /> + <public type="attr" name="startX" /> + <public type="attr" name="startY" /> + <public type="attr" name="endX" /> + <public type="attr" name="endY" /> + <public type="attr" name="offset" /> <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" /> <public type="style" name="Widget.Material.SeekBar.Discrete" /> diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java index adb282fb4bf9..94983b3d1f51 100644 --- a/graphics/java/android/graphics/Shader.java +++ b/graphics/java/android/graphics/Shader.java @@ -117,7 +117,10 @@ public class Shader { } } - /* package */ long getNativeInstance() { + /** + * @hide + */ + public long getNativeInstance() { return native_instance; } diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index 65260210042c..1fc1b83f7a6c 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -17,6 +17,8 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.ColorStateList; +import android.content.res.ComplexColor; +import android.content.res.GradientColor; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; @@ -27,6 +29,7 @@ import android.graphics.PixelFormat; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.PorterDuff.Mode; +import android.graphics.Shader; import android.util.ArrayMap; import android.util.AttributeSet; import android.util.DisplayMetrics; @@ -121,9 +124,9 @@ import java.util.Stack; * <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>Specifies the color used to fill the path. May be a color or (SDK 24+ only) a color state - * list. If this property is animated, any value set by the animation will override the original - * value. No path fill is drawn if this property is not specified.</dd> + * <dd>Specifies the color used to fill the path. May be a color, also may be a color state list or + * a gradient color for SDK 24+. If this property is animated, any value set by the animation will + * override the original value. No path fill is drawn if this property is not specified.</dd> * <dt><code>android:strokeColor</code></dt> * <dd>Specifies the color used to draw the path outline. May be a color or (SDK 24+ only) a color * state list. If this property is animated, any value set by the animation will override the @@ -1276,8 +1279,9 @@ public class VectorDrawable extends Drawable { ///////////////////////////////////////////////////// // Variables below need to be copied (deep copy if applicable) for mutation. private int[] mThemeAttrs; - ColorStateList mStrokeColors = null; - ColorStateList mFillColors = null; + + ComplexColor mStrokeColors = null; + ComplexColor mFillColors = null; private long mNativePtr = 0; public VFullPath() { @@ -1297,23 +1301,25 @@ public class VectorDrawable extends Drawable { public boolean onStateChange(int[] stateSet) { boolean changed = false; - if (mStrokeColors != null) { + if (mStrokeColors != null && mStrokeColors instanceof ColorStateList) { final int oldStrokeColor = getStrokeColor(); - final int newStrokeColor = mStrokeColors.getColorForState(stateSet, oldStrokeColor); + final int newStrokeColor = + ((ColorStateList) mStrokeColors).getColorForState(stateSet, oldStrokeColor); changed |= oldStrokeColor != newStrokeColor; if (oldStrokeColor != newStrokeColor) { nSetStrokeColor(mNativePtr, newStrokeColor); } } - if (mFillColors != null) { + if (mFillColors != null && mFillColors instanceof ColorStateList) { final int oldFillColor = getFillColor(); - final int newFillColor = mFillColors.getColorForState(stateSet, oldFillColor); + final int newFillColor = ((ColorStateList) mFillColors).getColorForState(stateSet, oldFillColor); changed |= oldFillColor != newFillColor; if (oldFillColor != newFillColor) { nSetFillColor(mNativePtr, newFillColor); } } + return changed; } @@ -1372,7 +1378,8 @@ public class VectorDrawable extends Drawable { int strokeLineCap = properties.getInt(STROKE_LINE_CAP_INDEX * 4); int strokeLineJoin = properties.getInt(STROKE_LINE_JOIN_INDEX * 4); float strokeMiterLimit = properties.getFloat(STROKE_MITER_LIMIT_INDEX * 4); - + Shader fillGradient = null; + Shader strokeGradient = null; // Account for any configuration changes. mChangingConfigurations |= a.getChangingConfigurations(); @@ -1391,23 +1398,43 @@ public class VectorDrawable extends Drawable { nSetPathString(mNativePtr, pathString, pathString.length()); } - final ColorStateList fillColors = a.getColorStateList( + final ComplexColor fillColors = a.getComplexColor( R.styleable.VectorDrawablePath_fillColor); if (fillColors != null) { - // If the color state list isn't stateful, discard the state - // list and keep the default (e.g. the only) color. - mFillColors = fillColors.isStateful() ? fillColors : null; + // If the colors is a gradient color, or the color state list is stateful, keep the + // colors information. Otherwise, discard the colors and keep the default color. + if (fillColors instanceof GradientColor) { + mFillColors = fillColors; + fillGradient = ((GradientColor) fillColors).getShader(); + } else if (fillColors.isStateful()) { + mFillColors = fillColors; + } else { + mFillColors = null; + } fillColor = fillColors.getDefaultColor(); } - final ColorStateList strokeColors = a.getColorStateList( + final ComplexColor strokeColors = a.getComplexColor( R.styleable.VectorDrawablePath_strokeColor); if (strokeColors != null) { - // If the color state list isn't stateful, discard the state - // list and keep the default (e.g. the only) color. - mStrokeColors = strokeColors.isStateful() ? strokeColors : null; + // If the colors is a gradient color, or the color state list is stateful, keep the + // colors information. Otherwise, discard the colors and keep the default color. + if (strokeColors instanceof GradientColor) { + mStrokeColors = strokeColors; + strokeGradient = ((GradientColor) strokeColors).getShader(); + } else if (strokeColors.isStateful()) { + mStrokeColors = strokeColors; + } else { + mStrokeColors = null; + } strokeColor = strokeColors.getDefaultColor(); } + // Update the gradient info, even if the gradiet is null. + nUpdateFullPathFillGradient(mNativePtr, + fillGradient != null ? fillGradient.getNativeInstance() : 0); + nUpdateFullPathStrokeGradient(mNativePtr, + strokeGradient != null ? strokeGradient.getNativeInstance() : 0); + fillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha, fillAlpha); strokeLineCap = a.getInt( @@ -1434,18 +1461,44 @@ public class VectorDrawable extends Drawable { @Override public boolean canApplyTheme() { - return mThemeAttrs != null; + if (mThemeAttrs != null) { + return true; + } + boolean fillCanApplyTheme = canGradientApplyTheme(mFillColors); + boolean strokeCanApplyTheme = canGradientApplyTheme(mStrokeColors); + if (fillCanApplyTheme || strokeCanApplyTheme) { + return true; + } + return false; + } @Override public void applyTheme(Theme t) { - if (mThemeAttrs == null) { - return; + if (mThemeAttrs != null) { + final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath); + updateStateFromTypedArray(a); + a.recycle(); } - final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath); - updateStateFromTypedArray(a); - a.recycle(); + boolean fillCanApplyTheme = canGradientApplyTheme(mFillColors); + boolean strokeCanApplyTheme = canGradientApplyTheme(mStrokeColors); + if (fillCanApplyTheme) { + mFillColors = mFillColors.obtainForTheme(t); + nUpdateFullPathFillGradient(mNativePtr, + ((GradientColor)mFillColors).getShader().getNativeInstance()); + } + + if (strokeCanApplyTheme) { + mStrokeColors = mStrokeColors.obtainForTheme(t); + nUpdateFullPathStrokeGradient(mNativePtr, + ((GradientColor)mStrokeColors).getShader().getNativeInstance()); + } + } + + private boolean canGradientApplyTheme(ComplexColor complexColor) { + return complexColor != null && complexColor.canApplyTheme() + && complexColor instanceof GradientColor; } /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ @@ -1560,6 +1613,8 @@ public class VectorDrawable extends Drawable { int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin); + private static native void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr); + private static native void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr); private static native long nCreateClipPath(); private static native long nCreateClipPath(long clipPathPtr); diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index 1d31c9e08a9e..4d4acb94c255 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -18,6 +18,7 @@ #include "PathParser.h" #include "SkImageInfo.h" +#include "SkShader.h" #include <utils/Log.h> #include "utils/Macros.h" #include "utils/VectorDrawableUtils.h" @@ -49,7 +50,7 @@ void Path::draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix, float s float minScale = fmin(scaleX, scaleY); float strokeScale = minScale * matrixScale; - drawPath(outCanvas, renderPath, strokeScale); + drawPath(outCanvas, renderPath, strokeScale, pathMatrix); } void Path::setPathData(const Data& data) { @@ -148,6 +149,9 @@ FullPath::FullPath(const FullPath& path) : Path(path) { mStrokeMiterLimit = path.mStrokeMiterLimit; mStrokeLineCap = path.mStrokeLineCap; mStrokeLineJoin = path.mStrokeLineJoin; + + SkRefCnt_SafeAssign(mStrokeGradient, path.mStrokeGradient); + SkRefCnt_SafeAssign(mFillGradient, path.mFillGradient); } const SkPath& FullPath::getUpdatedPath() { @@ -186,22 +190,44 @@ inline SkColor applyAlpha(SkColor color, float alpha) { return SkColorSetA(color, alphaBytes * alpha); } -void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale){ - // Draw path's fill, if fill color isn't transparent. - if (mFillColor != SK_ColorTRANSPARENT) { +void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale, + const SkMatrix& matrix){ + // Draw path's fill, if fill color or gradient is valid + bool needsFill = false; + if (mFillGradient != nullptr) { + mPaint.setColor(applyAlpha(SK_ColorBLACK, mFillAlpha)); + SkShader* newShader = mFillGradient->newWithLocalMatrix(matrix); + mPaint.setShader(newShader); + needsFill = true; + } else if (mFillColor != SK_ColorTRANSPARENT) { + mPaint.setColor(applyAlpha(mFillColor, mFillAlpha)); + outCanvas->drawPath(renderPath, mPaint); + needsFill = true; + } + + if (needsFill) { mPaint.setStyle(SkPaint::Style::kFill_Style); mPaint.setAntiAlias(true); - mPaint.setColor(applyAlpha(mFillColor, mFillAlpha)); outCanvas->drawPath(renderPath, mPaint); } - // Draw path's stroke, if stroke color isn't transparent - if (mStrokeColor != SK_ColorTRANSPARENT) { + + // Draw path's stroke, if stroke color or gradient is valid + bool needsStroke = false; + if (mStrokeGradient != nullptr) { + mPaint.setColor(applyAlpha(SK_ColorBLACK, mStrokeAlpha)); + SkShader* newShader = mStrokeGradient->newWithLocalMatrix(matrix); + mPaint.setShader(newShader); + needsStroke = true; + } else if (mStrokeColor != SK_ColorTRANSPARENT) { + mPaint.setColor(applyAlpha(mStrokeColor, mStrokeAlpha)); + needsStroke = true; + } + if (needsStroke) { mPaint.setStyle(SkPaint::Style::kStroke_Style); mPaint.setAntiAlias(true); mPaint.setStrokeJoin(mStrokeLineJoin); mPaint.setStrokeCap(mStrokeLineCap); mPaint.setStrokeMiter(mStrokeMiterLimit); - mPaint.setColor(applyAlpha(mStrokeColor, mStrokeAlpha)); mPaint.setStrokeWidth(mStrokeWidth * strokeScale); outCanvas->drawPath(renderPath, mPaint); } @@ -288,7 +314,7 @@ bool FullPath::getProperties(int8_t* outProperties, int length) { } void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, - float strokeScale){ + float strokeScale, const SkMatrix& matrix){ outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op); } diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index 5ae5f6a3bdba..09bdce596a21 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -26,6 +26,7 @@ #include <SkPath.h> #include <SkPathMeasure.h> #include <SkRect.h> +#include <SkShader.h> #include <cutils/compiler.h> #include <stddef.h> @@ -95,7 +96,7 @@ public: protected: virtual const SkPath& getUpdatedPath(); virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath, - float strokeScale) = 0; + float strokeScale, const SkMatrix& matrix) = 0; Data mData; SkPath mSkPath; bool mSkPathDirty = true; @@ -108,6 +109,11 @@ public: FullPath() : Path() {} FullPath(const Data& nodes) : Path(nodes) {} + ~FullPath() { + SkSafeUnref(mFillGradient); + SkSafeUnref(mStrokeGradient); + } + void updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha, SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, float trimPathOffset, @@ -162,10 +168,18 @@ public: } bool getProperties(int8_t* outProperties, int length); + void setFillGradient(SkShader* fillGradient) { + SkRefCnt_SafeAssign(mFillGradient, fillGradient); + }; + void setStrokeGradient(SkShader* strokeGradient) { + SkRefCnt_SafeAssign(mStrokeGradient, strokeGradient); + }; + + protected: const SkPath& getUpdatedPath() override; void drawPath(SkCanvas* outCanvas, const SkPath& renderPath, - float strokeScale) override; + float strokeScale, const SkMatrix& matrix) override; private: // Applies trimming to the specified path. @@ -174,6 +188,8 @@ private: SkColor mStrokeColor = SK_ColorTRANSPARENT; float mStrokeAlpha = 1; SkColor mFillColor = SK_ColorTRANSPARENT; + SkShader* mStrokeGradient = nullptr; + SkShader* mFillGradient = nullptr; float mFillAlpha = 1; float mTrimPathStart = 0; float mTrimPathEnd = 1; @@ -195,7 +211,7 @@ public: protected: void drawPath(SkCanvas* outCanvas, const SkPath& renderPath, - float strokeScale) override; + float strokeScale, const SkMatrix& matrix) override; }; class ANDROID_API Group: public Node { diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml new file mode 100644 index 000000000000..e0e3f03d64f5 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:angle="90" + android:startColor="?android:attr/colorPrimary" + android:endColor="?android:attr/colorControlActivated" + android:centerColor="#00ff0000" + android:startX="0" + android:startY="0" + android:endX="100" + android:endY="100" + android:type="linear"> +</gradient>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml new file mode 100644 index 000000000000..cfb123603735 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:angle="90" + android:startColor="?android:attr/colorPrimary" + android:endColor="?android:attr/colorControlActivated" + android:centerColor="#f00" + android:startX="0" + android:startY="0" + android:endX="100" + android:endY="100" + android:type="linear"> + <item android:offset="0.1" android:color="?android:attr/colorPrimary"/> + <item android:offset="0.4" android:color="#fff"/> + <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/> +</gradient>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml new file mode 100644 index 000000000000..18274b9ec55a --- /dev/null +++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:angle="90" + android:startColor="?android:attr/colorPrimary" + android:endColor="?android:attr/colorControlActivated" + android:centerColor="#f00" + android:startX="0" + android:startY="0" + android:endX="100" + android:endY="100" + android:type="linear"> + <item android:offset="0.1" android:color="?android:attr/colorPrimary"/> + <item android:offset="0.4" android:color="#f00"/> + <item android:offset="0.4" android:color="#fff"/> + <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/> +</gradient>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml new file mode 100644 index 000000000000..ef6fd70c67f7 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:centerColor="#ff0000" + android:endColor="?android:attr/colorControlActivated" + android:centerX="300" + android:centerY="300" + android:gradientRadius="100" + android:startColor="?android:attr/colorPrimary" + android:type="radial"> +</gradient>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml new file mode 100644 index 000000000000..51b0e173f746 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> + <!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:centerColor="#ff0000" + android:endColor="#ff0000ff" + android:centerX="300" + android:centerY="300" + android:gradientRadius="100" + android:startColor="#ffffffff" + android:type="radial"> + <item android:offset="0.1" android:color="?android:attr/colorPrimary"/> + <item android:offset="0.4" android:color="#fff"/> + <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/> +</gradient>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml new file mode 100644 index 000000000000..8caa1b4348a2 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> + <!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:centerX="300" + android:centerY="300" + android:gradientRadius="100" + android:type="radial"> + <item android:offset="0.1" android:color="?android:attr/colorPrimary"/> + <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/> +</gradient>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml new file mode 100644 index 000000000000..e1fbd10b7e91 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:centerColor="#ff0000" + android:endColor="#ff0000ff" + android:centerX="500" + android:centerY="500" + android:gradientRadius="10" + android:startColor="#ffffffff" + android:type="sweep"> +</gradient> diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml new file mode 100644 index 000000000000..332b93894960 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:centerColor="#ff0000" + android:endColor="#ff0000ff" + android:centerX="500" + android:centerY="500" + android:gradientRadius="10" + android:startColor="#ffffffff" + android:type="sweep"> + <item android:offset="0.1" android:color="?android:attr/colorPrimary"/> + <item android:offset="0.4" android:color="#fff"/> + <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/> +</gradient> diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml new file mode 100644 index 000000000000..3931288c5c25 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:centerX="500" + android:centerY="500" + android:gradientRadius="10" + android:type="sweep"> + <item android:offset="-0.3" android:color="#f00"/> + <item android:offset="0.1" android:color="?android:attr/colorPrimary"/> + <item android:offset="0.4" android:color="#0f0"/> + <item android:offset="0.6" android:color="#00f"/> + <item android:offset="0.7" android:color="?android:attr/colorControlActivated"/> + <item android:offset="1.5" android:color="#00f"/> +</gradient> diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient.xml b/tests/VectorDrawableTest/res/color/stroke_gradient.xml new file mode 100644 index 000000000000..cb324c9a7f4e --- /dev/null +++ b/tests/VectorDrawableTest/res/color/stroke_gradient.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:angle="90" + android:centerColor="#7f7f7f" + android:endColor="#ffffff" + android:startColor="#000000" + android:startX="0" + android:endX="100" + android:startY="0" + android:endY="0" + android:type="linear"> +</gradient>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml b/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml new file mode 100644 index 000000000000..15d948c25899 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:angle="90" + android:centerColor="#7f7f7f" + android:endColor="#ffffff" + android:startColor="#000000" + android:startX="0" + android:endX="100" + android:startY="0" + android:endY="0" + android:type="linear"> + <item android:offset="0.1" android:color="#f00"/> + <item android:offset="0.2" android:color="#f0f"/> + <item android:offset="0.9" android:color="#f00f"/> +</gradient>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml b/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml new file mode 100644 index 000000000000..fda2b88bc3e1 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<gradient xmlns:android="http://schemas.android.com/apk/res/android" + android:startX="0" + android:endX="100" + android:startY="0" + android:endY="0" + android:type="linear"> + <item android:offset="0.1" android:color="#f00"/> + <item android:offset="0.2" android:color="#2f0f"/> + <item android:offset="0.9" android:color="#f00f"/> +</gradient>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml b/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml new file mode 100644 index 000000000000..45d88b567ba2 --- /dev/null +++ b/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="?android:attr/colorPrimary" android:state_pressed="true" /> + <item android:color="?android:attr/colorControlActivated" /> +</selector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml b/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml new file mode 100644 index 000000000000..16251c8d50bd --- /dev/null +++ b/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="?android:attr/colorControlActivated" android:state_pressed="true" /> + <item android:color="?android:attr/colorPrimary" /> +</selector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml index 2be99bed4bfb..89afde22f635 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml @@ -27,8 +27,8 @@ <path android:name="box1" android:pathData="m20,200l100,90l180-180l-35-35l-145,145l-60-60l-40,40z" - android:fillColor="?android:attr/colorControlNormal" - android:strokeColor="?android:attr/colorControlNormal" + android:fillColor="?android:attr/colorPrimary" + android:strokeColor="?android:attr/colorPrimary" android:strokeLineCap="round" android:strokeLineJoin="round" /> </group> diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml new file mode 100644 index 000000000000..d67aca7cdaec --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="64dp" + android:width="64dp" + android:viewportHeight="400" + android:viewportWidth="400" > + +<group android:name="backgroundGroup" + android:scaleX="0.5" + android:scaleY="0.5"> + <path + android:name="background1" + android:fillColor="@color/fill_gradient_linear" + android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" /> + <path + android:name="background2" + android:fillColor="@color/fill_gradient_radial" + android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" /> + <path + android:name="background3" + android:fillColor="@color/fill_gradient_sweep" + android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" /> +</group> +<group + android:name="translateToCenterGroup" + android:translateX="50.0" + android:translateY="90.0" > + <path + android:name="twoLines" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient" + android:strokeWidth="20" /> + + <group + android:name="rotationGroup" + android:pivotX="0.0" + android:pivotY="0.0" + android:rotation="-45.0"> + <path + android:name="twoLines1" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient" + android:strokeWidth="20" /> + + <group + android:name="translateGroup" + android:translateX="130.0" + android:translateY="160.0"> + <group android:name="scaleGroup" > + <path + android:name="twoLines3" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient" + android:strokeWidth="20" /> + </group> + </group> + + <group + android:name="translateGroupHalf" + android:translateX="65.0" + android:translateY="80.0"> + <group android:name="scaleGroup" > + <path + android:name="twoLines2" + android:pathData="@string/twoLinePathData" + android:fillColor="@color/fill_gradient_linear" + android:strokeColor="@color/stroke_gradient" + android:strokeWidth="20" /> + </group> + </group> + </group> +</group> + +</vector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml new file mode 100644 index 000000000000..abf3c7a86b80 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="64dp" + android:width="64dp" + android:viewportHeight="400" + android:viewportWidth="400" > + +<group android:name="backgroundGroup" + android:scaleX="0.5" + android:scaleY="0.5"> + <path + android:name="background1" + android:fillColor="@color/fill_gradient_linear_item" + android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" /> + <path + android:name="background2" + android:fillColor="@color/fill_gradient_radial_item" + android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" /> + <path + android:name="background3" + android:fillColor="@color/fill_gradient_sweep_item" + android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" /> +</group> +<group + android:name="translateToCenterGroup" + android:translateX="50.0" + android:translateY="90.0" > + <path + android:name="twoLines" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient_item" + android:strokeWidth="20" /> + + <group + android:name="rotationGroup" + android:pivotX="0.0" + android:pivotY="0.0" + android:rotation="-45.0"> + <path + android:name="twoLines1" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient_item" + android:strokeWidth="20" /> + + <group + android:name="translateGroup" + android:translateX="130.0" + android:translateY="160.0"> + <group android:name="scaleGroup" > + <path + android:name="twoLines3" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient_item" + android:strokeWidth="20" /> + </group> + </group> + + <group + android:name="translateGroupHalf" + android:translateX="65.0" + android:translateY="80.0"> + <group android:name="scaleGroup" > + <path + android:name="twoLines2" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient_item" + android:strokeWidth="20" /> + </group> + </group> + </group> +</group> + +</vector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml new file mode 100644 index 000000000000..5f9726f72c03 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="64dp" + android:width="64dp" + android:viewportHeight="400" + android:viewportWidth="400" > + +<group android:name="backgroundGroup" + android:scaleX="0.5" + android:scaleY="0.5"> + <path + android:name="background1" + android:fillColor="@color/fill_gradient_linear_item_overlap" + android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" /> + <path + android:name="background2" + android:fillColor="@color/fill_gradient_radial_item_short" + android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" /> + <path + android:name="background3" + android:fillColor="@color/fill_gradient_sweep_item_long" + android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" /> +</group> +<group + android:name="translateToCenterGroup" + android:translateX="50.0" + android:translateY="90.0" > + <path + android:name="twoLines" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient_item_alpha" + android:strokeWidth="20" /> + + <group + android:name="rotationGroup" + android:pivotX="0.0" + android:pivotY="0.0" + android:rotation="-45.0"> + <path + android:name="twoLines1" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient_item_alpha" + android:strokeWidth="20" /> + + <group + android:name="translateGroup" + android:translateX="130.0" + android:translateY="160.0"> + <group android:name="scaleGroup" > + <path + android:name="twoLines3" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient_item_alpha" + android:strokeWidth="20" /> + </group> + </group> + + <group + android:name="translateGroupHalf" + android:translateX="65.0" + android:translateY="80.0"> + <group android:name="scaleGroup" > + <path + android:name="twoLines2" + android:pathData="@string/twoLinePathData" + android:strokeColor="@color/stroke_gradient_item_alpha" + android:strokeWidth="20" /> + </group> + </group> + </group> +</group> + +</vector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_state_list.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list.xml new file mode 100644 index 000000000000..b1ed85025040 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="64dp" + android:width="64dp" + android:viewportHeight="24" + android:viewportWidth="24" > + + <path + android:fillColor="@color/vector_icon_fill_state_list" + android:strokeColor="@color/vector_icon_stroke_state_list" + android:strokeWidth="3" + android:pathData="M16.0,5.0c-1.955.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z"/> + +</vector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java index b4a93f68f6c9..a7da286ac6ab 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java @@ -35,6 +35,10 @@ import java.text.DecimalFormat; public class VectorDrawablePerformance extends Activity { private static final String LOGCAT = "VectorDrawable1"; protected int[] icon = { + R.drawable.vector_icon_gradient_1, + R.drawable.vector_icon_gradient_2, + R.drawable.vector_icon_gradient_3, + R.drawable.vector_icon_state_list, R.drawable.vector_drawable01, R.drawable.vector_drawable02, R.drawable.vector_drawable03, @@ -102,7 +106,7 @@ public class VectorDrawablePerformance extends Activity { ScrollView scrollView = new ScrollView(this); GridLayout container = new GridLayout(this); scrollView.addView(container); - container.setColumnCount(5); + container.setColumnCount(4); Resources res = this.getResources(); container.setBackgroundColor(0xFF888888); VectorDrawable []d = new VectorDrawable[icon.length]; |