Fixes for drawing through an SkGPipe.

Implement SkGPipeCanvas::drawBitmap.

Fix a bug where needOpBytes did not necessarily provide as
many bytes as requested.

Fix a bug where needOpBytes would wipe old data without
calling notify.

Register SkEmbossMaskFilter so it can be flattened.

Override drawBitmapNine (currently unimplemented) so an
SkGPipeCanvas does not call its base class' method (which
would fail).
Review URL: https://codereview.appspot.com/6071045

git-svn-id: http://skia.googlecode.com/svn/trunk@3741 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/effects/SkEmbossMaskFilter.cpp b/src/effects/SkEmbossMaskFilter.cpp
index 245ccd6..f275cbe 100644
--- a/src/effects/SkEmbossMaskFilter.cpp
+++ b/src/effects/SkEmbossMaskFilter.cpp
@@ -131,3 +131,6 @@
     buffer.writeScalar(fBlurRadius);
 }
 
+SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkEmbossMaskFilter)
+    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkEmbossMaskFilter)
+SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp
index 0382c0a..7642f35 100644
--- a/src/pipe/SkGPipeRead.cpp
+++ b/src/pipe/SkGPipeRead.cpp
@@ -329,7 +329,14 @@
 
 static void drawBitmap_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
                           SkGPipeState* state) {
-    UNIMPLEMENTED
+    uint32_t bitmapSize = reader->readU32();
+    SkOrderedReadBuffer readBuffer(reader->skip(bitmapSize), bitmapSize);
+    SkBitmap bm;
+    bm.unflatten(readBuffer);
+    bool hasPaint = reader->readBool();
+    SkScalar left = reader->readScalar();
+    SkScalar top = reader->readScalar();
+    canvas->drawBitmap(bm, left, top, hasPaint ? &state->paint() : NULL);
 }
 
 static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index dba178b..9802b12 100644
--- a/src/pipe/SkGPipeWrite.cpp
+++ b/src/pipe/SkGPipeWrite.cpp
@@ -114,6 +114,8 @@
                                 const SkRect& dst, const SkPaint*) SK_OVERRIDE;
     virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
                                   const SkPaint*) SK_OVERRIDE;
+    virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+                                const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE;
     virtual void drawSprite(const SkBitmap&, int left, int top,
                             const SkPaint*) SK_OVERRIDE;
     virtual void drawText(const void* text, size_t byteLength, SkScalar x,
@@ -200,7 +202,13 @@
     }
 
     SkOrderedWriteBuffer tmpWriter(1024);
-    tmpWriter.setFlags(SkFlattenableWriteBuffer::kInlineFactoryNames_Flag);
+    
+    // Needs to be cross process so a bitmap shader will be preserved
+    // FIXME: Rather than forcing CrossProcess, we should create an SkRefCntSet
+    // so that we can store a pointer to a bitmap's pixels during flattening.
+    tmpWriter.setFlags((SkFlattenableWriteBuffer::Flags)
+                       (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
+                       | SkFlattenableWriteBuffer::kCrossProcess_Flag));
     tmpWriter.setFactoryRecorder(fFactorySet);
 
     tmpWriter.writeFlattenable(obj);
@@ -243,6 +251,7 @@
     fController = controller;
     fDone = false;
     fBlockSize = 0; // need first block from controller
+    fBytesNotified = 0;
     sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
 
     // we need a device to limit our clip
@@ -267,7 +276,11 @@
 
     needed += 4;  // size of DrawOp atom
     if (fWriter.size() + needed > fBlockSize) {
-        void* block = fController->requestBlock(MIN_BLOCK_SIZE, &fBlockSize);
+        // Before we wipe out any data that has already been written, read it
+        // out.
+        this->doNotify();
+        size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed);
+        void* block = fController->requestBlock(blockSize, &fBlockSize);
         if (NULL == block) {
             fDone = true;
             return false;
@@ -495,9 +508,32 @@
     }
 }
 
-void SkGPipeCanvas::drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
-                                   const SkPaint*) {
-    UNIMPLEMENTED
+void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
+                                   const SkPaint* paint) {
+    // This is the brute-force solution
+    // TODO: add the notion of a shared, counted for large immutable resources
+    NOTIFY_SETUP(this);
+    if (paint) {
+        this->writePaint(*paint);
+    }
+    SkOrderedWriteBuffer writeBuffer(0);
+    // FIXME: Rather than forcing CrossProcess, we should create an SkRefCntSet
+    // so that we can store a pointer to a bitmap's pixels during flattening.
+    writeBuffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
+    bm.flatten(writeBuffer);
+    int size = writeBuffer.size();
+    
+    if (this->needOpBytes(sizeof(uint32_t) + size + sizeof(SkScalar)*2)
+        + sizeof(bool)) {
+        // Record the act of drawing the bitmap
+        this->writeOp(kDrawBitmap_DrawOp);
+        fWriter.writeInt(size);
+        void* ptr = (void*) fWriter.reserve(size);
+        writeBuffer.flatten(ptr);
+        fWriter.writeBool(paint != NULL);
+        fWriter.writeScalar(left);
+        fWriter.writeScalar(top);
+    }
 }
 
 void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src,
@@ -509,7 +545,10 @@
                                          const SkPaint*) {
     UNIMPLEMENTED
 }
-
+void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+                                   const SkRect& dst, const SkPaint* paint) {
+    UNIMPLEMENTED
+}
 void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top,
                                    const SkPaint*) {
     UNIMPLEMENTED