Add group scaling factor into stroke width.

Originally, stroke width is independent of group scaling.
But that is a bug and causing animation trouble.

b/19501782

Change-Id: I33d5e44f2f8b2a82fee1a5a326223a39aaffa86c
This commit is contained in:
ztenghui
2015-04-01 16:38:44 -07:00
parent 072be09aaf
commit 9af77a4ce2
7 changed files with 276 additions and 8 deletions

View File

@@ -20,7 +20,7 @@ import java.util.Random;
/**
* A class that contains utility methods related to numbers.
*
*
* @hide Pending API council approval
*/
public final class MathUtils {
@@ -32,7 +32,7 @@ public final class MathUtils {
}
public static float abs(float v) {
return v > 0 ? v : -v;
return v > 0 ? v : -v;
}
public static int constrain(int amount, int low, int high) {
@@ -116,6 +116,14 @@ public final class MathUtils {
return v * v;
}
public static float dot(float v1x, float v1y, float v2x, float v2y) {
return v1x * v2x + v1y * v2y;
}
public static float cross(float v1x, float v1y, float v2x, float v2y) {
return v1x * v2y - v1y * v2x;
}
public static float radians(float degrees) {
return degrees * DEG_TO_RAD;
}
@@ -142,16 +150,16 @@ public final class MathUtils {
public static float tan(float angle) {
return (float) Math.tan(angle);
}
}
public static float lerp(float start, float stop, float amount) {
return start + (stop - start) * amount;
}
public static float norm(float start, float stop, float value) {
return (value - start) / (stop - start);
}
public static float map(float minStart, float minStop, float maxStart, float maxStop, float value) {
return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
}
@@ -164,7 +172,7 @@ public final class MathUtils {
if (howsmall >= howbig) return howsmall;
return (int) (sRandom.nextFloat() * (howbig - howsmall) + howsmall);
}
public static float random(float howbig) {
return sRandom.nextFloat() * howbig;
}

View File

@@ -36,6 +36,7 @@ import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.LayoutDirection;
import android.util.Log;
import android.util.MathUtils;
import android.util.PathParser;
import android.util.Xml;
@@ -955,10 +956,16 @@ public class VectorDrawable extends Drawable {
final float scaleX = w / mViewportWidth;
final float scaleY = h / mViewportHeight;
final float minScale = Math.min(scaleX, scaleY);
final Matrix groupStackedMatrix = vGroup.mStackedMatrix;
mFinalPathMatrix.set(vGroup.mStackedMatrix);
mFinalPathMatrix.set(groupStackedMatrix);
mFinalPathMatrix.postScale(scaleX, scaleY);
final float matrixScale = getMatrixScale(groupStackedMatrix);
if (matrixScale == 0) {
// When either x or y is scaled to 0, we don't need to draw anything.
return;
}
vPath.toPath(mPath);
final Path path = mPath;
@@ -1024,11 +1031,41 @@ public class VectorDrawable extends Drawable {
strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
strokePaint.setColorFilter(filter);
strokePaint.setStrokeWidth(fullPath.mStrokeWidth * minScale);
final float finalStrokeScale = minScale * matrixScale;
strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
canvas.drawPath(mRenderPath, strokePaint);
}
}
}
private float getMatrixScale(Matrix groupStackedMatrix) {
// Given unit vectors A = (0, 1) and B = (1, 0).
// After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
// Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
// which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
// If max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
//
// For non-skew case, which is most of the cases, matrix scale is computing exactly the
// scale on x and y axis, and take the minimal of these two.
// For skew case, an unit square will mapped to a parallelogram. And this function will
// return the minimal height of the 2 bases.
float[] unitVectors = new float[] {0, 1, 1, 0};
groupStackedMatrix.mapVectors(unitVectors);
float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]);
float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]);
float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1],
unitVectors[2], unitVectors[3]);
float maxScale = MathUtils.max(scaleX, scaleY);
float matrixScale = 0;
if (maxScale > 0) {
matrixScale = MathUtils.abs(crossProduct) / maxScale;
}
if (DBG_VECTOR_DRAWABLE) {
Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
}
return matrixScale;
}
}
private static class VGroup {

View File

@@ -0,0 +1,57 @@
<!--
Copyright (C) 2015 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:viewportHeight="200"
android:viewportWidth="200"
android:width="64dp" >
<group>
<path
android:name="background1"
android:fillColor="#FF000000"
android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
<path
android:name="background2"
android:fillColor="#FF000000"
android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
</group>
<group
android:pivotX="0"
android:pivotY="0"
android:rotation="90" >
<group
android:scaleX="1.5"
android:scaleY="1" >
<group
android:pivotX="0"
android:pivotY="0"
android:rotation="-90" >
<group
android:scaleX="1.5"
android:scaleY="1" >
<path
android:name="twoLines"
android:fillColor="#FFFF0000"
android:pathData="M 100, 0 l 0, 100, -100, 0 z"
android:strokeColor="#FF00FF00"
android:strokeWidth="10" />
</group>
</group>
</group>
</group>
</vector>

View File

@@ -0,0 +1,52 @@
<!--
Copyright (C) 2015 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:viewportHeight="200"
android:viewportWidth="200"
android:width="64dp" >
<group>
<path
android:name="background1"
android:fillColor="#FF000000"
android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
<path
android:name="background2"
android:fillColor="#FF000000"
android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
</group>
<group
android:scaleX="-1"
android:scaleY="-1" >
<group
android:scaleX="-1"
android:scaleY="-1" >
<group
android:pivotX="100"
android:pivotY="100"
android:rotation="45" >
<path
android:name="twoLines"
android:fillColor="#FFFF0000"
android:pathData="M 100, 0 l 0, 100, -100, 0 z"
android:strokeColor="#FF00FF00"
android:strokeWidth="10" />
</group>
</group>
</group>
</vector>

View File

@@ -0,0 +1,48 @@
<!--
Copyright (C) 2015 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:viewportHeight="200"
android:viewportWidth="200"
android:width="64dp" >
<group>
<path
android:name="background1"
android:fillColor="#FF000000"
android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
<path
android:name="background2"
android:fillColor="#FF000000"
android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
</group>
<group
android:scaleX="2"
android:scaleY="0.5" >
<group
android:pivotX="100"
android:pivotY="100"
android:rotation="45" >
<path
android:name="twoLines"
android:fillColor="#FFFF0000"
android:pathData="M 100, 0 l 0, 100, -100, 0 z"
android:strokeColor="#FF00FF00"
android:strokeWidth="10" />
</group>
</group>
</vector>

View File

@@ -0,0 +1,62 @@
<!--
Copyright (C) 2015 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:viewportHeight="200"
android:viewportWidth="200"
android:width="64dp" >
<group>
<path
android:name="background1"
android:fillColor="#FF000000"
android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
<path
android:name="background2"
android:fillColor="#FF000000"
android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
</group>
<group
android:pivotX="0"
android:pivotY="0"
android:rotation="45" >
<group
android:pivotX="0"
android:pivotY="0"
android:rotation="90" >
<group
android:scaleX="1.5"
android:scaleY="1" >
<group
android:pivotX="0"
android:pivotY="0"
android:rotation="-90" >
<group
android:scaleX="1.5"
android:scaleY="1" >
<path
android:name="twoLines"
android:fillColor="#FFFF0000"
android:pathData="M 100, 0 l 0, 100, -100, 0 z"
android:strokeColor="#FF00FF00"
android:strokeWidth="10" />
</group>
</group>
</group>
</group>
</group>
</vector>

View File

@@ -65,6 +65,10 @@ public class VectorDrawablePerformance extends Activity {
R.drawable.vector_drawable28,
R.drawable.vector_drawable29,
R.drawable.vector_drawable30,
R.drawable.vector_drawable_scale0,
R.drawable.vector_drawable_scale1,
R.drawable.vector_drawable_scale2,
R.drawable.vector_drawable_scale3,
};
public static VectorDrawable create(Resources resources, int rid) {