diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index 36d5b505d4de5..8b57d3d3d6c49 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -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;
}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index a542feb51c748..dbe2f3fa5cf20 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -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;
@@ -956,10 +957,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;
@@ -1025,11 +1032,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 {
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml
new file mode 100644
index 0000000000000..88bf777bdaeae
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml
new file mode 100644
index 0000000000000..530c73b20e44f
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml
new file mode 100644
index 0000000000000..200eb617a9e8b
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale3.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale3.xml
new file mode 100644
index 0000000000000..a40fc9c215958
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale3.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 d029050c2cf4b..b4a93f68f6c99 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -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) {