Share code in various SkGPipeCanvas::drawBitmap_ calls.

Also implement SkGPipeCanvas::drawBitmapMatrix, and
create a GM to make sure it works properly.

Use a flag instead of writing a bool for determining whether
drawBitmap_ has a paint and whether drawBitmapRect has a source
rectangle.

BUG=
TEST=drawbitmapmatrix GM

Review URL: https://codereview.appspot.com/6450053

git-svn-id: http://skia.googlecode.com/svn/trunk@4828 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/pipe/SkGPipePriv.h b/src/pipe/SkGPipePriv.h
index 3f8a748..d9a36e9 100644
--- a/src/pipe/SkGPipePriv.h
+++ b/src/pipe/SkGPipePriv.h
@@ -137,6 +137,12 @@
     kDrawVertices_HasColors_DrawOpFlag   = 1 << 1,
     kDrawVertices_HasIndices_DrawOpFlag  = 1 << 2,
 };
+enum {
+    kDrawBitmap_HasPaint_DrawOpsFlag   = 1 << 0,
+    // Specific to drawBitmapRect, but needs to be different from HasPaint,
+    // which is used for all drawBitmap calls, so include it here.
+    kDrawBitmap_HasSrcRect_DrawOpsFlag = 1 << 1,
+};
 
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp
index 450f19c..41650b1 100644
--- a/src/pipe/SkGPipeRead.cpp
+++ b/src/pipe/SkGPipeRead.cpp
@@ -407,7 +407,7 @@
 static void drawBitmap_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
                           SkGPipeState* state) {
     BitmapHolder holder(reader, op32, state);
-    bool hasPaint = reader->readBool();
+    bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpsFlag);
     SkScalar left = reader->readScalar();
     SkScalar top = reader->readScalar();
     canvas->drawBitmap(*holder.getBitmap(), left, top, hasPaint ? &state->paint() : NULL);
@@ -415,13 +415,18 @@
 
 static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
                                 SkGPipeState* state) {
-    UNIMPLEMENTED
+    BitmapHolder holder(reader, op32, state);
+    bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpsFlag);
+    SkMatrix matrix;
+    reader->readMatrix(&matrix);
+    canvas->drawBitmapMatrix(*holder.getBitmap(), matrix,
+                             hasPaint ? &state->paint() : NULL);
 }
 
 static void drawBitmapNine_rp(SkCanvas* canvas, SkReader32* reader,
                               uint32_t op32, SkGPipeState* state) {
     BitmapHolder holder(reader, op32, state);
-    bool hasPaint = reader->readBool();
+    bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpsFlag);
     const SkIRect* center = skip<SkIRect>(reader);
     const SkRect* dst = skip<SkRect>(reader);
     canvas->drawBitmapNine(*holder.getBitmap(), *center, *dst,
@@ -431,8 +436,9 @@
 static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader,
                               uint32_t op32, SkGPipeState* state) {
     BitmapHolder holder(reader, op32, state);
-    bool hasPaint = reader->readBool();
-    bool hasSrc = reader->readBool();
+    unsigned flags = DrawOp_unpackFlags(op32);
+    bool hasPaint = SkToBool(flags & kDrawBitmap_HasPaint_DrawOpsFlag);
+    bool hasSrc = SkToBool(flags & kDrawBitmap_HasSrcRect_DrawOpsFlag);
     const SkIRect* src;
     if (hasSrc) {
         src = skip<SkIRect>(reader);
@@ -446,7 +452,7 @@
 static void drawSprite_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
                           SkGPipeState* state) {
     BitmapHolder holder(reader, op32, state);
-    bool hasPaint = reader->readBool();
+    bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpsFlag);
     const SkIPoint* point = skip<SkIPoint>(reader);
     canvas->drawSprite(*holder.getBitmap(), point->fX, point->fY, hasPaint ? &state->paint() : NULL);
 }
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index 66cde1b..9efc0b5 100644
--- a/src/pipe/SkGPipeWrite.cpp
+++ b/src/pipe/SkGPipeWrite.cpp
@@ -483,6 +483,17 @@
     int fCurrFlatIndex[kCount_PaintFlats];
     int flattenToIndex(SkFlattenable* obj, PaintFlats);
 
+    // Common code used by drawBitmap* when flattening.
+    bool commonDrawBitmapFlatten(const SkBitmap& bm, DrawOps op, unsigned flags,
+                                 size_t opBytesNeeded, const SkPaint* paint);
+    // Common code used by drawBitmap* when storing in the heap.
+    bool commonDrawBitmapHeap(const SkBitmap& bm, DrawOps op, unsigned flags,
+                              size_t opBytesNeeded, const SkPaint* paint);
+    // Convenience type for function pointer
+    typedef bool (SkGPipeCanvas::*BitmapCommonFunction)(const SkBitmap&,
+                                                        DrawOps, unsigned,
+                                                        size_t, const SkPaint*);
+
     SkPaint fPaint;
     void writePaint(const SkPaint&);
 
