factory =
+ sPreloadedComplexColors.get(key);
if (factory != null) {
- csl = factory.newInstance(this, theme);
+ return (ColorStateList) factory.newInstance();
}
- if (csl == null) {
- csl = loadColorStateListForCookie(value, id, theme);
- }
+ csl = ColorStateList.valueOf(value.data);
- if (csl != null) {
- if (mPreloading) {
- if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
- "color")) {
- sPreloadedColorStateLists.put(key, csl.getConstantState());
- }
- } else {
- cache.put(key, theme, csl.getConstantState());
+ if (mPreloading) {
+ if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
+ "color")) {
+ sPreloadedComplexColors.put(key, csl.getConstantState());
}
}
return csl;
}
- private ColorStateList loadColorStateListForCookie(TypedValue value, int id, Theme theme) {
+ /**
+ * Load a ComplexColor based on the XML file content. The result can be a GradientColor or
+ * ColorStateList. Note that pure color will be wrapped into a ColorStateList.
+ *
+ * We deferred the parser creation to this function b/c we need to differentiate b/t gradient
+ * and selector tag.
+ *
+ * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content.
+ */
+ @Nullable
+ private ComplexColor loadComplexColorForCookie(TypedValue value, int id, Theme theme) {
if (value.string == null) {
throw new UnsupportedOperationException(
- "Can't convert to color state list: type=0x" + value.type);
+ "Can't convert to ComplexColor: type=0x" + value.type);
}
final String file = value.string.toString();
@@ -2692,29 +2763,45 @@ public class Resources {
if ((id >>> 24) == 0x1) {
final String name = getResourceName(id);
if (name != null) {
- Log.d(TAG, "Loading framework color state list #" + Integer.toHexString(id)
+ Log.d(TAG, "Loading framework ComplexColor #" + Integer.toHexString(id)
+ ": " + name + " at " + file);
}
}
}
if (DEBUG_LOAD) {
- Log.v(TAG, "Loading color state list for cookie " + value.assetCookie + ": " + file);
+ Log.v(TAG, "Loading ComplexColor for cookie " + value.assetCookie + ": " + file);
}
- final ColorStateList csl;
+ ComplexColor complexColor = null;
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
if (file.endsWith(".xml")) {
try {
- final XmlResourceParser rp = loadXmlResourceParser(
- file, id, value.assetCookie, "colorstatelist");
- csl = ColorStateList.createFromXml(this, rp, theme);
- rp.close();
+ final XmlResourceParser parser = loadXmlResourceParser(
+ file, id, value.assetCookie, "ComplexColor");
+
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Seek parser to start tag.
+ }
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ final String name = parser.getName();
+ if (name.equals("gradient")) {
+ complexColor = GradientColor.createFromXmlInner(this, parser, attrs, theme);
+ } else if (name.equals("selector")) {
+ complexColor = ColorStateList.createFromXmlInner(this, parser, attrs, theme);
+ }
+ parser.close();
} catch (Exception e) {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
final NotFoundException rnf = new NotFoundException(
- "File " + file + " from color state list resource ID #0x"
+ "File " + file + " from ComplexColor resource ID #0x"
+ Integer.toHexString(id));
rnf.initCause(e);
throw rnf;
@@ -2727,7 +2814,7 @@ public class Resources {
}
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
- return csl;
+ return complexColor;
}
/**
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index cc65e1e4f7103..6067577453c9d 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -453,6 +453,39 @@ public class TypedArray {
+ Integer.toHexString(type));
}
+ /**
+ * Retrieve the ComplexColor for the attribute at index.
+ * 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}
+ *
+ * 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 index.
* The value may be either a single solid color or a reference to
diff --git a/core/java/com/android/internal/util/GrowingArrayUtils.java b/core/java/com/android/internal/util/GrowingArrayUtils.java
index b4d2d73066dd7..968d9204b106b 100644
--- a/core/java/com/android/internal/util/GrowingArrayUtils.java
+++ b/core/java/com/android/internal/util/GrowingArrayUtils.java
@@ -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.
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index 53d4c6a1cb780..563ec8bd98340 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -90,6 +90,18 @@ static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong full
strokeLineJoin);
}
+static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) {
+ VectorDrawable::FullPath* path = reinterpret_cast(pathPtr);
+ SkShader* fillShader = reinterpret_cast(fillGradientPtr);
+ path->setFillGradient(fillShader);
+}
+
+static void updateFullPathStrokeGradient(JNIEnv*, jobject, jlong pathPtr, jlong strokeGradientPtr) {
+ VectorDrawable::FullPath* path = reinterpret_cast(pathPtr);
+ SkShader* strokeShader = reinterpret_cast(strokeGradientPtr);
+ path->setStrokeGradient(strokeShader);
+}
+
static jboolean getFullPathProperties(JNIEnv* env, jobject, jlong fullPathPtr,
jbyteArray outProperties, jint length) {
VectorDrawable::FullPath* fullPath = reinterpret_cast(fullPathPtr);
@@ -331,6 +343,8 @@ static const JNINativeMethod gMethods[] = {
{"nCreateFullPath", "!()J", (void*)createEmptyFullPath},
{"nCreateFullPath", "!(J)J", (void*)createFullPath},
{"nUpdateFullPathProperties", "!(JFIFIFFFFFII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
+ {"nUpdateFullPathFillGradient", "!(JJ)V", (void*)updateFullPathFillGradient},
+ {"nUpdateFullPathStrokeGradient", "!(JJ)V", (void*)updateFullPathStrokeGradient},
{"nGetFullPathProperties", "(J[BI)Z", (void*)getFullPathProperties},
{"nGetGroupProperties", "(J[FI)Z", (void*)getGroupProperties},
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 713038b60d89d..1f7206eeecee4 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3727,7 +3727,7 @@ i
-
@@ -3740,7 +3740,7 @@ i
-
@@ -8135,4 +8135,52 @@ i
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 57132ea82977a..a2ad09b248c3c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2691,6 +2691,11 @@
+
+
+
+
+
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index adb282fb4bf95..94983b3d1f514 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -117,7 +117,10 @@ public class Shader {
}
}
- /* package */ long getNativeInstance() {
+ /**
+ * @hide
+ */
+ public long getNativeInstance() {
return native_instance;
}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 65260210042c2..1fc1b83f7a6c0 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -17,6 +17,8 @@ package android.graphics.drawable;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.ColorStateList;
+import android.content.res.ComplexColor;
+import android.content.res.GradientColor;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
@@ -27,6 +29,7 @@ import android.graphics.PixelFormat;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.PorterDuff.Mode;
+import android.graphics.Shader;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -121,9 +124,9 @@ import java.util.Stack;
* Defines path data using exactly same format as "d" attribute
* in the SVG's path data. This is defined in the viewport space.
* android:fillColor
- * 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.
+ * 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.
* android:strokeColor
* Specifies the color used to draw the path outline. May be a color or (SDK 24+ only) a color
* state list. If this property is animated, any value set by the animation will override the
@@ -1276,8 +1279,9 @@ public class VectorDrawable extends Drawable {
/////////////////////////////////////////////////////
// Variables below need to be copied (deep copy if applicable) for mutation.
private int[] mThemeAttrs;
- ColorStateList mStrokeColors = null;
- ColorStateList mFillColors = null;
+
+ ComplexColor mStrokeColors = null;
+ ComplexColor mFillColors = null;
private long mNativePtr = 0;
public VFullPath() {
@@ -1297,23 +1301,25 @@ public class VectorDrawable extends Drawable {
public boolean onStateChange(int[] stateSet) {
boolean changed = false;
- if (mStrokeColors != null) {
+ if (mStrokeColors != null && mStrokeColors instanceof ColorStateList) {
final int oldStrokeColor = getStrokeColor();
- final int newStrokeColor = mStrokeColors.getColorForState(stateSet, oldStrokeColor);
+ final int newStrokeColor =
+ ((ColorStateList) mStrokeColors).getColorForState(stateSet, oldStrokeColor);
changed |= oldStrokeColor != newStrokeColor;
if (oldStrokeColor != newStrokeColor) {
nSetStrokeColor(mNativePtr, newStrokeColor);
}
}
- if (mFillColors != null) {
+ if (mFillColors != null && mFillColors instanceof ColorStateList) {
final int oldFillColor = getFillColor();
- final int newFillColor = mFillColors.getColorForState(stateSet, oldFillColor);
+ final int newFillColor = ((ColorStateList) mFillColors).getColorForState(stateSet, oldFillColor);
changed |= oldFillColor != newFillColor;
if (oldFillColor != newFillColor) {
nSetFillColor(mNativePtr, newFillColor);
}
}
+
return changed;
}
@@ -1372,7 +1378,8 @@ public class VectorDrawable extends Drawable {
int strokeLineCap = properties.getInt(STROKE_LINE_CAP_INDEX * 4);
int strokeLineJoin = properties.getInt(STROKE_LINE_JOIN_INDEX * 4);
float strokeMiterLimit = properties.getFloat(STROKE_MITER_LIMIT_INDEX * 4);
-
+ Shader fillGradient = null;
+ Shader strokeGradient = null;
// Account for any configuration changes.
mChangingConfigurations |= a.getChangingConfigurations();
@@ -1391,23 +1398,43 @@ public class VectorDrawable extends Drawable {
nSetPathString(mNativePtr, pathString, pathString.length());
}
- final ColorStateList fillColors = a.getColorStateList(
+ final ComplexColor fillColors = a.getComplexColor(
R.styleable.VectorDrawablePath_fillColor);
if (fillColors != null) {
- // If the color state list isn't stateful, discard the state
- // list and keep the default (e.g. the only) color.
- mFillColors = fillColors.isStateful() ? fillColors : null;
+ // If the colors is a gradient color, or the color state list is stateful, keep the
+ // colors information. Otherwise, discard the colors and keep the default color.
+ if (fillColors instanceof GradientColor) {
+ mFillColors = fillColors;
+ fillGradient = ((GradientColor) fillColors).getShader();
+ } else if (fillColors.isStateful()) {
+ mFillColors = fillColors;
+ } else {
+ mFillColors = null;
+ }
fillColor = fillColors.getDefaultColor();
}
- final ColorStateList strokeColors = a.getColorStateList(
+ final ComplexColor strokeColors = a.getComplexColor(
R.styleable.VectorDrawablePath_strokeColor);
if (strokeColors != null) {
- // If the color state list isn't stateful, discard the state
- // list and keep the default (e.g. the only) color.
- mStrokeColors = strokeColors.isStateful() ? strokeColors : null;
+ // If the colors is a gradient color, or the color state list is stateful, keep the
+ // colors information. Otherwise, discard the colors and keep the default color.
+ if (strokeColors instanceof GradientColor) {
+ mStrokeColors = strokeColors;
+ strokeGradient = ((GradientColor) strokeColors).getShader();
+ } else if (strokeColors.isStateful()) {
+ mStrokeColors = strokeColors;
+ } else {
+ mStrokeColors = null;
+ }
strokeColor = strokeColors.getDefaultColor();
}
+ // Update the gradient info, even if the gradiet is null.
+ nUpdateFullPathFillGradient(mNativePtr,
+ fillGradient != null ? fillGradient.getNativeInstance() : 0);
+ nUpdateFullPathStrokeGradient(mNativePtr,
+ strokeGradient != null ? strokeGradient.getNativeInstance() : 0);
+
fillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha, fillAlpha);
strokeLineCap = a.getInt(
@@ -1434,18 +1461,44 @@ public class VectorDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null;
+ if (mThemeAttrs != null) {
+ return true;
+ }
+ boolean fillCanApplyTheme = canGradientApplyTheme(mFillColors);
+ boolean strokeCanApplyTheme = canGradientApplyTheme(mStrokeColors);
+ if (fillCanApplyTheme || strokeCanApplyTheme) {
+ return true;
+ }
+ return false;
+
}
@Override
public void applyTheme(Theme t) {
- if (mThemeAttrs == null) {
- return;
+ if (mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
+ updateStateFromTypedArray(a);
+ a.recycle();
}
- final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
- updateStateFromTypedArray(a);
- a.recycle();
+ boolean fillCanApplyTheme = canGradientApplyTheme(mFillColors);
+ boolean strokeCanApplyTheme = canGradientApplyTheme(mStrokeColors);
+ if (fillCanApplyTheme) {
+ mFillColors = mFillColors.obtainForTheme(t);
+ nUpdateFullPathFillGradient(mNativePtr,
+ ((GradientColor)mFillColors).getShader().getNativeInstance());
+ }
+
+ if (strokeCanApplyTheme) {
+ mStrokeColors = mStrokeColors.obtainForTheme(t);
+ nUpdateFullPathStrokeGradient(mNativePtr,
+ ((GradientColor)mStrokeColors).getShader().getNativeInstance());
+ }
+ }
+
+ private boolean canGradientApplyTheme(ComplexColor complexColor) {
+ return complexColor != null && complexColor.canApplyTheme()
+ && complexColor instanceof GradientColor;
}
/* Setters and Getters, used by animator from AnimatedVectorDrawable. */
@@ -1560,6 +1613,8 @@ public class VectorDrawable extends Drawable {
int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
int strokeLineJoin);
+ private static native void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr);
+ private static native void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr);
private static native long nCreateClipPath();
private static native long nCreateClipPath(long clipPathPtr);
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 1d31c9e08a9e3..4d4acb94c2559 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -18,6 +18,7 @@
#include "PathParser.h"
#include "SkImageInfo.h"
+#include "SkShader.h"
#include
#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);
}
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 5ae5f6a3bdba1..09bdce596a218 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include
@@ -95,7 +96,7 @@ public:
protected:
virtual const SkPath& getUpdatedPath();
virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath,
- float strokeScale) = 0;
+ float strokeScale, const SkMatrix& matrix) = 0;
Data mData;
SkPath mSkPath;
bool mSkPathDirty = true;
@@ -108,6 +109,11 @@ public:
FullPath() : Path() {}
FullPath(const Data& nodes) : Path(nodes) {}
+ ~FullPath() {
+ SkSafeUnref(mFillGradient);
+ SkSafeUnref(mStrokeGradient);
+ }
+
void updateProperties(float strokeWidth, SkColor strokeColor,
float strokeAlpha, SkColor fillColor, float fillAlpha,
float trimPathStart, float trimPathEnd, float trimPathOffset,
@@ -162,10 +168,18 @@ public:
}
bool getProperties(int8_t* outProperties, int length);
+ void setFillGradient(SkShader* fillGradient) {
+ SkRefCnt_SafeAssign(mFillGradient, fillGradient);
+ };
+ void setStrokeGradient(SkShader* strokeGradient) {
+ SkRefCnt_SafeAssign(mStrokeGradient, strokeGradient);
+ };
+
+
protected:
const SkPath& getUpdatedPath() override;
void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
- float strokeScale) override;
+ float strokeScale, const SkMatrix& matrix) override;
private:
// Applies trimming to the specified path.
@@ -174,6 +188,8 @@ private:
SkColor mStrokeColor = SK_ColorTRANSPARENT;
float mStrokeAlpha = 1;
SkColor mFillColor = SK_ColorTRANSPARENT;
+ SkShader* mStrokeGradient = nullptr;
+ SkShader* mFillGradient = nullptr;
float mFillAlpha = 1;
float mTrimPathStart = 0;
float mTrimPathEnd = 1;
@@ -195,7 +211,7 @@ public:
protected:
void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
- float strokeScale) override;
+ float strokeScale, const SkMatrix& matrix) override;
};
class ANDROID_API Group: public Node {
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml
new file mode 100644
index 0000000000000..e0e3f03d64f59
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml
@@ -0,0 +1,29 @@
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml
new file mode 100644
index 0000000000000..cfb123603735b
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml
new file mode 100644
index 0000000000000..18274b9ec55a4
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml
new file mode 100644
index 0000000000000..ef6fd70c67f7d
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml
@@ -0,0 +1,27 @@
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml
new file mode 100644
index 0000000000000..51b0e173f7467
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml
new file mode 100644
index 0000000000000..8caa1b4348a28
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml
new file mode 100644
index 0000000000000..e1fbd10b7e91a
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml
@@ -0,0 +1,27 @@
+
+
+
+
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml
new file mode 100644
index 0000000000000..332b938949607
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml
new file mode 100644
index 0000000000000..3931288c5c25d
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient.xml b/tests/VectorDrawableTest/res/color/stroke_gradient.xml
new file mode 100644
index 0000000000000..cb324c9a7f4e8
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/stroke_gradient.xml
@@ -0,0 +1,29 @@
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml b/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml
new file mode 100644
index 0000000000000..15d948c25899f
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml b/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml
new file mode 100644
index 0000000000000..fda2b88bc3e12
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml b/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml
new file mode 100644
index 0000000000000..45d88b567ba26
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml b/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml
new file mode 100644
index 0000000000000..16251c8d50bde
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
index 2be99bed4bfb8..89afde22f6355 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -27,8 +27,8 @@
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml
new file mode 100644
index 0000000000000..d67aca7cdaec9
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml
new file mode 100644
index 0000000000000..abf3c7a86b80d
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml
new file mode 100644
index 0000000000000..5f9726f72c034
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_state_list.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list.xml
new file mode 100644
index 0000000000000..b1ed85025040c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index b4a93f68f6c99..a7da286ac6ab6 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -35,6 +35,10 @@ import java.text.DecimalFormat;
public class VectorDrawablePerformance extends Activity {
private static final String LOGCAT = "VectorDrawable1";
protected int[] icon = {
+ R.drawable.vector_icon_gradient_1,
+ R.drawable.vector_icon_gradient_2,
+ R.drawable.vector_icon_gradient_3,
+ R.drawable.vector_icon_state_list,
R.drawable.vector_drawable01,
R.drawable.vector_drawable02,
R.drawable.vector_drawable03,
@@ -102,7 +106,7 @@ public class VectorDrawablePerformance extends Activity {
ScrollView scrollView = new ScrollView(this);
GridLayout container = new GridLayout(this);
scrollView.addView(container);
- container.setColumnCount(5);
+ container.setColumnCount(4);
Resources res = this.getResources();
container.setBackgroundColor(0xFF888888);
VectorDrawable []d = new VectorDrawable[icon.length];