gfx/skia/trunk/src/pipe/SkGPipeWrite.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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  */
     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"
    32 enum {
    33     kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector)
    34 };
    36 static bool isCrossProcess(uint32_t flags) {
    37     return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag);
    38 }
    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 }
    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(size);
    63         SkAutoDataUnref data(stream.copyToData());
    64         writer->writePad(data->data(), size);
    65     }
    66     return 4 + SkAlign4(size);
    67 }
    69 ///////////////////////////////////////////////////////////////////////////////
    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     }
    82     ~FlattenableHeap() {
    83         fPointers.freeAll();
    84     }
    86     virtual void* allocThrow(size_t bytes) SK_OVERRIDE;
    88     virtual void unalloc(void* ptr) SK_OVERRIDE;
    90     void setBitmapStorage(SkBitmapHeap* heap) {
    91         this->setBitmapHeap(heap);
    92     }
    94     const SkFlatData* flatToReplace() const;
    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     }
   102     void markAllFlatsSafeToDelete() {
   103         fFlatsThatMustBeKept.reset();
   104     }
   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;
   113     typedef SkFlatController INHERITED;
   114 };
   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 }
   124 void* FlattenableHeap::allocThrow(size_t bytes) {
   125     void* ptr = sk_malloc_throw(bytes);
   126     *fPointers.append() = ptr;
   127     return ptr;
   128 }
   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 }
   153 ///////////////////////////////////////////////////////////////////////////////
   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;
   163 ///////////////////////////////////////////////////////////////////////////////
   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*);
   173     ~BitmapShuttle();
   175     virtual bool insert(const SkBitmap& bitmap, int32_t slot) SK_OVERRIDE;
   177     /**
   178      *  Remove the SkGPipeCanvas used for insertion. After this, calls to
   179      *  insert will crash.
   180      */
   181     void removeCanvas();
   183 private:
   184     SkGPipeCanvas*    fCanvas;
   185 };
   187 ///////////////////////////////////////////////////////////////////////////////
   189 class SkGPipeCanvas : public SkCanvas {
   190 public:
   191     SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags,
   192                   uint32_t width, uint32_t height);
   193     virtual ~SkGPipeCanvas();
   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
   218             // Break them all by destroying the final link to this SkGPipeCanvas.
   219             fBitmapShuttle->removeCanvas();
   220         }
   221         fDone = true;
   222     }
   224     void flushRecording(bool detachCurrentBlock);
   225     size_t freeMemoryIfPossible(size_t bytesToFree);
   227     size_t storageAllocatedForRecording() {
   228         return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->bytesAllocated();
   229     }
   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 drawText(const void* text, size_t byteLength, SkScalar x,
   253                           SkScalar y, const SkPaint&) SK_OVERRIDE;
   254     virtual void drawPosText(const void* text, size_t byteLength,
   255                              const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
   256     virtual void drawPosTextH(const void* text, size_t byteLength,
   257                               const SkScalar xpos[], SkScalar constY,
   258                               const SkPaint&) SK_OVERRIDE;
   259     virtual void drawTextOnPath(const void* text, size_t byteLength,
   260                             const SkPath& path, const SkMatrix* matrix,
   261                                 const SkPaint&) SK_OVERRIDE;
   262     virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
   263     virtual void drawVertices(VertexMode, int vertexCount,
   264                           const SkPoint vertices[], const SkPoint texs[],
   265                           const SkColor colors[], SkXfermode*,
   266                           const uint16_t indices[], int indexCount,
   267                               const SkPaint&) SK_OVERRIDE;
   268     virtual void drawData(const void*, size_t) SK_OVERRIDE;
   269     virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
   270     virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE;
   271     virtual void endCommentGroup() SK_OVERRIDE;
   273     /**
   274      * Flatten an SkBitmap to send to the reader, where it will be referenced
   275      * according to slot.
   276      */
   277     bool shuttleBitmap(const SkBitmap&, int32_t slot);
   279 protected:
   280     virtual void willSave(SaveFlags) SK_OVERRIDE;
   281     virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
   282     virtual void willRestore() SK_OVERRIDE;
   284     virtual void didTranslate(SkScalar, SkScalar) SK_OVERRIDE;
   285     virtual void didScale(SkScalar, SkScalar) SK_OVERRIDE;
   286     virtual void didRotate(SkScalar) SK_OVERRIDE;
   287     virtual void didSkew(SkScalar, SkScalar) SK_OVERRIDE;
   288     virtual void didConcat(const SkMatrix&) SK_OVERRIDE;
   289     virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
   291     virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
   293     virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
   294     virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
   295     virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
   296     virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
   298 private:
   299     enum {
   300         kNoSaveLayer = -1,
   301     };
   302     SkNamedFactorySet* fFactorySet;
   303     int                fFirstSaveLayerStackLevel;
   304     SkBitmapHeap*      fBitmapHeap;
   305     SkGPipeController* fController;
   306     SkWriter32&        fWriter;
   307     size_t             fBlockSize; // amount allocated for writer
   308     size_t             fBytesNotified;
   309     bool               fDone;
   310     const uint32_t     fFlags;
   312     SkRefCntSet        fTypefaceSet;
   314     uint32_t getTypefaceID(SkTypeface*);
   316     inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
   317         fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
   318     }
   320     inline void writeOp(DrawOps op) {
   321         fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
   322     }
   324     bool needOpBytes(size_t size = 0);
   326     inline void doNotify() {
   327         if (!fDone) {
   328             size_t bytes = fWriter.bytesWritten() - fBytesNotified;
   329             if (bytes > 0) {
   330                 fController->notifyWritten(bytes);
   331                 fBytesNotified += bytes;
   332             }
   333         }
   334     }
   336     // Should be called after any calls to an SkFlatDictionary::findAndReplace
   337     // if a new SkFlatData was added when in cross process mode
   338     void flattenFactoryNames();
   340     FlattenableHeap             fFlattenableHeap;
   341     FlatDictionary              fFlatDictionary;
   342     SkAutoTUnref<BitmapShuttle> fBitmapShuttle;
   343     int                         fCurrFlatIndex[kCount_PaintFlats];
   345     int flattenToIndex(SkFlattenable* obj, PaintFlats);
   347     // Common code used by drawBitmap*. Behaves differently depending on the
   348     // type of SkBitmapHeap being used, which is determined by the flags used.
   349     bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags,
   350                           size_t opBytesNeeded, const SkPaint* paint);
   352     SkPaint fPaint;
   353     void writePaint(const SkPaint&);
   355     class AutoPipeNotify {
   356     public:
   357         AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
   358         ~AutoPipeNotify() { fCanvas->doNotify(); }
   359     private:
   360         SkGPipeCanvas* fCanvas;
   361     };
   362     friend class AutoPipeNotify;
   364     typedef SkCanvas INHERITED;
   365 };
   367 void SkGPipeCanvas::flattenFactoryNames() {
   368     const char* name;
   369     while ((name = fFactorySet->getNextAddedFactoryName()) != NULL) {
   370         size_t len = strlen(name);
   371         if (this->needOpBytes(len)) {
   372             this->writeOp(kDef_Factory_DrawOp);
   373             fWriter.writeString(name, len);
   374         }
   375     }
   376 }
   378 bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) {
   379     SkASSERT(shouldFlattenBitmaps(fFlags));
   380     SkWriteBuffer buffer;
   381     buffer.setNamedFactoryRecorder(fFactorySet);
   382     buffer.writeBitmap(bm);
   383     this->flattenFactoryNames();
   384     uint32_t size = buffer.bytesWritten();
   385     if (this->needOpBytes(size)) {
   386         this->writeOp(kDef_Bitmap_DrawOp, 0, slot);
   387         void* dst = static_cast<void*>(fWriter.reserve(size));
   388         buffer.writeToMemory(dst);
   389         return true;
   390     }
   391     return false;
   392 }
   394 // return 0 for NULL (or unflattenable obj), or index-base-1
   395 // return ~(index-base-1) if an old flattenable was replaced
   396 int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
   397     SkASSERT(!fDone && fBitmapHeap != NULL);
   398     if (NULL == obj) {
   399         return 0;
   400     }
   402     fBitmapHeap->deferAddingOwners();
   403     bool added, replaced;
   404     const SkFlatData* flat = fFlatDictionary.findAndReplace(*obj, fFlattenableHeap.flatToReplace(),
   405                                                             &added, &replaced);
   406     fBitmapHeap->endAddingOwnersDeferral(added);
   407     int index = flat->index();
   408     if (added) {
   409         if (isCrossProcess(fFlags)) {
   410             this->flattenFactoryNames();
   411         }
   412         size_t flatSize = flat->flatSize();
   413         if (this->needOpBytes(flatSize)) {
   414             this->writeOp(kDef_Flattenable_DrawOp, paintflat, index);
   415             fWriter.write(flat->data(), flatSize);
   416         }
   417     }
   418     if (replaced) {
   419         index = ~index;
   420     }
   421     return index;
   422 }
   424 ///////////////////////////////////////////////////////////////////////////////
   426 #define MIN_BLOCK_SIZE  (16 * 1024)
   427 #define BITMAPS_TO_KEEP 5
   428 #define FLATTENABLES_TO_KEEP 10
   430 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
   431                              SkWriter32* writer, uint32_t flags,
   432                              uint32_t width, uint32_t height)
   433     : SkCanvas(width, height)
   434     , fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL)
   435     , fWriter(*writer)
   436     , fFlags(flags)
   437     , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, isCrossProcess(flags))
   438     , fFlatDictionary(&fFlattenableHeap)
   439 {
   440     fController = controller;
   441     fDone = false;
   442     fBlockSize = 0; // need first block from controller
   443     fBytesNotified = 0;
   444     fFirstSaveLayerStackLevel = kNoSaveLayer;
   445     sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
   447     // Tell the reader the appropriate flags to use.
   448     if (this->needOpBytes()) {
   449         this->writeOp(kReportFlags_DrawOp, fFlags, 0);
   450     }
   452     if (shouldFlattenBitmaps(flags)) {
   453         fBitmapShuttle.reset(SkNEW_ARGS(BitmapShuttle, (this)));
   454         fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, (fBitmapShuttle.get(), BITMAPS_TO_KEEP));
   455     } else {
   456         fBitmapHeap = SkNEW_ARGS(SkBitmapHeap,
   457                                  (BITMAPS_TO_KEEP, controller->numberOfReaders()));
   458         if (this->needOpBytes(sizeof(void*))) {
   459             this->writeOp(kShareBitmapHeap_DrawOp);
   460             fWriter.writePtr(static_cast<void*>(fBitmapHeap));
   461         }
   462     }
   463     fFlattenableHeap.setBitmapStorage(fBitmapHeap);
   464     this->doNotify();
   465 }
   467 SkGPipeCanvas::~SkGPipeCanvas() {
   468     this->finish(true);
   469     SkSafeUnref(fFactorySet);
   470     SkSafeUnref(fBitmapHeap);
   471 }
   473 bool SkGPipeCanvas::needOpBytes(size_t needed) {
   474     if (fDone) {
   475         return false;
   476     }
   478     needed += 4;  // size of DrawOp atom
   479     if (fWriter.bytesWritten() + needed > fBlockSize) {
   480         // Before we wipe out any data that has already been written, read it
   481         // out.
   482         this->doNotify();
   483         size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed);
   484         void* block = fController->requestBlock(blockSize, &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 }
   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 }
   513 ///////////////////////////////////////////////////////////////////////////////
   515 #define NOTIFY_SETUP(canvas)    \
   516     AutoPipeNotify apn(canvas)
   518 void SkGPipeCanvas::willSave(SaveFlags flags) {
   519     NOTIFY_SETUP(this);
   520     if (this->needOpBytes()) {
   521         this->writeOp(kSave_DrawOp, 0, flags);
   522     }
   524     this->INHERITED::willSave(flags);
   525 }
   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;
   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     }
   542     if (this->needOpBytes(size)) {
   543         this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
   544         if (bounds) {
   545             fWriter.writeRect(*bounds);
   546         }
   547     }
   549     if (kNoSaveLayer == fFirstSaveLayerStackLevel){
   550         fFirstSaveLayerStackLevel = this->getSaveCount();
   551     }
   553     this->INHERITED::willSaveLayer(bounds, paint, saveFlags);
   554     // we don't create a layer
   555     return kNoLayer_SaveLayerStrategy;
   556 }
   558 void SkGPipeCanvas::willRestore() {
   559     NOTIFY_SETUP(this);
   560     if (this->needOpBytes()) {
   561         this->writeOp(kRestore_DrawOp);
   562     }
   564     if (this->getSaveCount() - 1 == fFirstSaveLayerStackLevel){
   565         fFirstSaveLayerStackLevel = kNoSaveLayer;
   566     }
   568     this->INHERITED::willRestore();
   569 }
   571 bool SkGPipeCanvas::isDrawingToLayer() const {
   572     return kNoSaveLayer != fFirstSaveLayerStackLevel;
   573 }
   575 void SkGPipeCanvas::didTranslate(SkScalar dx, SkScalar dy) {
   576     if (dx || dy) {
   577         NOTIFY_SETUP(this);
   578         if (this->needOpBytes(2 * sizeof(SkScalar))) {
   579             this->writeOp(kTranslate_DrawOp);
   580             fWriter.writeScalar(dx);
   581             fWriter.writeScalar(dy);
   582         }
   583     }
   584     this->INHERITED::didTranslate(dx, dy);
   585 }
   587 void SkGPipeCanvas::didScale(SkScalar sx, SkScalar sy) {
   588     if (sx || sy) {
   589         NOTIFY_SETUP(this);
   590         if (this->needOpBytes(2 * sizeof(SkScalar))) {
   591             this->writeOp(kScale_DrawOp);
   592             fWriter.writeScalar(sx);
   593             fWriter.writeScalar(sy);
   594         }
   595     }
   596     this->INHERITED::didScale(sx, sy);
   597 }
   599 void SkGPipeCanvas::didRotate(SkScalar degrees) {
   600     if (degrees) {
   601         NOTIFY_SETUP(this);
   602         if (this->needOpBytes(sizeof(SkScalar))) {
   603             this->writeOp(kRotate_DrawOp);
   604             fWriter.writeScalar(degrees);
   605         }
   606     }
   607     this->INHERITED::didRotate(degrees);
   608 }
   610 void SkGPipeCanvas::didSkew(SkScalar sx, SkScalar sy) {
   611     if (sx || sy) {
   612         NOTIFY_SETUP(this);
   613         if (this->needOpBytes(2 * sizeof(SkScalar))) {
   614             this->writeOp(kSkew_DrawOp);
   615             fWriter.writeScalar(sx);
   616             fWriter.writeScalar(sy);
   617         }
   618     }
   619     this->INHERITED::didSkew(sx, sy);
   620 }
   622 void SkGPipeCanvas::didConcat(const SkMatrix& matrix) {
   623     if (!matrix.isIdentity()) {
   624         NOTIFY_SETUP(this);
   625         if (this->needOpBytes(matrix.writeToMemory(NULL))) {
   626             this->writeOp(kConcat_DrawOp);
   627             fWriter.writeMatrix(matrix);
   628         }
   629     }
   630     this->INHERITED::didConcat(matrix);
   631 }
   633 void SkGPipeCanvas::didSetMatrix(const SkMatrix& matrix) {
   634     NOTIFY_SETUP(this);
   635     if (this->needOpBytes(matrix.writeToMemory(NULL))) {
   636         this->writeOp(kSetMatrix_DrawOp);
   637         fWriter.writeMatrix(matrix);
   638     }
   639     this->INHERITED::didSetMatrix(matrix);
   640 }
   642 void SkGPipeCanvas::onClipRect(const SkRect& rect, SkRegion::Op rgnOp,
   643                                ClipEdgeStyle edgeStyle) {
   644     NOTIFY_SETUP(this);
   645     if (this->needOpBytes(sizeof(SkRect))) {
   646         unsigned flags = 0;
   647         if (kSoft_ClipEdgeStyle == edgeStyle) {
   648             flags = kClip_HasAntiAlias_DrawOpFlag;
   649         }
   650         this->writeOp(kClipRect_DrawOp, flags, rgnOp);
   651         fWriter.writeRect(rect);
   652     }
   653     this->INHERITED::onClipRect(rect, rgnOp, edgeStyle);
   654 }
   656 void SkGPipeCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op rgnOp,
   657                                 ClipEdgeStyle edgeStyle) {
   658     NOTIFY_SETUP(this);
   659     if (this->needOpBytes(kSizeOfFlatRRect)) {
   660         unsigned flags = 0;
   661         if (kSoft_ClipEdgeStyle == edgeStyle) {
   662             flags = kClip_HasAntiAlias_DrawOpFlag;
   663         }
   664         this->writeOp(kClipRRect_DrawOp, flags, rgnOp);
   665         fWriter.writeRRect(rrect);
   666     }
   667     this->INHERITED::onClipRRect(rrect, rgnOp, edgeStyle);
   668 }
   670 void SkGPipeCanvas::onClipPath(const SkPath& path, SkRegion::Op rgnOp,
   671                                ClipEdgeStyle edgeStyle) {
   672     NOTIFY_SETUP(this);
   673     if (this->needOpBytes(path.writeToMemory(NULL))) {
   674         unsigned flags = 0;
   675         if (kSoft_ClipEdgeStyle == edgeStyle) {
   676             flags = kClip_HasAntiAlias_DrawOpFlag;
   677         }
   678         this->writeOp(kClipPath_DrawOp, flags, rgnOp);
   679         fWriter.writePath(path);
   680     }
   681     // we just pass on the bounds of the path
   682     this->INHERITED::onClipRect(path.getBounds(), rgnOp, edgeStyle);
   683 }
   685 void SkGPipeCanvas::onClipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
   686     NOTIFY_SETUP(this);
   687     if (this->needOpBytes(region.writeToMemory(NULL))) {
   688         this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
   689         fWriter.writeRegion(region);
   690     }
   691     this->INHERITED::onClipRegion(region, rgnOp);
   692 }
   694 ///////////////////////////////////////////////////////////////////////////////
   696 void SkGPipeCanvas::clear(SkColor color) {
   697     NOTIFY_SETUP(this);
   698     unsigned flags = 0;
   699     if (color) {
   700         flags |= kClear_HasColor_DrawOpFlag;
   701     }
   702     if (this->needOpBytes(sizeof(SkColor))) {
   703         this->writeOp(kDrawClear_DrawOp, flags, 0);
   704         if (color) {
   705             fWriter.write32(color);
   706         }
   707     }
   708 }
   710 void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
   711     NOTIFY_SETUP(this);
   712     this->writePaint(paint);
   713     if (this->needOpBytes()) {
   714         this->writeOp(kDrawPaint_DrawOp);
   715     }
   716 }
   718 void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
   719                                const SkPoint pts[], const SkPaint& paint) {
   720     if (count) {
   721         NOTIFY_SETUP(this);
   722         this->writePaint(paint);
   723         if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
   724             this->writeOp(kDrawPoints_DrawOp, mode, 0);
   725             fWriter.write32(count);
   726             fWriter.write(pts, count * sizeof(SkPoint));
   727         }
   728     }
   729 }
   731 void SkGPipeCanvas::drawOval(const SkRect& rect, const SkPaint& paint) {
   732     NOTIFY_SETUP(this);
   733     this->writePaint(paint);
   734     if (this->needOpBytes(sizeof(SkRect))) {
   735         this->writeOp(kDrawOval_DrawOp);
   736         fWriter.writeRect(rect);
   737     }
   738 }
   740 void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
   741     NOTIFY_SETUP(this);
   742     this->writePaint(paint);
   743     if (this->needOpBytes(sizeof(SkRect))) {
   744         this->writeOp(kDrawRect_DrawOp);
   745         fWriter.writeRect(rect);
   746     }
   747 }
   749 void SkGPipeCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
   750     NOTIFY_SETUP(this);
   751     this->writePaint(paint);
   752     if (this->needOpBytes(kSizeOfFlatRRect)) {
   753         this->writeOp(kDrawRRect_DrawOp);
   754         fWriter.writeRRect(rrect);
   755     }
   756 }
   758 void SkGPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
   759                                  const SkPaint& paint) {
   760     NOTIFY_SETUP(this);
   761     this->writePaint(paint);
   762     if (this->needOpBytes(kSizeOfFlatRRect * 2)) {
   763         this->writeOp(kDrawDRRect_DrawOp);
   764         fWriter.writeRRect(outer);
   765         fWriter.writeRRect(inner);
   766     }
   767 }
   769 void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
   770     NOTIFY_SETUP(this);
   771     this->writePaint(paint);
   772     if (this->needOpBytes(path.writeToMemory(NULL))) {
   773         this->writeOp(kDrawPath_DrawOp);
   774         fWriter.writePath(path);
   775     }
   776 }
   778 bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op,
   779                                      unsigned flags,
   780                                      size_t opBytesNeeded,
   781                                      const SkPaint* paint) {
   782     if (paint != NULL) {
   783         flags |= kDrawBitmap_HasPaint_DrawOpFlag;
   784         this->writePaint(*paint);
   785     }
   786     if (this->needOpBytes(opBytesNeeded)) {
   787         SkASSERT(fBitmapHeap != NULL);
   788         int32_t bitmapIndex = fBitmapHeap->insert(bm);
   789         if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) {
   790             return false;
   791         }
   792         this->writeOp(op, flags, bitmapIndex);
   793         return true;
   794     }
   795     return false;
   796 }
   798 void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
   799                                const SkPaint* paint) {
   800     NOTIFY_SETUP(this);
   801     size_t opBytesNeeded = sizeof(SkScalar) * 2;
   803     if (this->commonDrawBitmap(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) {
   804         fWriter.writeScalar(left);
   805         fWriter.writeScalar(top);
   806     }
   807 }
   809 void SkGPipeCanvas::drawBitmapRectToRect(const SkBitmap& bm, const SkRect* src,
   810                                          const SkRect& dst, const SkPaint* paint,
   811                                          DrawBitmapRectFlags dbmrFlags) {
   812     NOTIFY_SETUP(this);
   813     size_t opBytesNeeded = sizeof(SkRect);
   814     bool hasSrc = src != NULL;
   815     unsigned flags;
   816     if (hasSrc) {
   817         flags = kDrawBitmap_HasSrcRect_DrawOpFlag;
   818         opBytesNeeded += sizeof(int32_t) * 4;
   819     } else {
   820         flags = 0;
   821     }
   822     if (dbmrFlags & kBleed_DrawBitmapRectFlag) {
   823         flags |= kDrawBitmap_Bleed_DrawOpFlag;
   824     }
   826     if (this->commonDrawBitmap(bm, kDrawBitmapRectToRect_DrawOp, flags, opBytesNeeded, paint)) {
   827         if (hasSrc) {
   828             fWriter.writeRect(*src);
   829         }
   830         fWriter.writeRect(dst);
   831     }
   832 }
   834 void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap& bm, const SkMatrix& matrix,
   835                                      const SkPaint* paint) {
   836     NOTIFY_SETUP(this);
   837     size_t opBytesNeeded = matrix.writeToMemory(NULL);
   839     if (this->commonDrawBitmap(bm, kDrawBitmapMatrix_DrawOp, 0, opBytesNeeded, paint)) {
   840         fWriter.writeMatrix(matrix);
   841     }
   842 }
   844 void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
   845                                    const SkRect& dst, const SkPaint* paint) {
   846     NOTIFY_SETUP(this);
   847     size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(SkRect);
   849     if (this->commonDrawBitmap(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, paint)) {
   850         fWriter.write32(center.fLeft);
   851         fWriter.write32(center.fTop);
   852         fWriter.write32(center.fRight);
   853         fWriter.write32(center.fBottom);
   854         fWriter.writeRect(dst);
   855     }
   856 }
   858 void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
   859                                    const SkPaint* paint) {
   860     NOTIFY_SETUP(this);
   861     size_t opBytesNeeded = sizeof(int32_t) * 2;
   863     if (this->commonDrawBitmap(bm, kDrawSprite_DrawOp, 0, opBytesNeeded, paint)) {
   864         fWriter.write32(left);
   865         fWriter.write32(top);
   866     }
   867 }
   869 void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
   870                                  SkScalar y, const SkPaint& paint) {
   871     if (byteLength) {
   872         NOTIFY_SETUP(this);
   873         this->writePaint(paint);
   874         if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
   875             this->writeOp(kDrawText_DrawOp);
   876             fWriter.write32(byteLength);
   877             fWriter.writePad(text, byteLength);
   878             fWriter.writeScalar(x);
   879             fWriter.writeScalar(y);
   880         }
   881     }
   882 }
   884 void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
   885                                 const SkPoint pos[], const SkPaint& paint) {
   886     if (byteLength) {
   887         NOTIFY_SETUP(this);
   888         this->writePaint(paint);
   889         int count = paint.textToGlyphs(text, byteLength, NULL);
   890         if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
   891             this->writeOp(kDrawPosText_DrawOp);
   892             fWriter.write32(byteLength);
   893             fWriter.writePad(text, byteLength);
   894             fWriter.write32(count);
   895             fWriter.write(pos, count * sizeof(SkPoint));
   896         }
   897     }
   898 }
   900 void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
   901                                  const SkScalar xpos[], SkScalar constY,
   902                                  const SkPaint& paint) {
   903     if (byteLength) {
   904         NOTIFY_SETUP(this);
   905         this->writePaint(paint);
   906         int count = paint.textToGlyphs(text, byteLength, NULL);
   907         if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
   908             this->writeOp(kDrawPosTextH_DrawOp);
   909             fWriter.write32(byteLength);
   910             fWriter.writePad(text, byteLength);
   911             fWriter.write32(count);
   912             fWriter.write(xpos, count * sizeof(SkScalar));
   913             fWriter.writeScalar(constY);
   914         }
   915     }
   916 }
   918 void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
   919                                    const SkPath& path, const SkMatrix* matrix,
   920                                    const SkPaint& paint) {
   921     if (byteLength) {
   922         NOTIFY_SETUP(this);
   923         unsigned flags = 0;
   924         size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(NULL);
   925         if (matrix) {
   926             flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
   927             size += matrix->writeToMemory(NULL);
   928         }
   929         this->writePaint(paint);
   930         if (this->needOpBytes(size)) {
   931             this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
   933             fWriter.write32(byteLength);
   934             fWriter.writePad(text, byteLength);
   936             fWriter.writePath(path);
   937             if (matrix) {
   938                 fWriter.writeMatrix(*matrix);
   939             }
   940         }
   941     }
   942 }
   944 void SkGPipeCanvas::drawPicture(SkPicture& picture) {
   945     // we want to playback the picture into individual draw calls
   946     this->INHERITED::drawPicture(picture);
   947 }
   949 void SkGPipeCanvas::drawVertices(VertexMode vmode, int vertexCount,
   950                                  const SkPoint vertices[], const SkPoint texs[],
   951                                  const SkColor colors[], SkXfermode* xfer,
   952                                  const uint16_t indices[], int indexCount,
   953                                  const SkPaint& paint) {
   954     if (0 == vertexCount) {
   955         return;
   956     }
   958     NOTIFY_SETUP(this);
   959     size_t size = 4 + vertexCount * sizeof(SkPoint);
   960     this->writePaint(paint);
   961     unsigned flags = 0;
   962     if (texs) {
   963         flags |= kDrawVertices_HasTexs_DrawOpFlag;
   964         size += vertexCount * sizeof(SkPoint);
   965     }
   966     if (colors) {
   967         flags |= kDrawVertices_HasColors_DrawOpFlag;
   968         size += vertexCount * sizeof(SkColor);
   969     }
   970     if (indices && indexCount > 0) {
   971         flags |= kDrawVertices_HasIndices_DrawOpFlag;
   972         size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
   973     }
   974     if (xfer && !SkXfermode::IsMode(xfer, SkXfermode::kModulate_Mode)) {
   975         flags |= kDrawVertices_HasXfermode_DrawOpFlag;
   976         size += sizeof(int32_t);    // mode enum
   977     }
   979     if (this->needOpBytes(size)) {
   980         this->writeOp(kDrawVertices_DrawOp, flags, 0);
   981         fWriter.write32(vmode);
   982         fWriter.write32(vertexCount);
   983         fWriter.write(vertices, vertexCount * sizeof(SkPoint));
   984         if (texs) {
   985             fWriter.write(texs, vertexCount * sizeof(SkPoint));
   986         }
   987         if (colors) {
   988             fWriter.write(colors, vertexCount * sizeof(SkColor));
   989         }
   990         if (flags & kDrawVertices_HasXfermode_DrawOpFlag) {
   991             SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
   992             (void)xfer->asMode(&mode);
   993             fWriter.write32(mode);
   994         }
   995         if (indices && indexCount > 0) {
   996             fWriter.write32(indexCount);
   997             fWriter.writePad(indices, indexCount * sizeof(uint16_t));
   998         }
   999     }
  1002 void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
  1003     if (size && ptr) {
  1004         NOTIFY_SETUP(this);
  1005         unsigned data = 0;
  1006         if (size < (1 << DRAWOPS_DATA_BITS)) {
  1007             data = (unsigned)size;
  1009         if (this->needOpBytes(4 + SkAlign4(size))) {
  1010             this->writeOp(kDrawData_DrawOp, 0, data);
  1011             if (0 == data) {
  1012                 fWriter.write32(size);
  1014             fWriter.writePad(ptr, size);
  1019 void SkGPipeCanvas::beginCommentGroup(const char* description) {
  1020     // ignore for now
  1023 void SkGPipeCanvas::addComment(const char* kywd, const char* value) {
  1024     // ignore for now
  1027 void SkGPipeCanvas::endCommentGroup() {
  1028     // ignore for now
  1031 void SkGPipeCanvas::flushRecording(bool detachCurrentBlock) {
  1032     doNotify();
  1033     if (detachCurrentBlock) {
  1034         // force a new block to be requested for the next recorded command
  1035         fBlockSize = 0;
  1039 size_t SkGPipeCanvas::freeMemoryIfPossible(size_t bytesToFree) {
  1040     return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->freeMemoryIfPossible(bytesToFree);
  1043 ///////////////////////////////////////////////////////////////////////////////
  1045 template <typename T> uint32_t castToU32(T value) {
  1046     union {
  1047         T           fSrc;
  1048         uint32_t    fDst;
  1049     } data;
  1050     data.fSrc = value;
  1051     return data.fDst;
  1054 void SkGPipeCanvas::writePaint(const SkPaint& paint) {
  1055     if (fDone) {
  1056         return;
  1058     SkPaint& base = fPaint;
  1059     uint32_t storage[32];
  1060     uint32_t* ptr = storage;
  1062     if (base.getFlags() != paint.getFlags()) {
  1063         *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
  1064         base.setFlags(paint.getFlags());
  1066     if (base.getColor() != paint.getColor()) {
  1067         *ptr++ = PaintOp_packOp(kColor_PaintOp);
  1068         *ptr++ = paint.getColor();
  1069         base.setColor(paint.getColor());
  1071     if (base.getStyle() != paint.getStyle()) {
  1072         *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
  1073         base.setStyle(paint.getStyle());
  1075     if (base.getStrokeJoin() != paint.getStrokeJoin()) {
  1076         *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
  1077         base.setStrokeJoin(paint.getStrokeJoin());
  1079     if (base.getStrokeCap() != paint.getStrokeCap()) {
  1080         *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
  1081         base.setStrokeCap(paint.getStrokeCap());
  1083     if (base.getStrokeWidth() != paint.getStrokeWidth()) {
  1084         *ptr++ = PaintOp_packOp(kWidth_PaintOp);
  1085         *ptr++ = castToU32(paint.getStrokeWidth());
  1086         base.setStrokeWidth(paint.getStrokeWidth());
  1088     if (base.getStrokeMiter() != paint.getStrokeMiter()) {
  1089         *ptr++ = PaintOp_packOp(kMiter_PaintOp);
  1090         *ptr++ = castToU32(paint.getStrokeMiter());
  1091         base.setStrokeMiter(paint.getStrokeMiter());
  1093     if (base.getTextEncoding() != paint.getTextEncoding()) {
  1094         *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
  1095         base.setTextEncoding(paint.getTextEncoding());
  1097     if (base.getHinting() != paint.getHinting()) {
  1098         *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
  1099         base.setHinting(paint.getHinting());
  1101     if (base.getTextAlign() != paint.getTextAlign()) {
  1102         *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
  1103         base.setTextAlign(paint.getTextAlign());
  1105     if (base.getTextSize() != paint.getTextSize()) {
  1106         *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
  1107         *ptr++ = castToU32(paint.getTextSize());
  1108         base.setTextSize(paint.getTextSize());
  1110     if (base.getTextScaleX() != paint.getTextScaleX()) {
  1111         *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
  1112         *ptr++ = castToU32(paint.getTextScaleX());
  1113         base.setTextScaleX(paint.getTextScaleX());
  1115     if (base.getTextSkewX() != paint.getTextSkewX()) {
  1116         *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
  1117         *ptr++ = castToU32(paint.getTextSkewX());
  1118         base.setTextSkewX(paint.getTextSkewX());
  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());
  1134         base.setTypeface(paint.getTypeface());
  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;
  1145         // Store the index of any flat that needs to be kept. 0 means no flat.
  1146         if (index > 0) {
  1147             fFlattenableHeap.markFlatForKeeping(index);
  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;
  1156     size_t size = (char*)ptr - (char*)storage;
  1157     if (size && this->needOpBytes(size)) {
  1158         this->writeOp(kPaintOp_DrawOp, 0, size);
  1159         fWriter.write(storage, size);
  1160         for (size_t i = 0; i < size/4; i++) {
  1161 //            SkDebugf("[%d] %08X\n", i, storage[i]);
  1165     //
  1166     //  Do these after we've written kPaintOp_DrawOp
  1168     if (base.getAnnotation() != paint.getAnnotation()) {
  1169         if (NULL == paint.getAnnotation()) {
  1170             if (this->needOpBytes()) {
  1171                 this->writeOp(kSetAnnotation_DrawOp, 0, 0);
  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, size);
  1179                 buffer.writeToMemory(fWriter.reserve(size));
  1182         base.setAnnotation(paint.getAnnotation());
  1186 ///////////////////////////////////////////////////////////////////////////////
  1188 #include "SkGPipe.h"
  1190 SkGPipeController::~SkGPipeController() {
  1191     SkSafeUnref(fCanvas);
  1194 void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) {
  1195     SkRefCnt_SafeAssign(fCanvas, canvas);
  1198 ///////////////////////////////////////////////////////////////////////////////
  1200 SkGPipeWriter::SkGPipeWriter()
  1201 : fWriter(0) {
  1202     fCanvas = NULL;
  1205 SkGPipeWriter::~SkGPipeWriter() {
  1206     this->endRecording();
  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));
  1215     controller->setCanvas(fCanvas);
  1216     return fCanvas;
  1219 void SkGPipeWriter::endRecording() {
  1220     if (fCanvas) {
  1221         fCanvas->finish(true);
  1222         fCanvas->unref();
  1223         fCanvas = NULL;
  1227 void SkGPipeWriter::flushRecording(bool detachCurrentBlock) {
  1228     if (fCanvas) {
  1229         fCanvas->flushRecording(detachCurrentBlock);
  1233 size_t SkGPipeWriter::freeMemoryIfPossible(size_t bytesToFree) {
  1234     if (fCanvas) {
  1235         return fCanvas->freeMemoryIfPossible(bytesToFree);
  1237     return 0;
  1240 size_t SkGPipeWriter::storageAllocatedForRecording() const {
  1241     return NULL == fCanvas ? 0 : fCanvas->storageAllocatedForRecording();
  1244 ///////////////////////////////////////////////////////////////////////////////
  1246 BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) {
  1247     SkASSERT(canvas != NULL);
  1248     fCanvas = canvas;
  1249     fCanvas->ref();
  1252 BitmapShuttle::~BitmapShuttle() {
  1253     this->removeCanvas();
  1256 bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) {
  1257     SkASSERT(fCanvas != NULL);
  1258     return fCanvas->shuttleBitmap(bitmap, slot);
  1261 void BitmapShuttle::removeCanvas() {
  1262     if (NULL == fCanvas) {
  1263         return;
  1265     fCanvas->unref();
  1266     fCanvas = NULL;

mercurial