am 094c82ad: Merge "Scaling (Animated)VectorDrawable inside ImageView" into mnc-dev

* commit '094c82ada3799045588790252a64806b9930f8c2':
  Scaling (Animated)VectorDrawable inside ImageView
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 24cb055..1cfccc4 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -200,6 +200,11 @@
     private static final int LINEJOIN_ROUND = 1;
     private static final int LINEJOIN_BEVEL = 2;
 
+    // Cap the bitmap size, such that it won't hurt the performance too much
+    // and it won't crash due to a very large scale.
+    // The drawable will look blurry above this size.
+    private static final int MAX_CACHED_BITMAP_SIZE = 2048;
+
     private static final boolean DBG_VECTOR_DRAWABLE = false;
 
     private VectorDrawableState mVectorState;
@@ -219,6 +224,11 @@
     private int mDpiScaledHeight = 0;
     private Insets mDpiScaleInsets = Insets.NONE;
 
+    // Temp variable, only for saving "new" operation at the draw() time.
+    private final float[] mTmpFloats = new float[9];
+    private final Matrix mTmpMatrix = new Matrix();
+    private final Rect mTmpBounds = new Rect();
+
     public VectorDrawable() {
         this(null, null);
     }
@@ -262,44 +272,59 @@
 
     @Override
     public void draw(Canvas canvas) {
-        final Rect bounds = getBounds();
-        if (bounds.width() <= 0 || bounds.height() <= 0) {
+        // We will offset the bounds for drawBitmap, so copyBounds() here instead
+        // of getBounds().
+        copyBounds(mTmpBounds);
+        if (mTmpBounds.width() <= 0 || mTmpBounds.height() <= 0) {
             // Nothing to draw
             return;
         }
 
-        final int saveCount = canvas.save();
-        final boolean needMirroring = needMirroring();
+        // Color filters always override tint filters.
+        final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter);
 
-        canvas.translate(bounds.left, bounds.top);
+        // The imageView can scale the canvas in different ways, in order to
+        // avoid blurry scaling, we have to draw into a bitmap with exact pixel
+        // size first. This bitmap size is determined by the bounds and the
+        // canvas scale.
+        canvas.getMatrix(mTmpMatrix);
+        mTmpMatrix.getValues(mTmpFloats);
+        float canvasScaleX = Math.abs(mTmpFloats[Matrix.MSCALE_X]);
+        float canvasScaleY = Math.abs(mTmpFloats[Matrix.MSCALE_Y]);
+        int scaledWidth = (int) (mTmpBounds.width() * canvasScaleX);
+        int scaledHeight = (int) (mTmpBounds.height() * canvasScaleY);
+        scaledWidth = Math.min(MAX_CACHED_BITMAP_SIZE, scaledWidth);
+        scaledHeight = Math.min(MAX_CACHED_BITMAP_SIZE, scaledHeight);
+
+        if (scaledWidth <= 0 || scaledHeight <= 0) {
+            return;
+        }
+
+        final int saveCount = canvas.save();
+        canvas.translate(mTmpBounds.left, mTmpBounds.top);
+
+        // Handle RTL mirroring.
+        final boolean needMirroring = needMirroring();
         if (needMirroring) {
-            canvas.translate(bounds.width(), 0);
+            canvas.translate(mTmpBounds.width(), 0);
             canvas.scale(-1.0f, 1.0f);
         }
 
-        // Color filters always override tint filters.
-        final ColorFilter colorFilter = mColorFilter == null ? mTintFilter : mColorFilter;
+        // At this point, canvas has been translated to the right position.
+        // And we use this bound for the destination rect for the drawBitmap, so
+        // we offset to (0, 0);
+        mTmpBounds.offsetTo(0, 0);
 
+        mVectorState.createCachedBitmapIfNeeded(scaledWidth, scaledHeight);
         if (!mAllowCaching) {
-            // AnimatedVectorDrawable
-            if (!mVectorState.hasTranslucentRoot()) {
-                mVectorState.mVPathRenderer.draw(
-                        canvas, bounds.width(), bounds.height(), colorFilter);
-            } else {
-                mVectorState.createCachedBitmapIfNeeded(bounds);
-                mVectorState.updateCachedBitmap(bounds);
-                mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
-            }
+            mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
         } else {
-            // Static Vector Drawable case.
-            mVectorState.createCachedBitmapIfNeeded(bounds);
             if (!mVectorState.canReuseCache()) {
-                mVectorState.updateCachedBitmap(bounds);
+                mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
                 mVectorState.updateCacheStates();
             }
-            mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
         }
-
+        mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter, mTmpBounds);
         canvas.restoreToCount(saveCount);
     }
 
@@ -770,10 +795,11 @@
             }
         }
 
-        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter) {
+        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter,
+                Rect originalBounds) {
             // The bitmap's size is the same as the bounds.
             final Paint p = getPaint(filter);
-            canvas.drawBitmap(mCachedBitmap, 0, 0, p);
+            canvas.drawBitmap(mCachedBitmap, null, originalBounds, p);
         }
 
         public boolean hasTranslucentRoot() {
@@ -797,16 +823,15 @@
             return mTempPaint;
         }
 
-        public void updateCachedBitmap(Rect bounds) {
+        public void updateCachedBitmap(int width, int height) {
             mCachedBitmap.eraseColor(Color.TRANSPARENT);
             Canvas tmpCanvas = new Canvas(mCachedBitmap);
-            mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height(), null);
+            mVPathRenderer.draw(tmpCanvas, width, height, null);
         }
 
-        public void createCachedBitmapIfNeeded(Rect bounds) {
-            if (mCachedBitmap == null || !canReuseBitmap(bounds.width(),
-                    bounds.height())) {
-                mCachedBitmap = Bitmap.createBitmap(bounds.width(), bounds.height(),
+        public void createCachedBitmapIfNeeded(int width, int height) {
+            if (mCachedBitmap == null || !canReuseBitmap(width, height)) {
+                mCachedBitmap = Bitmap.createBitmap(width, height,
                         Bitmap.Config.ARGB_8888);
                 mCacheDirty = true;
             }
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/ScaleDrawableTests.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/ScaleDrawableTests.java
index 3787843..c5be6c4 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/ScaleDrawableTests.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/ScaleDrawableTests.java
@@ -37,8 +37,8 @@
     };
 
     protected int icon = R.drawable.bitmap_drawable01;
-
     protected int vector_icon = R.drawable.vector_drawable16;
+    protected int animated_vector_icon = R.drawable.ic_hourglass_animation;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -46,12 +46,12 @@
         ScrollView scrollView = new ScrollView(this);
         GridLayout container = new GridLayout(this);
         scrollView.addView(container);
-        container.setColumnCount(3);
+        container.setColumnCount(4);
         container.setBackgroundColor(0xFF888888);
 
         LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
-        params.width = 400;
-        params.height = 300;
+        params.width = 300;
+        params.height = 200;
 
         for (int i = 0; i < scaleTypes.length; i++) {
             TextView t = new TextView(this);
@@ -71,6 +71,13 @@
             view.setScaleType(scaleType);
             view.setImageResource(vector_icon);
             container.addView(view);
+
+            ImageView avd_view = new ImageView(this);
+            avd_view.setLayoutParams(params);
+            avd_view.setScaleType(scaleType);
+            avd_view.setImageResource(animated_vector_icon);
+            container.addView(avd_view);
+
         }
 
         setContentView(scrollView);