Fix GC issue, fix local shader transformations.

Change-Id: I208bdf89815dcd18dcadd43df932a77362918435
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 4c92942..4ba679b 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -22,6 +22,12 @@
  */
 public class BitmapShader extends Shader {
     /**
+     * Prevent garbage collection.
+     */
+    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
+    private final Bitmap mBitmap;
+
+    /**
      * Call this to create a new shader that will draw with a bitmap.
      *
      * @param bitmap            The bitmap to use inside the shader
@@ -29,6 +35,7 @@
      * @param tileY             The tiling mode for y to draw the bitmap in.
      */
     public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY) {
+        mBitmap = bitmap;
         final int b = bitmap.ni();
         native_instance = nativeCreate(b, tileX.nativeInt, tileY.nativeInt);
         native_shader = nativePostCreate(native_instance, b, tileX.nativeInt, tileY.nativeInt);
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index c64b483..74d50e4 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -80,7 +80,7 @@
 
     data[kScaleZ] = 1.0f;
 
-    mSimpleMatrix = (!v[SkMatrix::kMPersp0] && !v[SkMatrix::kMPersp1] && !v[SkMatrix::kMPersp2]);
+    mSimpleMatrix = (v.getType() <= SkMatrix::kScale_Mask);
 }
 
 void Matrix4::copyTo(SkMatrix& v) const {
@@ -232,9 +232,26 @@
     data[kTranslateZ] = -(far + near) / (far - near);
 }
 
+#define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c)
+
+void Matrix4::mapPoint(float& x, float& y) const {
+    if (mSimpleMatrix) {
+        MUL_ADD_STORE(x, data[kScaleX], data[kTranslateX]);
+        MUL_ADD_STORE(y, data[kScaleY], data[kTranslateY]);
+        return;
+    }
+
+    float dx = x * data[kScaleX] + y * data[kSkewX] + data[kTranslateX];
+    float dy = x * data[kSkewY] + y * data[kScaleY] + data[kTranslateY];
+    float dz = x * data[kPerspective0] + y * data[kPerspective1] + data[kPerspective2];
+    if (dz) dz = 1.0f / dz;
+
+    x = dx * dz;
+    y = dy * dz;
+}
+
 void Matrix4::mapRect(Rect& r) const {
     if (mSimpleMatrix) {
-        #define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c)
         MUL_ADD_STORE(r.left, data[kScaleX], data[kTranslateX]);
         MUL_ADD_STORE(r.right, data[kScaleX], data[kTranslateX]);
         MUL_ADD_STORE(r.top, data[kScaleY], data[kTranslateY]);
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index ebc8b29..c247a67 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -104,10 +104,8 @@
     void copyTo(float* v) const;
     void copyTo(SkMatrix& v) const;
 
-    /**
-     * Does not apply rotations!
-     */
     void mapRect(Rect& r) const;
+    void mapPoint(float& x, float& y) const;
 
     float getTranslateX();
     float getTranslateY();
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 3569d6a..c7a01b1 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -164,7 +164,8 @@
     Rect start(mBounds[0], mBounds[1], mBounds[2], mBounds[3]);
     if (mMatrix) {
         mat4 shaderMatrix(*mMatrix);
-        shaderMatrix.mapRect(start);
+        shaderMatrix.mapPoint(start.left, start.top);
+        shaderMatrix.mapPoint(start.right, start.bottom);
     }
     snapshot.transform.mapRect(start);