@@ -831,74 +842,75 @@
     }
 }
 
-void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
-                                   const SkPaint* paint) {
-    bool flatten = shouldFlattenBitmaps(fFlags);
-    const void* ptr = 0;
-    int bitmapIndex = 0;
-    if (flatten) {
-        bitmapIndex = this->flattenToIndex(bm);
-    } else {
-        ptr = fSharedHeap.addBitmap(bm);
-        if (NULL == ptr) {
-            return;
-        }
-    }
-
-    NOTIFY_SETUP(this);
-    if (paint) {
+bool SkGPipeCanvas::commonDrawBitmapFlatten(const SkBitmap& bm, DrawOps op,
+                                            unsigned flags,
+                                            size_t opBytesNeeded,
+                                            const SkPaint* paint) {
+    if (paint != NULL) {
+        flags |= kDrawBitmap_HasPaint_DrawOpsFlag;
         this->writePaint(*paint);
     }
-
-    size_t opBytesNeeded = sizeof(SkScalar) * 2 + sizeof(bool);
-    if (!flatten) {
-        opBytesNeeded += sizeof(void*);
-    }
+    int bitmapIndex = this->flattenToIndex(bm);
     if (this->needOpBytes(opBytesNeeded)) {
-        this->writeOp(kDrawBitmap_DrawOp, 0, bitmapIndex);
-        if (!flatten) {
-            fWriter.writePtr(const_cast<void*>(ptr));
-        }
-        fWriter.writeBool(paint != NULL);
+        this->writeOp(op, flags, bitmapIndex);
+        return true;
+    }
+    return false;
+}
+
+bool SkGPipeCanvas::commonDrawBitmapHeap(const SkBitmap& bm, DrawOps op,
+                                         unsigned flags,
+                                         size_t opBytesNeeded,
+                                         const SkPaint* paint) {
+    const void* ptr = fSharedHeap.addBitmap(bm);
+    if (NULL == ptr) {
+        return false;
+    }
+    if (paint != NULL) {
+        flags |= kDrawBitmap_HasPaint_DrawOpsFlag;
+        this->writePaint(*paint);
+    }
+    if (this->needOpBytes(opBytesNeeded + sizeof(void*))) {
+        this->writeOp(op, flags, 0);
+        fWriter.writePtr(const_cast<void*>(ptr));
+        return true;
+    }
+    return false;
+}
+
+void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
+                               const SkPaint* paint) {
+    NOTIFY_SETUP(this);
+    size_t opBytesNeeded = sizeof(SkScalar) * 2;
+
+    BitmapCommonFunction bitmapCommon = shouldFlattenBitmaps(fFlags) ?
+            &SkGPipeCanvas::commonDrawBitmapFlatten :
+            &SkGPipeCanvas::commonDrawBitmapHeap;
+
+    if ((*this.*bitmapCommon)(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) {
         fWriter.writeScalar(left);
         fWriter.writeScalar(top);
     }
 }
 
 void SkGPipeCanvas::drawBitmapRect(const SkBitmap& bm, const SkIRect* src,
-                                       const SkRect& dst, const SkPaint* paint) {
-    bool flatten = shouldFlattenBitmaps(fFlags);
-    const void* ptr = 0;
-    int bitmapIndex = 0;
-    if (flatten) {
-        bitmapIndex = this->flattenToIndex(bm);
-    } else {
-        ptr = fSharedHeap.addBitmap(bm);
-        if (NULL == ptr) {
-            return;
-        }
-    }
-
+                                   const SkRect& dst, const SkPaint* paint) {
     NOTIFY_SETUP(this);
-    if (paint) {
-        this->writePaint(*paint);
+    size_t opBytesNeeded = sizeof(SkRect);
+    bool hasSrc = src != NULL;
+    unsigned flags;
+    if (hasSrc) {
+        flags = kDrawBitmap_HasSrcRect_DrawOpsFlag;
+        opBytesNeeded += sizeof(int32_t) * 4;
+    } else {
+        flags = 0;
     }
 
-    size_t opBytesNeeded = sizeof(SkRect) + sizeof(bool) * 2;
-    bool hasSrc = src != NULL;
-    if (hasSrc) {
-        opBytesNeeded += sizeof(int32_t) * 4;
-    }
-    if (!flatten) {
-        opBytesNeeded += sizeof(void*);
-    }
-    if (this->needOpBytes(opBytesNeeded)) {
-        this->writeOp(kDrawBitmapRect_DrawOp, 0, bitmapIndex);
-        if (!flatten) {
-            fWriter.writePtr(const_cast<void*>(ptr));
-        }
-        fWriter.writeBool(paint != NULL);
-        fWriter.writeBool(hasSrc);
+    BitmapCommonFunction bitmapCommon = shouldFlattenBitmaps(fFlags) ?
+            &SkGPipeCanvas::commonDrawBitmapFlatten :
+            &SkGPipeCanvas::commonDrawBitmapHeap;
+    
+    if ((*this.*bitmapCommon)(bm, kDrawBitmapRect_DrawOp, flags, opBytesNeeded, paint)) {
         if (hasSrc) {
             fWriter.write32(src->fLeft);
             fWriter.write32(src->fTop);
@@ -909,40 +921,30 @@
     }
 }
 
-void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
-                                         const SkPaint*) {
-    UNIMPLEMENTED
+void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap& bm, const SkMatrix& matrix,
+                                     const SkPaint* paint) {
+    NOTIFY_SETUP(this);
+    size_t opBytesNeeded = matrix.writeToMemory(NULL);
+    
+    BitmapCommonFunction bitmapCommon = shouldFlattenBitmaps(fFlags) ?
+        &SkGPipeCanvas::commonDrawBitmapFlatten :
+        &SkGPipeCanvas::commonDrawBitmapHeap;
+
+    if ((*this.*bitmapCommon)(bm, kDrawBitmapMatrix_DrawOp, 0, opBytesNeeded, paint)) {
+        fWriter.writeMatrix(matrix);
+    }
 }
 
 void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
                                    const SkRect& dst, const SkPaint* paint) {
-    bool flatten = shouldFlattenBitmaps(fFlags);
-    const void* ptr = 0;
-    int bitmapIndex = 0;
-    if (flatten) {
-        bitmapIndex = this->flattenToIndex(bm);
-    } else {
-        ptr = fSharedHeap.addBitmap(bm);
-        if (NULL == ptr) {
-            return;
-        }
-    }
-
     NOTIFY_SETUP(this);
-    if (paint) {
-        this->writePaint(*paint);
-    }
+    size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(SkRect);
 
-    size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(bool) + sizeof(SkRect);
-    if (!flatten) {
-        opBytesNeeded += sizeof(void*);
-    }
-    if (this->needOpBytes(opBytesNeeded)) {
-        this->writeOp(kDrawBitmapNine_DrawOp, 0, bitmapIndex);
-        if (!flatten) {
-            fWriter.writePtr(const_cast<void*>(ptr));
-        }
-        fWriter.writeBool(paint != NULL);
+    BitmapCommonFunction bitmapCommon = shouldFlattenBitmaps(fFlags) ?
+            &SkGPipeCanvas::commonDrawBitmapFlatten :
+            &SkGPipeCanvas::commonDrawBitmapHeap;
+
+    if ((*this.*bitmapCommon)(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, paint)) {
         fWriter.write32(center.fLeft);
         fWriter.write32(center.fTop);
         fWriter.write32(center.fRight);
@@ -953,33 +955,14 @@
 
 void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
                                    const SkPaint* paint) {
-    bool flatten = shouldFlattenBitmaps(fFlags);
-    const void* ptr = 0;
-    int bitmapIndex = 0;
-    if (flatten) {
-        bitmapIndex = this->flattenToIndex(bm);
-    } else {
-        ptr = fSharedHeap.addBitmap(bm);
-        if (NULL == ptr) {
-            return;
-        }
-    }
-
     NOTIFY_SETUP(this);
-    if (paint) {
-        this->writePaint(*paint);
-    }
+    size_t opBytesNeeded = sizeof(int32_t) * 2;
 
-    size_t opBytesNeeded = sizeof(int32_t) * 2 + sizeof(bool);
-    if (!flatten) {
-        opBytesNeeded += sizeof(void*);
-    }
-    if (this->needOpBytes(opBytesNeeded)) {
-        this->writeOp(kDrawSprite_DrawOp, 0, bitmapIndex);
-        if (!flatten) {
-            fWriter.writePtr(const_cast<void*>(ptr));
-        }
-        fWriter.writeBool(paint != NULL);
+    BitmapCommonFunction bitmapCommon = shouldFlattenBitmaps(fFlags) ?
+            &SkGPipeCanvas::commonDrawBitmapFlatten :
+            &SkGPipeCanvas::commonDrawBitmapHeap;
+
+    if ((*this.*bitmapCommon)(bm, kDrawSprite_DrawOp, 0, opBytesNeeded, paint)) {
         fWriter.write32(left);
         fWriter.write32(top);
     }