Add implementation for drawBitmap(Bitmap, Rect, Rect, Paint)

Change-Id: I10904d2325a5431d15801aebcec1048715678e8c
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 5a2e99d..ccf1221 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -403,7 +403,6 @@
     @Override
     public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
             int width, int height, boolean hasAlpha, Paint paint) {
-
         // TODO: Implement
     }
 
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index bd3b18d..cba6ed1 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -196,9 +196,13 @@
         float srcLeft, float srcTop, float srcRight, float srcBottom,
         float dstLeft, float dstTop, float dstRight, float dstBottom,
         SkMatrix* matrix, SkPaint* paint,
-        jint bitmapDenstiy, jint canvasDensity, jint screenDensity) {
-    // TODO: Implement!
-    LOGE("Not implemented: drawBitmap(IIFFFFFFFFIIIII)V");
+        jint bitmapDensity, jint canvasDensity, jint screenDensity) {
+    if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
+        renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
+                dstLeft, dstTop, dstRight, dstBottom, matrix, paint);
+    } else {
+
+    }
 }
 
 static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject canvas,
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 3010f29..091abb0 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -205,12 +205,12 @@
     const float u2 = texCoords.right / float(mWidth);
     const float v2 = (mHeight - texCoords.bottom) / float(mHeight);
 
-    resetDrawTextureTexCoords(u1, v1, u2, v1);
+    resetDrawTextureTexCoords(u1, v1, u2, v2);
 
     drawTextureRect(layer.left, layer.top, layer.right, layer.bottom,
             current->texture, current->alpha, current->mode, true, true);
 
-    resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
+    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
 
     glDeleteFramebuffers(1, &current->fbo);
     glDeleteTextures(1, &current->texture);
@@ -263,9 +263,11 @@
     // The FBO will not be scaled, so we can use lower quality filtering
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
+    // TODO VERY IMPORTANT: Fix TextView to not call saveLayer() all the time
     // TODO ***** IMPORTANT *****
     // Creating a texture-backed FBO works only if the texture is the same size
     // as the original rendering buffer (in this case, mWidth and mHeight.)
@@ -381,32 +383,42 @@
 void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
     Texture* texture = mTextureCache.get(bitmap);
 
-    SkXfermode::Mode mode;
     int alpha;
-
-    if (paint) {
-        const bool isMode = SkXfermode::IsMode(paint->getXfermode(), &mode);
-        if (!isMode) {
-            // Assume SRC_OVER
-            mode = SkXfermode::kSrcOver_Mode;
-        }
-
-        // Skia draws using the color's alpha channel if < 255
-        // Otherwise, it uses the paint's alpha
-        int color = paint->getColor();
-        alpha = (color >> 24) & 0xFF;
-        if (alpha == 255) {
-            alpha = paint->getAlpha();
-        }
-    } else {
-        mode = SkXfermode::kSrcOver_Mode;
-        alpha = 255;
-    }
+    SkXfermode::Mode mode;
+    getAlphaAndMode(paint, &alpha, &mode);
 
     drawTextureRect(left, top, left + texture->width, top + texture->height, texture->id,
             alpha / 255.0f, mode, texture->blend, true);
 }
 
+void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
+         float srcLeft, float srcTop, float srcRight, float srcBottom,
+         float dstLeft, float dstTop, float dstRight, float dstBottom,
+         const SkMatrix* matrix, const SkPaint* paint) {
+    Texture* texture = mTextureCache.get(bitmap);
+
+    int alpha;
+    SkXfermode::Mode mode;
+    getAlphaAndMode(paint, &alpha, &mode);
+
+    const float width = texture->width;
+    const float height = texture->height;
+
+    const float u1 = srcLeft / width;
+    const float v1 = srcTop / height;
+    const float u2 = srcRight / width;
+    const float v2 = srcBottom / height;
+
+    resetDrawTextureTexCoords(u1, v1, u2, v2);
+
+    // TODO: implement Matrix
+
+    drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture->id,
+            alpha / 255.0f, mode, texture->blend, true);
+
+    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+}
+
 void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
     const Rect& clip = mSnapshot->clipRect;
     drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode);
@@ -515,13 +527,34 @@
 
 void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
     mDrawTextureVertices[0].texture[0] = u1;
-    mDrawTextureVertices[0].texture[1] = v2;
+    mDrawTextureVertices[0].texture[1] = v1;
     mDrawTextureVertices[1].texture[0] = u2;
