Merge "Gradient for VectorDrawable's fill and stroke"
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
55
core/java/android/content/res/ComplexColor.java
Normal file
55
core/java/android/content/res/ComplexColor.java
Normal file
@@ -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);
|
||||
}
|
||||
523
core/java/android/content/res/GradientColor.java
Normal file
523
core/java/android/content/res/GradientColor.java
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,6 +2614,82 @@ 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
|
||||
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("loadComplexColor", name);
|
||||
}
|
||||
}
|
||||
|
||||
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 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");
|
||||
}
|
||||
|
||||
return complexColor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ColorStateList loadColorStateList(TypedValue value, int id, Theme theme)
|
||||
throws NotFoundException {
|
||||
@@ -2626,63 +2703,57 @@ public class Resources {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
csl = ColorStateList.valueOf(value.data);
|
||||
|
||||
if (mPreloading) {
|
||||
if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
|
||||
"color")) {
|
||||
sPreloadedColorStateLists.put(key, csl.getConstantState());
|
||||
}
|
||||
}
|
||||
|
||||
return csl;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -453,6 +453,39 @@ public class TypedArray {
|
||||
+ Integer.toHexString(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -96,6 +96,21 @@ public final class GrowingArrayUtils {
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
||||
@@ -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},
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -117,7 +117,10 @@ public class Shader {
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ long getNativeInstance() {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public long getNativeInstance() {
|
||||
return native_instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
mPaint.setStyle(SkPaint::Style::kFill_Style);
|
||||
mPaint.setAntiAlias(true);
|
||||
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;
|
||||
}
|
||||
// Draw path's stroke, if stroke color isn't transparent
|
||||
if (mStrokeColor != SK_ColorTRANSPARENT) {
|
||||
|
||||
if (needsFill) {
|
||||
mPaint.setStyle(SkPaint::Style::kFill_Style);
|
||||
mPaint.setAntiAlias(true);
|
||||
outCanvas->drawPath(renderPath, mPaint);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
29
tests/VectorDrawableTest/res/color/fill_gradient_linear.xml
Normal file
29
tests/VectorDrawableTest/res/color/fill_gradient_linear.xml
Normal file
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
27
tests/VectorDrawableTest/res/color/fill_gradient_radial.xml
Normal file
27
tests/VectorDrawableTest/res/color/fill_gradient_radial.xml
Normal file
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
27
tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml
Normal file
27
tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml
Normal file
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
29
tests/VectorDrawableTest/res/color/stroke_gradient.xml
Normal file
29
tests/VectorDrawableTest/res/color/stroke_gradient.xml
Normal file
@@ -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>
|
||||
32
tests/VectorDrawableTest/res/color/stroke_gradient_item.xml
Normal file
32
tests/VectorDrawableTest/res/color/stroke_gradient_item.xml
Normal file
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user