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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user