Loading core/java/android/util/MathUtils.java +14 −6 Original line number Diff line number Diff line Loading @@ -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; } Loading graphics/java/android/graphics/drawable/VectorDrawable.java +39 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 { Loading tests/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml 0 → 100644 +57 −0 Original line number Diff line number Diff line <!-- 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> No newline at end of file tests/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml 0 → 100644 +52 −0 Original line number Diff line number Diff line <!-- 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> No newline at end of file tests/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml 0 → 100644 +48 −0 Original line number Diff line number Diff line <!-- 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> No newline at end of file Loading
core/java/android/util/MathUtils.java +14 −6 Original line number Diff line number Diff line Loading @@ -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; } Loading
graphics/java/android/graphics/drawable/VectorDrawable.java +39 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 { Loading
tests/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml 0 → 100644 +57 −0 Original line number Diff line number Diff line <!-- 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> No newline at end of file
tests/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml 0 → 100644 +52 −0 Original line number Diff line number Diff line <!-- 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> No newline at end of file
tests/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml 0 → 100644 +48 −0 Original line number Diff line number Diff line <!-- 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> No newline at end of file