Add fillType support to VectorDrawable

Default as non-zero, which is the same as SVG.
b/27533958

Change-Id: Id20e6d3493bb4d2b4b65d7f6cdb13586631c40e4
This commit is contained in:
Teng-Hui Zhu
2016-03-15 14:32:16 -07:00
parent e2578e2d9e
commit 46591f4a2d
12 changed files with 101 additions and 13 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<VectorDrawable::FullPath*>(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},

View File

@@ -5876,6 +5876,12 @@ i
</attr>
<!-- sets the Miter limit for a stroked path -->
<attr name="strokeMiterLimit" format="float"/>
<!-- sets the fillType for a path. It is the same as SVG's "fill-rule" properties.
For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty -->
<attr name="fillType" format="enum">
<enum name="nonZero" value="0"/>
<enum name="evenOdd" value="1"/>
</attr>
</declare-styleable>
<!-- Defines the clip path used in VectorDrawables. -->

View File

@@ -2706,6 +2706,7 @@
<public type="attr" name="canRecord" />
<public type="attr" name="tunerCount" />
<public type="attr" name="nfcAntennaPositionDrawable" />
<public type="attr" name="fillType" />
<public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
<public type="style" name="Widget.Material.SeekBar.Discrete" />

View File

@@ -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<String, Integer> sPropertyMap
= new HashMap<String, Integer> () {
{
@@ -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);

View File

@@ -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<SkPath::FillType>(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);
}

View File

@@ -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;
};

View File

@@ -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.
*/
-->
<vector android:height="24dp" android:viewportHeight="400.0"
android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillType="evenOdd"
android:fillColor="#f00"
android:pathData="M250,75L323,301 131,161 369,161 177,301z"
android:strokeColor="#000" android:strokeWidth="3"/>
<path android:fillType="evenOdd"
android:fillColor="#f00"
android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
android:strokeColor="#000" android:strokeWidth="3"/>
<path android:fillType="evenOdd"
android:fillColor="#f00"
android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
android:strokeColor="#000" android:strokeWidth="3"/>
</vector>

View File

@@ -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.
*/
-->
<vector android:height="24dp" android:viewportHeight="400.0"
android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillType="nonZero"
android:fillColor="#f00"
android:pathData="M250,75L323,301 131,161 369,161 177,301z"
android:strokeColor="#000" android:strokeWidth="3"/>
<path android:fillType="nonZero"
android:fillColor="#f00"
android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
android:strokeColor="#000" android:strokeWidth="3"/>
<path android:fillType="nonZero"
android:fillColor="#f00"
android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
android:strokeColor="#000" android:strokeWidth="3"/>
</vector>

View File

@@ -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,