Share code in various SkGPipeCanvas::drawBitmap_ calls.
authorscroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 30 Jul 2012 14:40:01 +0000 (14:40 +0000)
committerscroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 30 Jul 2012 14:40:01 +0000 (14:40 +0000)
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

gm/bitmapmatrix.cpp [new file with mode: 0644]
gyp/gmslides.gypi
src/pipe/SkGPipePriv.h
src/pipe/SkGPipeRead.cpp
src/pipe/SkGPipeWrite.cpp

diff --git a/gm/bitmapmatrix.cpp b/gm/bitmapmatrix.cpp
new file mode 100644 (file)
index 0000000..d05dbeb
--- /dev/null
@@ -0,0 +1,103 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "gm.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColor.h"
+#include "SkMatrix.h"
+#include "SkPath.h"
+#include "SkRect.h"
+#include "SkSize.h"
+#include "SkString.h"
+
+namespace skiagm {
+
+class DrawBitmapMatrixGM : public GM {
+public:
+    DrawBitmapMatrixGM() {}
+
+protected:
+    virtual SkString onShortName() SK_OVERRIDE {
+        return SkString("drawbitmapmatrix");
+    }
+
+    virtual SkISize onISize() SK_OVERRIDE { return make_isize(1024, 256); }
+
+    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+        SkBitmap bm;
+        this->setupBitmap(&bm);
+
+        // Draw normally.
+        SkMatrix matrix;
+        matrix.reset();
+        SkPaint paint;
+        paint.setAntiAlias(true);
+        paint.setDither(true);
+        canvas->drawBitmapMatrix(bm, matrix, &paint);
+
+        // Draw stretched horizontally and squished vertically.
+        canvas->translate(SkIntToScalar(bm.width() + 5), 0);
+        matrix.setScale(SkIntToScalar(2), SK_ScalarHalf);
+        canvas->drawBitmapMatrix(bm, matrix, &paint);
+
+        // Draw rotated
+        canvas->translate(SkIntToScalar(bm.width()*2 + 5), 0);
+        matrix.reset();
+        matrix.setRotate(SkIntToScalar(45), SkIntToScalar(bm.width() / 2),
+                         SkIntToScalar(bm.height() / 2));
+        canvas->save();
+        canvas->translate(0, SkIntToScalar(10));
+        canvas->drawBitmapMatrix(bm, matrix, &paint);
+        canvas->restore();
+
+        // Draw with perspective
+        canvas->translate(SkIntToScalar(bm.width() + 15), 0);
+        matrix.reset();
+        matrix.setPerspX(SkScalarDiv(SK_Scalar1, SkIntToScalar(1000)));
+        matrix.setPerspY(SkScalarDiv(SK_Scalar1, SkIntToScalar(1000)));
+        canvas->drawBitmapMatrix(bm, matrix, &paint);
+
+        // Draw with skew
+        canvas->translate(SkIntToScalar(bm.width() + 5), 0);
+        matrix.reset();
+        matrix.setSkew(SkIntToScalar(2), SkIntToScalar(2));
+        canvas->drawBitmapMatrix(bm, matrix, &paint);
+
+        // Draw with sin/cos
+        canvas->translate(SkIntToScalar(bm.width() * 4), 0);
+        matrix.reset();
+        matrix.setSinCos(SK_ScalarHalf, SkIntToScalar(2));
+        canvas->drawBitmapMatrix(bm, matrix, &paint);
+    }
+private:
+    void setupBitmap(SkBitmap* bm) {
+        SkASSERT(bm);
+        static const int SIZE = 64;
+        bm->setConfig(SkBitmap::kARGB_8888_Config, SIZE, SIZE);
+        bm->allocPixels();
+        SkCanvas canvas(*bm);
+
+        SkPaint paint;
+        paint.setColor(SK_ColorGREEN);
+        canvas.drawPaint(paint);
+
+        paint.setColor(SK_ColorBLUE);
+        paint.setAntiAlias(true);
+        SkRect rect = SkRect::MakeWH(SkIntToScalar(SIZE), SkIntToScalar(SIZE));
+        SkPath path;
+        path.addOval(rect);
+        canvas.drawPath(path, paint);
+    }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new DrawBitmapMatrixGM; }
+static GMRegistry reg(MyFactory);
+
+}
index 5e25eb3..18592d6 100644 (file)
@@ -6,6 +6,7 @@
     '../gm/arithmode.cpp',
     '../gm/bigmatrix.cpp',
     '../gm/bitmapcopy.cpp',
+    '../gm/bitmapmatrix.cpp',
     '../gm/bitmapfilters.cpp',
     '../gm/bitmapscroll.cpp',
     '../gm/blurs.cpp',
index 3f8a748..d9a36e9 100644 (file)
@@ -137,6 +137,12 @@ enum {
     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,
+};
 
 ///////////////////////////////////////////////////////////////////////////////
 
index 450f19c..41650b1 100644 (file)
@@ -407,7 +407,7 @@ BitmapHolder::BitmapHolder(SkReader32* reader, uint32_t op32,
 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 drawBitmap_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
 
 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 drawBitmapNine_rp(SkCanvas* canvas, SkReader32* reader,
 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 drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader,
 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);
 }
index 66cde1b..9efc0b5 100644 (file)
@@ -483,6 +483,17 @@ private:
     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::drawPath(const SkPath& path, const SkPaint& paint) {
     }
 }
 
-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;
-        }
+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);
+    }
+    int bitmapIndex = this->flattenToIndex(bm);
+    if (this->needOpBytes(opBytesNeeded)) {
+        this->writeOp(op, flags, bitmapIndex);
+        return true;
     }
+    return false;
+}
 
-    NOTIFY_SETUP(this);
-    if (paint) {
+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);
     }
-
-    size_t opBytesNeeded = sizeof(SkScalar) * 2 + sizeof(bool);
-    if (!flatten) {
-        opBytesNeeded += sizeof(void*);
+    if (this->needOpBytes(opBytesNeeded + sizeof(void*))) {
+        this->writeOp(op, flags, 0);
+        fWriter.writePtr(const_cast<void*>(ptr));
+        return true;
     }
-    if (this->needOpBytes(opBytesNeeded)) {
-        this->writeOp(kDrawBitmap_DrawOp, 0, bitmapIndex);
-        if (!flatten) {
-            fWriter.writePtr(const_cast<void*>(ptr));
-        }
-        fWriter.writeBool(paint != NULL);
+    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) + sizeof(bool) * 2;
+    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;
     }
-    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::drawBitmapRect(const SkBitmap& bm, const SkIRect* src,
     }
 }
 
-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::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
 
 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);
     }