-    mDrawTextureVertices[1].texture[1] = v2;
+    mDrawTextureVertices[1].texture[1] = v1;
     mDrawTextureVertices[2].texture[0] = u1;
-    mDrawTextureVertices[2].texture[1] = v1;
+    mDrawTextureVertices[2].texture[1] = v2;
     mDrawTextureVertices[3].texture[0] = u2;
-    mDrawTextureVertices[3].texture[1] = v1;
+    mDrawTextureVertices[3].texture[1] = v2;
+}
+
+void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
+    if (paint) {
+        const bool isMode = SkXfermode::IsMode(paint->getXfermode(), mode);
+        if (!isMode) {
+            // Assume SRC_OVER
+            *mode = SkXfermode::kSrcOver_Mode;
+        }
+
+        // Skia draws using the color's alpha channel if < 255
+        // Otherwise, it uses the paint's alpha
+        int color = paint->getColor();
+        *alpha = (color >> 24) & 0xFF;
+        if (*alpha == 255) {
+            *alpha = paint->getAlpha();
+        }
+    } else {
+        *mode = SkXfermode::kSrcOver_Mode;
+        *alpha = 255;
+    }
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 965188f..a698e79 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -103,6 +103,9 @@
     bool clipRect(float left, float top, float right, float bottom);
 
     void drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint);
+    void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
+            float dstLeft, float dstTop, float dstRight, float dstBottom,
+            const SkMatrix* matrix, const SkPaint* paint);
     void drawColor(int color, SkXfermode::Mode mode);
     void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
 
@@ -193,7 +196,7 @@
      * Resets the texture coordinates stored in mDrawTextureVertices. Setting the values
      * back to default is achieved by calling:
      *
-     * resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
+     * resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
      *
      * @param u1 The left coordinate of the texture
      * @param v1 The bottom coordinate of the texture
@@ -202,6 +205,16 @@
      */
     void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2);
 
+    /**
+     * Gets the alpha and xfermode out of a paint object. If the paint is null
+     * alpha will be 255 and the xfermode will be SRC_OVER.
+     *
+     * @param paint The paint to extract values from
+     * @param alpha Where to store the resulting alpha
+     * @param mode Where to store the resulting xfermode
+     */
+    inline void getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
+
     // Dimensions of the drawing surface
     int mWidth, mHeight;
 
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 4e16507..7b8b313 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -92,6 +92,7 @@
 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 7a00c67..79eed4e 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -59,6 +59,16 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        
+        <activity
+                android:name="BitmapsRectActivity"
+                android:label="_BitmapsRect"
+                android:theme="@android:style/Theme.Translucent.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
                 
     </application>
 </manifest>
diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/BitmapsRectActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/BitmapsRectActivity.java
new file mode 100644
index 0000000..f8726c2
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/BitmapsRectActivity.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+package com.google.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class BitmapsRectActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final BitmapsView view = new BitmapsView(this);
+        setContentView(view);
+    }
+
+    static class BitmapsView extends View {
+        private Paint mBitmapPaint;
+        private final Bitmap mBitmap1;
+        private final Bitmap mBitmap2;
+        private final Rect mSrcRect;
+        private final RectF mDstRect;
+        private final RectF mDstRect2;
+
+        BitmapsView(Context c) {
+            super(c);
+
+            mBitmap1 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1);
+            mBitmap2 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset2);
+
+            mBitmapPaint = new Paint();
+            mBitmapPaint.setFilterBitmap(true);
+
+            final float fourth = mBitmap1.getWidth() / 4.0f;
+            final float half = mBitmap1.getHeight() / 2.0f;
+            mSrcRect = new Rect((int) fourth, (int) (half - half / 2.0f),
+                    (int) (fourth + fourth), (int) (half + half / 2.0f));
+            mDstRect = new RectF(fourth, half - half / 2.0f, fourth + fourth, half + half / 2.0f);
+            mDstRect2 = new RectF(fourth, half - half / 2.0f,
+                    (fourth + fourth) * 3.0f, (half + half / 2.0f) * 3.0f);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+
+            canvas.translate(120.0f, 50.0f);
+            canvas.drawBitmap(mBitmap1, mSrcRect, mDstRect, mBitmapPaint);
+
+            canvas.translate(0.0f, mBitmap1.getHeight());
+            canvas.translate(-100.0f, 25.0f);
+            canvas.drawBitmap(mBitmap1, mSrcRect, mDstRect2, mBitmapPaint);
+        }
+    }
+}
\ No newline at end of file