diff --git a/api/current.txt b/api/current.txt index 50e0de4175bb1..30a41060ee6f3 100644 --- a/api/current.txt +++ b/api/current.txt @@ -559,6 +559,7 @@ package android { field public static final int fillBefore = 16843196; // 0x10101bc field public static final int fillColor = 16843780; // 0x1010404 field public static final int fillEnabled = 16843343; // 0x101024f + field public static final int fillType = 16844064; // 0x1010520 field public static final int fillViewport = 16843130; // 0x101017a field public static final int filter = 16843035; // 0x101011b field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4 diff --git a/api/system-current.txt b/api/system-current.txt index 6433194e67877..faefaa8d94d77 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -654,6 +654,7 @@ package android { field public static final int fillBefore = 16843196; // 0x10101bc field public static final int fillColor = 16843780; // 0x1010404 field public static final int fillEnabled = 16843343; // 0x101024f + field public static final int fillType = 16844064; // 0x1010520 field public static final int fillViewport = 16843130; // 0x101017a field public static final int filter = 16843035; // 0x101011b field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4 diff --git a/api/test-current.txt b/api/test-current.txt index 6a54f31956aae..02b5896c96510 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -559,6 +559,7 @@ package android { field public static final int fillBefore = 16843196; // 0x10101bc field public static final int fillColor = 16843780; // 0x1010404 field public static final int fillEnabled = 16843343; // 0x101024f + field public static final int fillType = 16844064; // 0x1010520 field public static final int fillViewport = 16843130; // 0x101017a field public static final int filter = 16843035; // 0x101011b field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4 diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp index 7314fbcd92d2a..e17de17e06cc0 100644 --- a/core/jni/android_graphics_drawable_VectorDrawable.cpp +++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp @@ -78,11 +78,11 @@ static jlong createFullPath(JNIEnv*, jobject, jlong srcFullPathPtr) { static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong fullPathPtr, jfloat strokeWidth, jint strokeColor, jfloat strokeAlpha, jint fillColor, jfloat fillAlpha, jfloat trimPathStart, jfloat trimPathEnd, jfloat trimPathOffset, jfloat strokeMiterLimit, - jint strokeLineCap, jint strokeLineJoin) { + jint strokeLineCap, jint strokeLineJoin, jint fillType) { VectorDrawable::FullPath* fullPath = reinterpret_cast(fullPathPtr); fullPath->updateProperties(strokeWidth, strokeColor, strokeAlpha, fillColor, fillAlpha, trimPathStart, trimPathEnd, trimPathOffset, strokeMiterLimit, strokeLineCap, - strokeLineJoin); + strokeLineJoin, fillType); } static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) { @@ -331,7 +331,7 @@ static const JNINativeMethod gMethods[] = { {"nDraw", "(JJJLandroid/graphics/Rect;ZZ)V", (void*)draw}, {"nCreateFullPath", "!()J", (void*)createEmptyFullPath}, {"nCreateFullPath", "!(J)J", (void*)createFullPath}, - {"nUpdateFullPathProperties", "!(JFIFIFFFFFII)V", (void*)updateFullPathPropertiesAndStrokeStyles}, + {"nUpdateFullPathProperties", "!(JFIFIFFFFFIII)V", (void*)updateFullPathPropertiesAndStrokeStyles}, {"nUpdateFullPathFillGradient", "!(JJ)V", (void*)updateFullPathFillGradient}, {"nUpdateFullPathStrokeGradient", "!(JJ)V", (void*)updateFullPathStrokeGradient}, {"nGetFullPathProperties", "(J[BI)Z", (void*)getFullPathProperties}, diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 50c7bfbd0d0f3..a52c4e5ffbf43 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -5876,6 +5876,12 @@ i + + + + + diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 2b0ef4266ee15..4e8740a52fb50 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2706,6 +2706,7 @@ + diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index ae98c22dd4b00..bd069ffeddada 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -1281,8 +1281,10 @@ public class VectorDrawable extends Drawable { private static final int STROKE_LINE_CAP_INDEX = 8; private static final int STROKE_LINE_JOIN_INDEX = 9; private static final int STROKE_MITER_LIMIT_INDEX = 10; - private static final int TOTAL_PROPERTY_COUNT = 11; + private static final int FILL_TYPE_INDEX = 11; + private static final int TOTAL_PROPERTY_COUNT = 12; + // Property map for animatable attributes. private final static HashMap sPropertyMap = new HashMap () { { @@ -1399,6 +1401,7 @@ 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); + int fillType = properties.getInt(FILL_TYPE_INDEX * 4); Shader fillGradient = null; Shader strokeGradient = null; // Account for any configuration changes. @@ -1474,10 +1477,11 @@ public class VectorDrawable extends Drawable { R.styleable.VectorDrawablePath_trimPathOffset, trimPathOffset); trimPathStart = a.getFloat( R.styleable.VectorDrawablePath_trimPathStart, trimPathStart); + fillType = a.getInt(R.styleable.VectorDrawablePath_fillType, fillType); nUpdateFullPathProperties(mNativePtr, strokeWidth, strokeColor, strokeAlpha, fillColor, fillAlpha, trimPathStart, trimPathEnd, trimPathOffset, - strokeMiterLimit, strokeLineCap, strokeLineJoin); + strokeMiterLimit, strokeLineCap, strokeLineJoin, fillType); } @Override @@ -1645,7 +1649,7 @@ public class VectorDrawable extends Drawable { private static native void nUpdateFullPathProperties(long pathPtr, float strokeWidth, int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap, - int strokeLineJoin); + int strokeLineJoin, int fillType); private static native void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr); private static native void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr); diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index 2e3856fafb606..8822fcad458f3 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -158,7 +158,8 @@ const SkPath& FullPath::getUpdatedPath() { void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha, SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, - float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin) { + float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, + int fillType) { mProperties.strokeWidth = strokeWidth; mProperties.strokeColor = strokeColor; mProperties.strokeAlpha = strokeAlpha; @@ -167,6 +168,7 @@ void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float st mProperties.strokeMiterLimit = strokeMiterLimit; mProperties.strokeLineCap = strokeLineCap; mProperties.strokeLineJoin = strokeLineJoin; + mProperties.fillType = fillType; // If any trim property changes, mark trim dirty and update the trim path setTrimPathStart(trimPathStart); @@ -179,7 +181,7 @@ inline SkColor applyAlpha(SkColor color, float alpha) { return SkColorSetA(color, alphaBytes * alpha); } -void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale, +void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale, const SkMatrix& matrix){ // Draw path's fill, if fill color or gradient is valid bool needsFill = false; @@ -196,6 +198,8 @@ void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float str if (needsFill) { mPaint.setStyle(SkPaint::Style::kFill_Style); mPaint.setAntiAlias(true); + SkPath::FillType ft = static_cast(mProperties.fillType); + renderPath.setFillType(ft); outCanvas->drawPath(renderPath, mPaint); } @@ -300,7 +304,7 @@ void FullPath::setPropertyValue(int propertyId, float value) { } } -void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, +void ClipPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale, const SkMatrix& matrix){ outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op); } diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index 36a8aebeaa332..4d2fed096adf0 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -96,7 +96,7 @@ public: protected: virtual const SkPath& getUpdatedPath(); - virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath, + virtual void drawPath(SkCanvas *outCanvas, SkPath& renderPath, float strokeScale, const SkMatrix& matrix) = 0; Data mData; SkPath mSkPath; @@ -118,6 +118,7 @@ struct Properties { int32_t strokeLineCap = SkPaint::Cap::kButt_Cap; int32_t strokeLineJoin = SkPaint::Join::kMiter_Join; float strokeMiterLimit = 4; + int fillType = 0; /* non-zero or kWinding_FillType in Skia */ }; FullPath(const FullPath& path); // for cloning @@ -133,7 +134,7 @@ struct Properties { void updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha, SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, float trimPathOffset, - float strokeMiterLimit, int strokeLineCap, int strokeLineJoin); + float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, int fillType); // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI float getStrokeWidth() { return mProperties.strokeWidth; @@ -197,7 +198,7 @@ struct Properties { protected: const SkPath& getUpdatedPath() override; - void drawPath(SkCanvas* outCanvas, const SkPath& renderPath, + void drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale, const SkMatrix& matrix) override; private: @@ -213,6 +214,7 @@ private: StrokeLineCap, StrokeLineJoin, StrokeMiterLimit, + FillType, Count, }; // Applies trimming to the specified path. @@ -233,7 +235,7 @@ public: ClipPath(const Data& nodes) : Path(nodes) {} protected: - void drawPath(SkCanvas* outCanvas, const SkPath& renderPath, + void drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale, const SkMatrix& matrix) override; }; diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml new file mode 100644 index 0000000000000..d5d86d80269b7 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml @@ -0,0 +1,33 @@ + + + + + + + \ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml new file mode 100644 index 0000000000000..9754e4bed48b4 --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml @@ -0,0 +1,33 @@ + + + + + + + \ 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 495d62010fb8f..5856f49da343c 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java @@ -35,6 +35,8 @@ import java.text.DecimalFormat; public class VectorDrawablePerformance extends Activity { private static final String LOGCAT = "VectorDrawable1"; protected int[] icon = { + R.drawable.vector_icon_filltype_nonzero, + R.drawable.vector_icon_filltype_evenodd, R.drawable.vector_icon_gradient_1, R.drawable.vector_icon_gradient_2, R.drawable.vector_icon_gradient_3,