Home | History | Annotate | Download | only in pipe
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "SkAnnotation.h"
     10 #include "SkBitmapDevice.h"
     11 #include "SkBitmapHeap.h"
     12 #include "SkCanvas.h"
     13 #include "SkColorFilter.h"
     14 #include "SkData.h"
     15 #include "SkDrawLooper.h"
     16 #include "SkGPipe.h"
     17 #include "SkGPipePriv.h"
     18 #include "SkImageFilter.h"
     19 #include "SkMaskFilter.h"
     20 #include "SkWriteBuffer.h"
     21 #include "SkPaint.h"
     22 #include "SkPathEffect.h"
     23 #include "SkPictureFlat.h"
     24 #include "SkRasterizer.h"
     25 #include "SkRRect.h"
     26 #include "SkShader.h"
     27 #include "SkStream.h"
     28 #include "SkTSearch.h"
     29 #include "SkTypeface.h"
     30 #include "SkWriter32.h"
     31 
     32 enum {
     33     kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector)
     34 };
     35 
     36 static bool isCrossProcess(uint32_t flags) {
     37     return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag);
     38 }
     39 
     40 static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
     41     SkASSERT(paintFlat < kCount_PaintFlats);
     42     switch (paintFlat) {
     43         case kColorFilter_PaintFlat:    return paint.getColorFilter();
     44         case kDrawLooper_PaintFlat:     return paint.getLooper();
     45         case kMaskFilter_PaintFlat:     return paint.getMaskFilter();
     46         case kPathEffect_PaintFlat:     return paint.getPathEffect();
     47         case kRasterizer_PaintFlat:     return paint.getRasterizer();
     48         case kShader_PaintFlat:         return paint.getShader();
     49         case kImageFilter_PaintFlat:    return paint.getImageFilter();
     50         case kXfermode_PaintFlat:       return paint.getXfermode();
     51     }
     52     SkDEBUGFAIL("never gets here");
     53     return NULL;
     54 }
     55 
     56 static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
     57     SkASSERT(typeface);
     58     SkDynamicMemoryWStream stream;
     59     typeface->serialize(&stream);
     60     size_t size = stream.getOffset();
     61     if (writer) {
     62         writer->write32(SkToU32(size));
     63         SkAutoDataUnref data(stream.copyToData());
     64         writer->writePad(data->data(), size);
     65     }
     66     return 4 + SkAlign4(size);
     67 }
     68 
     69 ///////////////////////////////////////////////////////////////////////////////
     70 
     71 class FlattenableHeap : public SkFlatController {
     72 public:
     73     FlattenableHeap(int numFlatsToKeep, SkNamedFactorySet* fset, bool isCrossProcess)
     74     : INHERITED(isCrossProcess ? SkWriteBuffer::kCrossProcess_Flag : 0)
     75     , fNumFlatsToKeep(numFlatsToKeep) {
     76         SkASSERT((isCrossProcess && fset != NULL) || (!isCrossProcess && NULL == fset));
     77         if (isCrossProcess) {
     78             this->setNamedFactorySet(fset);
     79         }
     80     }
     81 
     82     ~FlattenableHeap() {
     83         fPointers.freeAll();
     84     }
     85 
     86     virtual void* allocThrow(size_t bytes) SK_OVERRIDE;
     87 
     88     virtual void unalloc(void* ptr) SK_OVERRIDE;
     89 
     90     void setBitmapStorage(SkBitmapHeap* heap) {
     91         this->setBitmapHeap(heap);
     92     }
     93 
     94     const SkFlatData* flatToReplace() const;
     95 
     96     // Mark an SkFlatData as one that should not be returned by flatToReplace.
     97     // Takes the result of SkFlatData::index() as its parameter.
     98     void markFlatForKeeping(int index) {
     99         *fFlatsThatMustBeKept.append() = index;
    100     }
    101 
    102     void markAllFlatsSafeToDelete() {
    103         fFlatsThatMustBeKept.reset();
    104     }
    105 
    106 private:
    107     // Keep track of the indices (i.e. the result of SkFlatData::index()) of
    108     // flats that must be kept, since they are on the current paint.
    109     SkTDArray<int>   fFlatsThatMustBeKept;
    110     SkTDArray<void*> fPointers;
    111     const int        fNumFlatsToKeep;
    112 
    113     typedef SkFlatController INHERITED;
    114 };
    115 
    116 void FlattenableHeap::unalloc(void* ptr) {
    117     int indexToRemove = fPointers.rfind(ptr);
    118     if (indexToRemove >= 0) {
    119         sk_free(ptr);
    120         fPointers.remove(indexToRemove);
    121     }
    122 }
    123 
    124 void* FlattenableHeap::allocThrow(size_t bytes) {
    125     void* ptr = sk_malloc_throw(bytes);
    126     *fPointers.append() = ptr;
    127     return ptr;
    128 }
    129 
    130 const SkFlatData* FlattenableHeap::flatToReplace() const {
    131     // First, determine whether we should replace one.
    132     if (fPointers.count() > fNumFlatsToKeep) {
    133         // Look through the flattenable heap.
    134         // TODO: Return the LRU flat.
    135         for (int i = 0; i < fPointers.count(); i++) {
    136             SkFlatData* potential = (SkFlatData*)fPointers[i];
    137             // Make sure that it is not one that must be kept.
    138             bool mustKeep = false;
    139             for (int j = 0; j < fFlatsThatMustBeKept.count(); j++) {
    140                 if (potential->index() == fFlatsThatMustBeKept[j]) {
    141                     mustKeep = true;
    142                     break;
    143                 }
    144             }
    145             if (!mustKeep) {
    146                 return potential;
    147             }
    148         }
    149     }
    150     return NULL;
    151 }
    152 
    153 ///////////////////////////////////////////////////////////////////////////////
    154 
    155 struct SkFlattenableTraits {
    156     static void Flatten(SkWriteBuffer& buffer, const SkFlattenable& flattenable) {
    157         buffer.writeFlattenable(&flattenable);
    158     }
    159     // No need to define unflatten if we never call it.
    160 };
    161 typedef SkFlatDictionary<SkFlattenable, SkFlattenableTraits> FlatDictionary;
    162 
    163 ///////////////////////////////////////////////////////////////////////////////
    164 
    165 /**
    166  * If SkBitmaps are to be flattened to send to the reader, this class is
    167  * provided to the SkBitmapHeap to tell the SkGPipeCanvas to do so.
    168  */
    169 class BitmapShuttle : public SkBitmapHeap::ExternalStorage {
    170 public:
    171     BitmapShuttle(SkGPipeCanvas*);
    172 
    173     ~BitmapShuttle();
    174 
    175     virtual bool insert(const SkBitmap& bitmap, int32_t slot) SK_OVERRIDE;
    176 
    177     /**
    178      *  Remove the SkGPipeCanvas used for insertion. After this, calls to
    179      *  insert will crash.
    180      */
    181     void removeCanvas();
    182 
    183 private:
    184     SkGPipeCanvas*    fCanvas;
    185 };
    186 
    187 ///////////////////////////////////////////////////////////////////////////////
    188 
    189 class SkGPipeCanvas : public SkCanvas {
    190 public:
    191     SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags,
    192                   uint32_t width, uint32_t height);
    193     virtual ~SkGPipeCanvas();
    194 
    195     /**
    196      *  Called when nothing else is to be written to the stream. Any repeated
    197      *  calls are ignored.
    198      *
    199      *  @param notifyReaders Whether to send a message to the reader(s) that
    200      *      the writer is through sending commands. Should generally be true,
    201      *      unless there is an error which prevents further messages from
    202      *      being sent.
    203      */
    204     void finish(bool notifyReaders) {
    205         if (fDone) {
    206             return;
    207         }
    208         if (notifyReaders && this->needOpBytes()) {
    209             this->writeOp(kDone_DrawOp);
    210             this->doNotify();
    211         }
    212         if (shouldFlattenBitmaps(fFlags)) {
    213             // The following circular references exist:
    214             // fFlattenableHeap -> fWriteBuffer -> fBitmapStorage -> fExternalStorage -> fCanvas
    215             // fBitmapHeap -> fExternalStorage -> fCanvas
    216             // fFlattenableHeap -> fBitmapStorage -> fExternalStorage -> fCanvas
    217 
    218             // Break them all by destroying the final link to this SkGPipeCanvas.
    219             fBitmapShuttle->removeCanvas();
    220         }
    221         fDone = true;
    222     }
    223 
    224     void flushRecording(bool detachCurrentBlock);
    225     size_t freeMemoryIfPossible(size_t bytesToFree);
    226 
    227     size_t storageAllocatedForRecording() {
    228         return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->bytesAllocated();
    229     }
    230 
    231     // overrides from SkCanvas
    232     virtual bool isDrawingToLayer() const SK_OVERRIDE;
    233     virtual void clear(SkColor) SK_OVERRIDE;
    234     virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
    235     virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
    236                             const SkPaint&) SK_OVERRIDE;
    237     virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE;
    238     virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE;
    239     virtual void drawRRect(const SkRRect&, const SkPaint&) SK_OVERRIDE;
    240     virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE;
    241     virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
    242                             const SkPaint*) SK_OVERRIDE;
    243     virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src,
    244                                       const SkRect& dst, const SkPaint* paint,
    245                                       DrawBitmapRectFlags flags) SK_OVERRIDE;
    246     virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
    247                                   const SkPaint*) SK_OVERRIDE;
    248     virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
    249                                 const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE;
    250     virtual void drawSprite(const SkBitmap&, int left, int top,
    251                             const SkPaint*) SK_OVERRIDE;
    252     virtual void drawVertices(VertexMode, int vertexCount,
    253                           const SkPoint vertices[], const SkPoint texs[],
    254                           const SkColor colors[], SkXfermode*,
    255                           const uint16_t indices[], int indexCount,
    256                               const SkPaint&) SK_OVERRIDE;
    257     virtual void drawData(const void*, size_t) SK_OVERRIDE;
    258     virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
    259     virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE;
    260     virtual void endCommentGroup() SK_OVERRIDE;
    261 
    262     /**
    263      * Flatten an SkBitmap to send to the reader, where it will be referenced
    264      * according to slot.
    265      */
    266     bool shuttleBitmap(const SkBitmap&, int32_t slot);
    267 
    268 protected:
    269     virtual void willSave(SaveFlags) SK_OVERRIDE;
    270     virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
    271     virtual void willRestore() SK_OVERRIDE;
    272 
    273     virtual void didConcat(const SkMatrix&) SK_OVERRIDE;
    274     virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
    275 
    276     virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
    277     virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
    278                             const SkPaint&) SK_OVERRIDE;
    279     virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
    280                                const SkPaint&) SK_OVERRIDE;
    281     virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
    282                                 SkScalar constY, const SkPaint&) SK_OVERRIDE;
    283     virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
    284                                   const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
    285 
    286     virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
    287     virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
    288     virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
    289     virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
    290 
    291     virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE;
    292 
    293 private:
    294     void recordTranslate(const SkMatrix&);
    295     void recordScale(const SkMatrix&);
    296     void recordConcat(const SkMatrix&);
    297 
    298     enum {
    299         kNoSaveLayer = -1,
    300     };
    301     SkNamedFactorySet* fFactorySet;
    302     int                fFirstSaveLayerStackLevel;
    303     SkBitmapHeap*      fBitmapHeap;
    304     SkGPipeController* fController;
    305     SkWriter32&        fWriter;
    306     size_t             fBlockSize; // amount allocated for writer
    307     size_t             fBytesNotified;
    308     bool               fDone;
    309     const uint32_t     fFlags;
    310 
    311     SkRefCntSet        fTypefaceSet;
    312 
    313     uint32_t getTypefaceID(SkTypeface*);
    314 
    315     inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
    316         fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
    317     }
    318 
    319     inline void writeOp(DrawOps op) {
    320         fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
    321     }
    322 
    323     bool needOpBytes(size_t size = 0);
    324 
    325     inline void doNotify() {
    326         if (!fDone) {
    327             size_t bytes = fWriter.bytesWritten() - fBytesNotified;
    328             if (bytes > 0) {
    329                 fController->notifyWritten(bytes);
    330                 fBytesNotified += bytes;
    331             }
    332         }
    333     }
    334 
    335     // Should be called after any calls to an SkFlatDictionary::findAndReplace
    336     // if a new SkFlatData was added when in cross process mode
    337     void flattenFactoryNames();
    338 
    339     FlattenableHeap             fFlattenableHeap;
    340     FlatDictionary              fFlatDictionary;
    341     SkAutoTUnref<BitmapShuttle> fBitmapShuttle;
    342     int                         fCurrFlatIndex[kCount_PaintFlats];
    343 
    344     int flattenToIndex(SkFlattenable* obj, PaintFlats);
    345 
    346     // Common code used by drawBitmap*. Behaves differently depending on the
    347     // type of SkBitmapHeap being used, which is determined by the flags used.
    348     bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags,
    349                           size_t opBytesNeeded, const SkPaint* paint);
    350 
    351     SkPaint fPaint;
    352     void writePaint(const SkPaint&);
    353 
    354     class AutoPipeNotify {
    355     public:
    356         AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
    357         ~AutoPipeNotify() { fCanvas->doNotify(); }
    358     private:
    359         SkGPipeCanvas* fCanvas;
    360     };
    361     friend class AutoPipeNotify;
    362 
    363     typedef SkCanvas INHERITED;
    364 };
    365 
    366 void SkGPipeCanvas::flattenFactoryNames() {
    367     const char* name;
    368     while ((name = fFactorySet->getNextAddedFactoryName()) != NULL) {
    369         size_t len = strlen(name);
    370         if (this->needOpBytes(SkWriter32::WriteStringSize(name, len))) {
    371             this->writeOp(kDef_Factory_DrawOp);
    372             fWriter.writeString(name, len);
    373         }
    374     }
    375 }
    376 
    377 bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) {
    378     SkASSERT(shouldFlattenBitmaps(fFlags));
    379     SkWriteBuffer buffer;
    380     buffer.setNamedFactoryRecorder(fFactorySet);
    381     buffer.writeBitmap(bm);
    382     this->flattenFactoryNames();
    383     size_t size = buffer.bytesWritten();
    384     if (this->needOpBytes(size)) {
    385         this->writeOp(kDef_Bitmap_DrawOp, 0, slot);
    386         void* dst = static_cast<void*>(fWriter.reserve(size));
    387         buffer.writeToMemory(dst);
    388         return true;
    389     }
    390     return false;
    391 }
    392 
    393 // return 0 for NULL (or unflattenable obj), or index-base-1
    394 // return ~(index-base-1) if an old flattenable was replaced
    395 int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
    396     SkASSERT(!fDone && fBitmapHeap != NULL);
    397     if (NULL == obj) {
    398         return 0;
    399     }
    400 
    401     fBitmapHeap->deferAddingOwners();
    402     bool added, replaced;
    403     const SkFlatData* flat = fFlatDictionary.findAndReplace(*obj, fFlattenableHeap.flatToReplace(),
    404                                                             &added, &replaced);
    405     fBitmapHeap->endAddingOwnersDeferral(added);
    406     int index = flat->index();
    407     if (added) {
    408         if (isCrossProcess(fFlags)) {
    409             this->flattenFactoryNames();
    410         }
    411         size_t flatSize = flat->flatSize();
    412         if (this->needOpBytes(flatSize)) {
    413             this->writeOp(kDef_Flattenable_DrawOp, paintflat, index);
    414             fWriter.write(flat->data(), flatSize);
    415         }
    416     }
    417     if (replaced) {
    418         index = ~index;
    419     }
    420     return index;
    421 }
    422 
    423 ///////////////////////////////////////////////////////////////////////////////
    424 
    425 #define MIN_BLOCK_SIZE  (16 * 1024)
    426 #define BITMAPS_TO_KEEP 5
    427 #define FLATTENABLES_TO_KEEP 10
    428 
    429 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
    430                              SkWriter32* writer, uint32_t flags,
    431                              uint32_t width, uint32_t height)
    432     : SkCanvas(width, height)
    433     , fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL)
    434     , fWriter(*writer)
    435     , fFlags(flags)
    436     , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, isCrossProcess(flags))
    437     , fFlatDictionary(&fFlattenableHeap)
    438 {
    439     fController = controller;
    440     fDone = false;
    441     fBlockSize = 0; // need first block from controller
    442     fBytesNotified = 0;
    443     fFirstSaveLayerStackLevel = kNoSaveLayer;
    444     sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
    445 
    446     // Tell the reader the appropriate flags to use.
    447     if (this->needOpBytes()) {
    448         this->writeOp(kReportFlags_DrawOp, fFlags, 0);
    449     }
    450 
    451     if (shouldFlattenBitmaps(flags)) {
    452         fBitmapShuttle.reset(SkNEW_ARGS(BitmapShuttle, (this)));
    453         fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, (fBitmapShuttle.get(), BITMAPS_TO_KEEP));
    454     } else {
    455         fBitmapHeap = SkNEW_ARGS(SkBitmapHeap,
    456                                  (BITMAPS_TO_KEEP, controller->numberOfReaders()));
    457         if (this->needOpBytes(sizeof(void*))) {
    458             this->writeOp(kShareBitmapHeap_DrawOp);
    459             fWriter.writePtr(static_cast<void*>(fBitmapHeap));
    460         }
    461     }
    462     fFlattenableHeap.setBitmapStorage(fBitmapHeap);
    463     this->doNotify();
    464 }
    465 
    466 SkGPipeCanvas::~SkGPipeCanvas() {
    467     this->finish(true);
    468     SkSafeUnref(fFactorySet);
    469     SkSafeUnref(fBitmapHeap);
    470 }
    471 
    472 bool SkGPipeCanvas::needOpBytes(size_t needed) {
    473     if (fDone) {
    474         return false;
    475     }
    476 
    477     needed += 4;  // size of DrawOp atom
    478     needed = SkTMax<size_t>(MIN_BLOCK_SIZE, needed);
    479     needed = SkAlign4(needed);
    480     if (fWriter.bytesWritten() + needed > fBlockSize) {
    481         // Before we wipe out any data that has already been written, read it
    482         // out.
    483         this->doNotify();
    484         void* block = fController->requestBlock(needed, &fBlockSize);
    485         if (NULL == block) {
    486             // Do not notify the readers, which would call this function again.
    487             this->finish(false);
    488             return false;
    489         }
    490         SkASSERT(SkIsAlign4(fBlockSize));
    491         fWriter.reset(block, fBlockSize);
    492         fBytesNotified = 0;
    493     }
    494     return true;
    495 }
    496 
    497 uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
    498     uint32_t id = 0; // 0 means default/null typeface
    499     if (face) {
    500         id = fTypefaceSet.find(face);
    501         if (0 == id) {
    502             id = fTypefaceSet.add(face);
    503             size_t size = writeTypeface(NULL, face);
    504             if (this->needOpBytes(size)) {
    505                 this->writeOp(kDef_Typeface_DrawOp);
    506                 writeTypeface(&fWriter, face);
    507             }
    508         }
    509     }
    510     return id;
    511 }
    512 
    513 ///////////////////////////////////////////////////////////////////////////////
    514 
    515 #define NOTIFY_SETUP(canvas)    \
    516     AutoPipeNotify apn(canvas)
    517 
    518 void SkGPipeCanvas::willSave(SaveFlags flags) {
    519     NOTIFY_SETUP(this);
    520     if (this->needOpBytes()) {
    521         this->writeOp(kSave_DrawOp, 0, flags);
    522     }
    523 
    524     this->INHERITED::willSave(flags);
    525 }
    526 
    527 SkCanvas::SaveLayerStrategy SkGPipeCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
    528                                                          SaveFlags saveFlags) {
    529     NOTIFY_SETUP(this);
    530     size_t size = 0;
    531     unsigned opFlags = 0;
    532 
    533     if (bounds) {
    534         opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
    535         size += sizeof(SkRect);
    536     }
    537     if (paint) {
    538         opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
    539         this->writePaint(*paint);
    540     }
    541 
    542     if (this->needOpBytes(size)) {
    543         this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
    544         if (bounds) {
    545             fWriter.writeRect(*bounds);
    546         }
    547     }
    548 
    549     if (kNoSaveLayer == fFirstSaveLayerStackLevel){
    550         fFirstSaveLayerStackLevel = this->getSaveCount();
    551     }
    552 
    553     this->INHERITED::willSaveLayer(bounds, paint, saveFlags);
    554     // we don't create a layer
    555     return kNoLayer_SaveLayerStrategy;
    556 }
    557 
    558 void SkGPipeCanvas::willRestore() {
    559     NOTIFY_SETUP(this);
    560     if (this->needOpBytes()) {
    561         this->writeOp(kRestore_DrawOp);
    562     }
    563 
    564     if (this->getSaveCount() - 1 == fFirstSaveLayerStackLevel){
    565         fFirstSaveLayerStackLevel = kNoSaveLayer;
    566     }
    567 
    568     this->INHERITED::willRestore();
    569 }
    570 
    571 bool SkGPipeCanvas::isDrawingToLayer() const {
    572     return kNoSaveLayer != fFirstSaveLayerStackLevel;
    573 }
    574 
    575 void SkGPipeCanvas::recordTranslate(const SkMatrix& m) {
    576     if (this->needOpBytes(2 * sizeof(SkScalar))) {
    577         this->writeOp(kTranslate_DrawOp);
    578         fWriter.writeScalar(m.getTranslateX());
    579         fWriter.writeScalar(m.getTranslateY());
    580     }
    581 }
    582 
    583 void SkGPipeCanvas::recordScale(const SkMatrix& m) {
    584     if (this->needOpBytes(2 * sizeof(SkScalar))) {
    585         this->writeOp(kScale_DrawOp);
    586         fWriter.writeScalar(m.getScaleX());
    587         fWriter.writeScalar(m.getScaleY());
    588     }
    589 }
    590 
    591 void SkGPipeCanvas::recordConcat(const SkMatrix& m) {
    592     if (this->needOpBytes(m.writeToMemory(NULL))) {
    593         this->writeOp(kConcat_DrawOp);
    594         fWriter.writeMatrix(m);
    595     }
    596 }
    597 
    598 void SkGPipeCanvas::didConcat(const SkMatrix& matrix) {
    599     if (!matrix.isIdentity()) {
    600         NOTIFY_SETUP(this);
    601         switch (matrix.getType()) {
    602             case SkMatrix::kTranslate_Mask:
    603                 this->recordTranslate(matrix);
    604                 break;
    605             case SkMatrix::kScale_Mask:
    606                 this->recordScale(matrix);
    607                 break;
    608             default:
    609                 this->recordConcat(matrix);
    610                 break;
    611         }
    612     }
    613 
    614     this->INHERITED::didConcat(matrix);
    615 }
    616 
    617 void SkGPipeCanvas::didSetMatrix(const SkMatrix& matrix) {
    618     NOTIFY_SETUP(this);
    619     if (this->needOpBytes(matrix.writeToMemory(NULL))) {
    620         this->writeOp(kSetMatrix_DrawOp);
    621         fWriter.writeMatrix(matrix);
    622     }
    623     this->INHERITED::didSetMatrix(matrix);
    624 }
    625 
    626 void SkGPipeCanvas::onClipRect(const SkRect& rect, SkRegion::Op rgnOp,
    627                                ClipEdgeStyle edgeStyle) {
    628     NOTIFY_SETUP(this);
    629     if (this->needOpBytes(sizeof(SkRect))) {
    630         unsigned flags = 0;
    631         if (kSoft_ClipEdgeStyle == edgeStyle) {
    632             flags = kClip_HasAntiAlias_DrawOpFlag;
    633         }
    634         this->writeOp(kClipRect_DrawOp, flags, rgnOp);
    635         fWriter.writeRect(rect);
    636     }
    637     this->INHERITED::onClipRect(rect, rgnOp, edgeStyle);
    638 }
    639 
    640 void SkGPipeCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op rgnOp,
    641                                 ClipEdgeStyle edgeStyle) {
    642     NOTIFY_SETUP(this);
    643     if (this->needOpBytes(kSizeOfFlatRRect)) {
    644         unsigned flags = 0;
    645         if (kSoft_ClipEdgeStyle == edgeStyle) {
    646             flags = kClip_HasAntiAlias_DrawOpFlag;
    647         }
    648         this->writeOp(kClipRRect_DrawOp, flags, rgnOp);
    649         fWriter.writeRRect(rrect);
    650     }
    651     this->INHERITED::onClipRRect(rrect, rgnOp, edgeStyle);
    652 }
    653 
    654 void SkGPipeCanvas::onClipPath(const SkPath& path, SkRegion::Op rgnOp,
    655                                ClipEdgeStyle edgeStyle) {
    656     NOTIFY_SETUP(this);
    657     if (this->needOpBytes(path.writeToMemory(NULL))) {
    658         unsigned flags = 0;
    659         if (kSoft_ClipEdgeStyle == edgeStyle) {
    660             flags = kClip_HasAntiAlias_DrawOpFlag;
    661         }
    662         this->writeOp(kClipPath_DrawOp, flags, rgnOp);
    663         fWriter.writePath(path);
    664     }
    665     // we just pass on the bounds of the path
    666     this->INHERITED::onClipRect(path.getBounds(), rgnOp, edgeStyle);
    667 }
    668 
    669 void SkGPipeCanvas::onClipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
    670     NOTIFY_SETUP(this);
    671     if (this->needOpBytes(region.writeToMemory(NULL))) {
    672         this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
    673         fWriter.writeRegion(region);
    674     }
    675     this->INHERITED::onClipRegion(region, rgnOp);
    676 }
    677 
    678 ///////////////////////////////////////////////////////////////////////////////
    679 
    680 void SkGPipeCanvas::clear(SkColor color) {
    681     NOTIFY_SETUP(this);
    682     unsigned flags = 0;
    683     if (color) {
    684         flags |= kClear_HasColor_DrawOpFlag;
    685     }
    686     if (this->needOpBytes(sizeof(SkColor))) {
    687         this->writeOp(kDrawClear_DrawOp, flags, 0);
    688         if (color) {
    689             fWriter.write32(color);
    690         }
    691     }
    692 }
    693 
    694 void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
    695     NOTIFY_SETUP(this);
    696     this->writePaint(paint);
    697     if (this->needOpBytes()) {
    698         this->writeOp(kDrawPaint_DrawOp);
    699     }
    700 }
    701 
    702 void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
    703                                const SkPoint pts[], const SkPaint& paint) {
    704     if (count) {
    705         NOTIFY_SETUP(this);
    706         this->writePaint(paint);
    707         if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
    708             this->writeOp(kDrawPoints_DrawOp, mode, 0);
    709             fWriter.write32(SkToU32(count));
    710             fWriter.write(pts, count * sizeof(SkPoint));
    711         }
    712     }
    713 }
    714 
    715 void SkGPipeCanvas::drawOval(const SkRect& rect, const SkPaint& paint) {
    716     NOTIFY_SETUP(this);
    717     this->writePaint(paint);
    718     if (this->needOpBytes(sizeof(SkRect))) {
    719         this->writeOp(kDrawOval_DrawOp);
    720         fWriter.writeRect(rect);
    721     }
    722 }
    723 
    724 void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
    725     NOTIFY_SETUP(this);
    726     this->writePaint(paint);
    727     if (this->needOpBytes(sizeof(SkRect))) {
    728         this->writeOp(kDrawRect_DrawOp);
    729         fWriter.writeRect(rect);
    730     }
    731 }
    732 
    733 void SkGPipeCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    734     NOTIFY_SETUP(this);
    735     this->writePaint(paint);
    736     if (this->needOpBytes(kSizeOfFlatRRect)) {
    737         this->writeOp(kDrawRRect_DrawOp);
    738         fWriter.writeRRect(rrect);
    739     }
    740 }
    741 
    742 void SkGPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
    743                                  const SkPaint& paint) {
    744     NOTIFY_SETUP(this);
    745     this->writePaint(paint);
    746     if (this->needOpBytes(kSizeOfFlatRRect * 2)) {
    747         this->writeOp(kDrawDRRect_DrawOp);
    748         fWriter.writeRRect(outer);
    749         fWriter.writeRRect(inner);
    750     }
    751 }
    752 
    753 void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
    754     NOTIFY_SETUP(this);
    755     this->writePaint(paint);
    756     if (this->needOpBytes(path.writeToMemory(NULL))) {
    757         this->writeOp(kDrawPath_DrawOp);
    758         fWriter.writePath(path);
    759     }
    760 }
    761 
    762 bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op,
    763                                      unsigned flags,
    764                                      size_t opBytesNeeded,
    765                                      const SkPaint* paint) {
    766     if (fDone) {
    767         return false;
    768     }
    769 
    770     if (paint != NULL) {
    771         flags |= kDrawBitmap_HasPaint_DrawOpFlag;
    772         this->writePaint(*paint);
    773     }
    774     // This needs to run first so its calls to needOpBytes() and its writes
    775     // don't interlace with the needOpBytes() and write below.
    776     SkASSERT(fBitmapHeap != NULL);
    777     int32_t bitmapIndex = fBitmapHeap->insert(bm);
    778     if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) {
    779         return false;
    780     }
    781 
    782     if (this->needOpBytes(opBytesNeeded)) {
    783         this->writeOp(op, flags, bitmapIndex);
    784         return true;
    785     }
    786     return false;
    787 }
    788 
    789 void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
    790                                const SkPaint* paint) {
    791     NOTIFY_SETUP(this);
    792     size_t opBytesNeeded = sizeof(SkScalar) * 2;
    793 
    794     if (this->commonDrawBitmap(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) {
    795         fWriter.writeScalar(left);
    796         fWriter.writeScalar(top);
    797     }
    798 }
    799 
    800 void SkGPipeCanvas::drawBitmapRectToRect(const SkBitmap& bm, const SkRect* src,
    801                                          const SkRect& dst, const SkPaint* paint,
    802                                          DrawBitmapRectFlags dbmrFlags) {
    803     NOTIFY_SETUP(this);
    804     size_t opBytesNeeded = sizeof(SkRect);
    805     bool hasSrc = src != NULL;
    806     unsigned flags;
    807     if (hasSrc) {
    808         flags = kDrawBitmap_HasSrcRect_DrawOpFlag;
    809         opBytesNeeded += sizeof(int32_t) * 4;
    810     } else {
    811         flags = 0;
    812     }
    813     if (dbmrFlags & kBleed_DrawBitmapRectFlag) {
    814         flags |= kDrawBitmap_Bleed_DrawOpFlag;
    815     }
    816 
    817     if (this->commonDrawBitmap(bm, kDrawBitmapRectToRect_DrawOp, flags, opBytesNeeded, paint)) {
    818         if (hasSrc) {
    819             fWriter.writeRect(*src);
    820         }
    821         fWriter.writeRect(dst);
    822     }
    823 }
    824 
    825 void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap& bm, const SkMatrix& matrix,
    826                                      const SkPaint* paint) {
    827     NOTIFY_SETUP(this);
    828     size_t opBytesNeeded = matrix.writeToMemory(NULL);
    829 
    830     if (this->commonDrawBitmap(bm, kDrawBitmapMatrix_DrawOp, 0, opBytesNeeded, paint)) {
    831         fWriter.writeMatrix(matrix);
    832     }
    833 }
    834 
    835 void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
    836                                    const SkRect& dst, const SkPaint* paint) {
    837     NOTIFY_SETUP(this);
    838     size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(SkRect);
    839 
    840     if (this->commonDrawBitmap(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, paint)) {
    841         fWriter.write32(center.fLeft);
    842         fWriter.write32(center.fTop);
    843         fWriter.write32(center.fRight);
    844         fWriter.write32(center.fBottom);
    845         fWriter.writeRect(dst);
    846     }
    847 }
    848 
    849 void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
    850                                    const SkPaint* paint) {
    851     NOTIFY_SETUP(this);
    852     size_t opBytesNeeded = sizeof(int32_t) * 2;
    853 
    854     if (this->commonDrawBitmap(bm, kDrawSprite_DrawOp, 0, opBytesNeeded, paint)) {
    855         fWriter.write32(left);
    856         fWriter.write32(top);
    857     }
    858 }
    859 
    860 void SkGPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
    861                                const SkPaint& paint) {
    862     if (byteLength) {
    863         NOTIFY_SETUP(this);
    864         this->writePaint(paint);
    865         if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
    866             this->writeOp(kDrawText_DrawOp);
    867             fWriter.write32(SkToU32(byteLength));
    868             fWriter.writePad(text, byteLength);
    869             fWriter.writeScalar(x);
    870             fWriter.writeScalar(y);
    871         }
    872     }
    873 }
    874 
    875 void SkGPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
    876                                   const SkPaint& paint) {
    877     if (byteLength) {
    878         NOTIFY_SETUP(this);
    879         this->writePaint(paint);
    880         int count = paint.textToGlyphs(text, byteLength, NULL);
    881         if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
    882             this->writeOp(kDrawPosText_DrawOp);
    883             fWriter.write32(SkToU32(byteLength));
    884             fWriter.writePad(text, byteLength);
    885             fWriter.write32(count);
    886             fWriter.write(pos, count * sizeof(SkPoint));
    887         }
    888     }
    889 }
    890 
    891 void SkGPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
    892                                    SkScalar constY, const SkPaint& paint) {
    893     if (byteLength) {
    894         NOTIFY_SETUP(this);
    895         this->writePaint(paint);
    896         int count = paint.textToGlyphs(text, byteLength, NULL);
    897         if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
    898             this->writeOp(kDrawPosTextH_DrawOp);
    899             fWriter.write32(SkToU32(byteLength));
    900             fWriter.writePad(text, byteLength);
    901             fWriter.write32(count);
    902             fWriter.write(xpos, count * sizeof(SkScalar));
    903             fWriter.writeScalar(constY);
    904         }
    905     }
    906 }
    907 
    908 void SkGPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
    909                                      const SkMatrix* matrix, const SkPaint& paint) {
    910     if (byteLength) {
    911         NOTIFY_SETUP(this);
    912         unsigned flags = 0;
    913         size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(NULL);
    914         if (matrix) {
    915             flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
    916             size += matrix->writeToMemory(NULL);
    917         }
    918         this->writePaint(paint);
    919         if (this->needOpBytes(size)) {
    920             this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
    921 
    922             fWriter.write32(SkToU32(byteLength));
    923             fWriter.writePad(text, byteLength);
    924 
    925             fWriter.writePath(path);
    926             if (matrix) {
    927                 fWriter.writeMatrix(*matrix);
    928             }
    929         }
    930     }
    931 }
    932 
    933 void SkGPipeCanvas::onDrawPicture(const SkPicture* picture) {
    934     // we want to playback the picture into individual draw calls
    935     this->INHERITED::onDrawPicture(picture);
    936 }
    937 
    938 void SkGPipeCanvas::drawVertices(VertexMode vmode, int vertexCount,
    939                                  const SkPoint vertices[], const SkPoint texs[],
    940                                  const SkColor colors[], SkXfermode* xfer,
    941                                  const uint16_t indices[], int indexCount,
    942                                  const SkPaint& paint) {
    943     if (0 == vertexCount) {
    944         return;
    945     }
    946 
    947     NOTIFY_SETUP(this);
    948     this->writePaint(paint);
    949 
    950     unsigned flags = 0;  // packs with the op, so needs no extra space
    951 
    952     size_t size = 0;
    953     size += 4;                              // vmode
    954     size += 4;                              // vertex count
    955     size += vertexCount * sizeof(SkPoint);  // vertices
    956 
    957     if (texs) {
    958         flags |= kDrawVertices_HasTexs_DrawOpFlag;
    959         size += vertexCount * sizeof(SkPoint);
    960     }
    961     if (colors) {
    962         flags |= kDrawVertices_HasColors_DrawOpFlag;
    963         size += vertexCount * sizeof(SkColor);
    964     }
    965     if (xfer && !SkXfermode::IsMode(xfer, SkXfermode::kModulate_Mode)) {
    966         flags |= kDrawVertices_HasXfermode_DrawOpFlag;
    967         size += sizeof(int32_t);    // SkXfermode::Mode
    968     }
    969     if (indices && indexCount > 0) {
    970         flags |= kDrawVertices_HasIndices_DrawOpFlag;
    971         size += 4;                                        // index count
    972         size += SkAlign4(indexCount * sizeof(uint16_t));  // indices
    973     }
    974 
    975     if (this->needOpBytes(size)) {
    976         this->writeOp(kDrawVertices_DrawOp, flags, 0);
    977         fWriter.write32(vmode);
    978         fWriter.write32(vertexCount);
    979         fWriter.write(vertices, vertexCount * sizeof(SkPoint));
    980         if (flags & kDrawVertices_HasTexs_DrawOpFlag) {
    981             fWriter.write(texs, vertexCount * sizeof(SkPoint));
    982         }
    983         if (flags & kDrawVertices_HasColors_DrawOpFlag) {
    984             fWriter.write(colors, vertexCount * sizeof(SkColor));
    985         }
    986         if (flags & kDrawVertices_HasXfermode_DrawOpFlag) {
    987             SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
    988             SkAssertResult(xfer->asMode(&mode));
    989             fWriter.write32(mode);
    990         }
    991         if (flags & kDrawVertices_HasIndices_DrawOpFlag) {
    992             fWriter.write32(indexCount);
    993             fWriter.writePad(indices, indexCount * sizeof(uint16_t));
    994         }
    995     }
    996 }
    997 
    998 void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
    999     if (size && ptr) {
   1000         NOTIFY_SETUP(this);
   1001         unsigned data = 0;
   1002         if (size < (1 << DRAWOPS_DATA_BITS)) {
   1003             data = (unsigned)size;
   1004         }
   1005         if (this->needOpBytes(4 + SkAlign4(size))) {
   1006             this->writeOp(kDrawData_DrawOp, 0, data);
   1007             if (0 == data) {
   1008                 fWriter.write32(SkToU32(size));
   1009             }
   1010             fWriter.writePad(ptr, size);
   1011         }
   1012     }
   1013 }
   1014 
   1015 void SkGPipeCanvas::beginCommentGroup(const char* description) {
   1016     // ignore for now
   1017 }
   1018 
   1019 void SkGPipeCanvas::addComment(const char* kywd, const char* value) {
   1020     // ignore for now
   1021 }
   1022 
   1023 void SkGPipeCanvas::endCommentGroup() {
   1024     // ignore for now
   1025 }
   1026 
   1027 void SkGPipeCanvas::flushRecording(bool detachCurrentBlock) {
   1028     this->doNotify();
   1029     if (detachCurrentBlock) {
   1030         // force a new block to be requested for the next recorded command
   1031         fBlockSize = 0;
   1032     }
   1033 }
   1034 
   1035 size_t SkGPipeCanvas::freeMemoryIfPossible(size_t bytesToFree) {
   1036     return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->freeMemoryIfPossible(bytesToFree);
   1037 }
   1038 
   1039 ///////////////////////////////////////////////////////////////////////////////
   1040 
   1041 template <typename T> uint32_t castToU32(T value) {
   1042     union {
   1043         T           fSrc;
   1044         uint32_t    fDst;
   1045     } data;
   1046     data.fSrc = value;
   1047     return data.fDst;
   1048 }
   1049 
   1050 void SkGPipeCanvas::writePaint(const SkPaint& paint) {
   1051     if (fDone) {
   1052         return;
   1053     }
   1054     SkPaint& base = fPaint;
   1055     uint32_t storage[32];
   1056     uint32_t* ptr = storage;
   1057 
   1058     if (base.getFlags() != paint.getFlags()) {
   1059         *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
   1060         base.setFlags(paint.getFlags());
   1061     }
   1062     if (base.getColor() != paint.getColor()) {
   1063         *ptr++ = PaintOp_packOp(kColor_PaintOp);
   1064         *ptr++ = paint.getColor();
   1065         base.setColor(paint.getColor());
   1066     }
   1067     if (base.getFilterLevel() != paint.getFilterLevel()) {
   1068         *ptr++ = PaintOp_packOpData(kFilterLevel_PaintOp, paint.getFilterLevel());
   1069         base.setFilterLevel(paint.getFilterLevel());
   1070     }
   1071     if (base.getStyle() != paint.getStyle()) {
   1072         *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
   1073         base.setStyle(paint.getStyle());
   1074     }
   1075     if (base.getStrokeJoin() != paint.getStrokeJoin()) {
   1076         *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
   1077         base.setStrokeJoin(paint.getStrokeJoin());
   1078     }
   1079     if (base.getStrokeCap() != paint.getStrokeCap()) {
   1080         *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
   1081         base.setStrokeCap(paint.getStrokeCap());
   1082     }
   1083     if (base.getStrokeWidth() != paint.getStrokeWidth()) {
   1084         *ptr++ = PaintOp_packOp(kWidth_PaintOp);
   1085         *ptr++ = castToU32(paint.getStrokeWidth());
   1086         base.setStrokeWidth(paint.getStrokeWidth());
   1087     }
   1088     if (base.getStrokeMiter() != paint.getStrokeMiter()) {
   1089         *ptr++ = PaintOp_packOp(kMiter_PaintOp);
   1090         *ptr++ = castToU32(paint.getStrokeMiter());
   1091         base.setStrokeMiter(paint.getStrokeMiter());
   1092     }
   1093     if (base.getTextEncoding() != paint.getTextEncoding()) {
   1094         *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
   1095         base.setTextEncoding(paint.getTextEncoding());
   1096     }
   1097     if (base.getHinting() != paint.getHinting()) {
   1098         *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
   1099         base.setHinting(paint.getHinting());
   1100     }
   1101     if (base.getTextAlign() != paint.getTextAlign()) {
   1102         *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
   1103         base.setTextAlign(paint.getTextAlign());
   1104     }
   1105     if (base.getTextSize() != paint.getTextSize()) {
   1106         *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
   1107         *ptr++ = castToU32(paint.getTextSize());
   1108         base.setTextSize(paint.getTextSize());
   1109     }
   1110     if (base.getTextScaleX() != paint.getTextScaleX()) {
   1111         *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
   1112         *ptr++ = castToU32(paint.getTextScaleX());
   1113         base.setTextScaleX(paint.getTextScaleX());
   1114     }
   1115     if (base.getTextSkewX() != paint.getTextSkewX()) {
   1116         *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
   1117         *ptr++ = castToU32(paint.getTextSkewX());
   1118         base.setTextSkewX(paint.getTextSkewX());
   1119     }
   1120 
   1121     if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
   1122         if (isCrossProcess(fFlags)) {
   1123             uint32_t id = this->getTypefaceID(paint.getTypeface());
   1124             *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
   1125         } else if (this->needOpBytes(sizeof(void*))) {
   1126             // Add to the set for ref counting.
   1127             fTypefaceSet.add(paint.getTypeface());
   1128             // It is safe to write the typeface to the stream before the rest
   1129             // of the paint unless we ever send a kReset_PaintOp, which we
   1130             // currently never do.
   1131             this->writeOp(kSetTypeface_DrawOp);
   1132             fWriter.writePtr(paint.getTypeface());
   1133         }
   1134         base.setTypeface(paint.getTypeface());
   1135     }
   1136 
   1137     // This is a new paint, so all old flats can be safely purged, if necessary.
   1138     fFlattenableHeap.markAllFlatsSafeToDelete();
   1139     for (int i = 0; i < kCount_PaintFlats; i++) {
   1140         int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i);
   1141         bool replaced = index < 0;
   1142         if (replaced) {
   1143             index = ~index;
   1144         }
   1145         // Store the index of any flat that needs to be kept. 0 means no flat.
   1146         if (index > 0) {
   1147             fFlattenableHeap.markFlatForKeeping(index);
   1148         }
   1149         SkASSERT(index >= 0 && index <= fFlatDictionary.count());
   1150         if (index != fCurrFlatIndex[i] || replaced) {
   1151             *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index);
   1152             fCurrFlatIndex[i] = index;
   1153         }
   1154     }
   1155 
   1156     size_t size = (char*)ptr - (char*)storage;
   1157     if (size && this->needOpBytes(size)) {
   1158         this->writeOp(kPaintOp_DrawOp, 0, SkToU32(size));
   1159         fWriter.write(storage, size);
   1160         for (size_t i = 0; i < size/4; i++) {
   1161 //            SkDebugf("[%d] %08X\n", i, storage[i]);
   1162         }
   1163     }
   1164 
   1165     //
   1166     //  Do these after we've written kPaintOp_DrawOp
   1167 
   1168     if (base.getAnnotation() != paint.getAnnotation()) {
   1169         if (NULL == paint.getAnnotation()) {
   1170             if (this->needOpBytes()) {
   1171                 this->writeOp(kSetAnnotation_DrawOp, 0, 0);
   1172             }
   1173         } else {
   1174             SkWriteBuffer buffer;
   1175             paint.getAnnotation()->writeToBuffer(buffer);
   1176             const size_t size = buffer.bytesWritten();
   1177             if (this->needOpBytes(size)) {
   1178                 this->writeOp(kSetAnnotation_DrawOp, 0, SkToU32(size));
   1179                 buffer.writeToMemory(fWriter.reserve(size));
   1180             }
   1181         }
   1182         base.setAnnotation(paint.getAnnotation());
   1183     }
   1184 }
   1185 
   1186 ///////////////////////////////////////////////////////////////////////////////
   1187 
   1188 #include "SkGPipe.h"
   1189 
   1190 SkGPipeController::~SkGPipeController() {
   1191     SkSafeUnref(fCanvas);
   1192 }
   1193 
   1194 void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) {
   1195     SkRefCnt_SafeAssign(fCanvas, canvas);
   1196 }
   1197 
   1198 ///////////////////////////////////////////////////////////////////////////////
   1199 
   1200 SkGPipeWriter::SkGPipeWriter()
   1201 : fWriter(0) {
   1202     fCanvas = NULL;
   1203 }
   1204 
   1205 SkGPipeWriter::~SkGPipeWriter() {
   1206     this->endRecording();
   1207 }
   1208 
   1209 SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags,
   1210                                         uint32_t width, uint32_t height) {
   1211     if (NULL == fCanvas) {
   1212         fWriter.reset(NULL, 0);
   1213         fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags, width, height));
   1214     }
   1215     controller->setCanvas(fCanvas);
   1216     return fCanvas;
   1217 }
   1218 
   1219 void SkGPipeWriter::endRecording() {
   1220     if (fCanvas) {
   1221         fCanvas->finish(true);
   1222         fCanvas->unref();
   1223         fCanvas = NULL;
   1224     }
   1225 }
   1226 
   1227 void SkGPipeWriter::flushRecording(bool detachCurrentBlock) {
   1228     if (fCanvas) {
   1229         fCanvas->flushRecording(detachCurrentBlock);
   1230     }
   1231 }
   1232 
   1233 size_t SkGPipeWriter::freeMemoryIfPossible(size_t bytesToFree) {
   1234     if (fCanvas) {
   1235         return fCanvas->freeMemoryIfPossible(bytesToFree);
   1236     }
   1237     return 0;
   1238 }
   1239 
   1240 size_t SkGPipeWriter::storageAllocatedForRecording() const {
   1241     return NULL == fCanvas ? 0 : fCanvas->storageAllocatedForRecording();
   1242 }
   1243 
   1244 ///////////////////////////////////////////////////////////////////////////////
   1245 
   1246 BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) {
   1247     SkASSERT(canvas != NULL);
   1248     fCanvas = canvas;
   1249     fCanvas->ref();
   1250 }
   1251 
   1252 BitmapShuttle::~BitmapShuttle() {
   1253     this->removeCanvas();
   1254 }
   1255 
   1256 bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) {
   1257     SkASSERT(fCanvas != NULL);
   1258     return fCanvas->shuttleBitmap(bitmap, slot);
   1259 }
   1260 
   1261 void BitmapShuttle::removeCanvas() {
   1262     if (NULL == fCanvas) {
   1263         return;
   1264     }
   1265     fCanvas->unref();
   1266     fCanvas = NULL;
   1267 }
   1268