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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/pipe/SkGPipeWrite.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1267 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2011 Google Inc.
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +#include "SkAnnotation.h"
    1.13 +#include "SkBitmapDevice.h"
    1.14 +#include "SkBitmapHeap.h"
    1.15 +#include "SkCanvas.h"
    1.16 +#include "SkColorFilter.h"
    1.17 +#include "SkData.h"
    1.18 +#include "SkDrawLooper.h"
    1.19 +#include "SkGPipe.h"
    1.20 +#include "SkGPipePriv.h"
    1.21 +#include "SkImageFilter.h"
    1.22 +#include "SkMaskFilter.h"
    1.23 +#include "SkWriteBuffer.h"
    1.24 +#include "SkPaint.h"
    1.25 +#include "SkPathEffect.h"
    1.26 +#include "SkPictureFlat.h"
    1.27 +#include "SkRasterizer.h"
    1.28 +#include "SkRRect.h"
    1.29 +#include "SkShader.h"
    1.30 +#include "SkStream.h"
    1.31 +#include "SkTSearch.h"
    1.32 +#include "SkTypeface.h"
    1.33 +#include "SkWriter32.h"
    1.34 +
    1.35 +enum {
    1.36 +    kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector)
    1.37 +};
    1.38 +
    1.39 +static bool isCrossProcess(uint32_t flags) {
    1.40 +    return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag);
    1.41 +}
    1.42 +
    1.43 +static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
    1.44 +    SkASSERT(paintFlat < kCount_PaintFlats);
    1.45 +    switch (paintFlat) {
    1.46 +        case kColorFilter_PaintFlat:    return paint.getColorFilter();
    1.47 +        case kDrawLooper_PaintFlat:     return paint.getLooper();
    1.48 +        case kMaskFilter_PaintFlat:     return paint.getMaskFilter();
    1.49 +        case kPathEffect_PaintFlat:     return paint.getPathEffect();
    1.50 +        case kRasterizer_PaintFlat:     return paint.getRasterizer();
    1.51 +        case kShader_PaintFlat:         return paint.getShader();
    1.52 +        case kImageFilter_PaintFlat:    return paint.getImageFilter();
    1.53 +        case kXfermode_PaintFlat:       return paint.getXfermode();
    1.54 +    }
    1.55 +    SkDEBUGFAIL("never gets here");
    1.56 +    return NULL;
    1.57 +}
    1.58 +
    1.59 +static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
    1.60 +    SkASSERT(typeface);
    1.61 +    SkDynamicMemoryWStream stream;
    1.62 +    typeface->serialize(&stream);
    1.63 +    size_t size = stream.getOffset();
    1.64 +    if (writer) {
    1.65 +        writer->write32(size);
    1.66 +        SkAutoDataUnref data(stream.copyToData());
    1.67 +        writer->writePad(data->data(), size);
    1.68 +    }
    1.69 +    return 4 + SkAlign4(size);
    1.70 +}
    1.71 +
    1.72 +///////////////////////////////////////////////////////////////////////////////
    1.73 +
    1.74 +class FlattenableHeap : public SkFlatController {
    1.75 +public:
    1.76 +    FlattenableHeap(int numFlatsToKeep, SkNamedFactorySet* fset, bool isCrossProcess)
    1.77 +    : INHERITED(isCrossProcess ? SkWriteBuffer::kCrossProcess_Flag : 0)
    1.78 +    , fNumFlatsToKeep(numFlatsToKeep) {
    1.79 +        SkASSERT((isCrossProcess && fset != NULL) || (!isCrossProcess && NULL == fset));
    1.80 +        if (isCrossProcess) {
    1.81 +            this->setNamedFactorySet(fset);
    1.82 +        }
    1.83 +    }
    1.84 +
    1.85 +    ~FlattenableHeap() {
    1.86 +        fPointers.freeAll();
    1.87 +    }
    1.88 +
    1.89 +    virtual void* allocThrow(size_t bytes) SK_OVERRIDE;
    1.90 +
    1.91 +    virtual void unalloc(void* ptr) SK_OVERRIDE;
    1.92 +
    1.93 +    void setBitmapStorage(SkBitmapHeap* heap) {
    1.94 +        this->setBitmapHeap(heap);
    1.95 +    }
    1.96 +
    1.97 +    const SkFlatData* flatToReplace() const;
    1.98 +
    1.99 +    // Mark an SkFlatData as one that should not be returned by flatToReplace.
   1.100 +    // Takes the result of SkFlatData::index() as its parameter.
   1.101 +    void markFlatForKeeping(int index) {
   1.102 +        *fFlatsThatMustBeKept.append() = index;
   1.103 +    }
   1.104 +
   1.105 +    void markAllFlatsSafeToDelete() {
   1.106 +        fFlatsThatMustBeKept.reset();
   1.107 +    }
   1.108 +
   1.109 +private:
   1.110 +    // Keep track of the indices (i.e. the result of SkFlatData::index()) of
   1.111 +    // flats that must be kept, since they are on the current paint.
   1.112 +    SkTDArray<int>   fFlatsThatMustBeKept;
   1.113 +    SkTDArray<void*> fPointers;
   1.114 +    const int        fNumFlatsToKeep;
   1.115 +
   1.116 +    typedef SkFlatController INHERITED;
   1.117 +};
   1.118 +
   1.119 +void FlattenableHeap::unalloc(void* ptr) {
   1.120 +    int indexToRemove = fPointers.rfind(ptr);
   1.121 +    if (indexToRemove >= 0) {
   1.122 +        sk_free(ptr);
   1.123 +        fPointers.remove(indexToRemove);
   1.124 +    }
   1.125 +}
   1.126 +
   1.127 +void* FlattenableHeap::allocThrow(size_t bytes) {
   1.128 +    void* ptr = sk_malloc_throw(bytes);
   1.129 +    *fPointers.append() = ptr;
   1.130 +    return ptr;
   1.131 +}
   1.132 +
   1.133 +const SkFlatData* FlattenableHeap::flatToReplace() const {
   1.134 +    // First, determine whether we should replace one.
   1.135 +    if (fPointers.count() > fNumFlatsToKeep) {
   1.136 +        // Look through the flattenable heap.
   1.137 +        // TODO: Return the LRU flat.
   1.138 +        for (int i = 0; i < fPointers.count(); i++) {
   1.139 +            SkFlatData* potential = (SkFlatData*)fPointers[i];
   1.140 +            // Make sure that it is not one that must be kept.
   1.141 +            bool mustKeep = false;
   1.142 +            for (int j = 0; j < fFlatsThatMustBeKept.count(); j++) {
   1.143 +                if (potential->index() == fFlatsThatMustBeKept[j]) {
   1.144 +                    mustKeep = true;
   1.145 +                    break;
   1.146 +                }
   1.147 +            }
   1.148 +            if (!mustKeep) {
   1.149 +                return potential;
   1.150 +            }
   1.151 +        }
   1.152 +    }
   1.153 +    return NULL;
   1.154 +}
   1.155 +
   1.156 +///////////////////////////////////////////////////////////////////////////////
   1.157 +
   1.158 +struct SkFlattenableTraits {
   1.159 +    static void Flatten(SkWriteBuffer& buffer, const SkFlattenable& flattenable) {
   1.160 +        buffer.writeFlattenable(&flattenable);
   1.161 +    }
   1.162 +    // No need to define unflatten if we never call it.
   1.163 +};
   1.164 +typedef SkFlatDictionary<SkFlattenable, SkFlattenableTraits> FlatDictionary;
   1.165 +
   1.166 +///////////////////////////////////////////////////////////////////////////////
   1.167 +
   1.168 +/**
   1.169 + * If SkBitmaps are to be flattened to send to the reader, this class is
   1.170 + * provided to the SkBitmapHeap to tell the SkGPipeCanvas to do so.
   1.171 + */
   1.172 +class BitmapShuttle : public SkBitmapHeap::ExternalStorage {
   1.173 +public:
   1.174 +    BitmapShuttle(SkGPipeCanvas*);
   1.175 +
   1.176 +    ~BitmapShuttle();
   1.177 +
   1.178 +    virtual bool insert(const SkBitmap& bitmap, int32_t slot) SK_OVERRIDE;
   1.179 +
   1.180 +    /**
   1.181 +     *  Remove the SkGPipeCanvas used for insertion. After this, calls to
   1.182 +     *  insert will crash.
   1.183 +     */
   1.184 +    void removeCanvas();
   1.185 +
   1.186 +private:
   1.187 +    SkGPipeCanvas*    fCanvas;
   1.188 +};
   1.189 +
   1.190 +///////////////////////////////////////////////////////////////////////////////
   1.191 +
   1.192 +class SkGPipeCanvas : public SkCanvas {
   1.193 +public:
   1.194 +    SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags,
   1.195 +                  uint32_t width, uint32_t height);
   1.196 +    virtual ~SkGPipeCanvas();
   1.197 +
   1.198 +    /**
   1.199 +     *  Called when nothing else is to be written to the stream. Any repeated
   1.200 +     *  calls are ignored.
   1.201 +     *
   1.202 +     *  @param notifyReaders Whether to send a message to the reader(s) that
   1.203 +     *      the writer is through sending commands. Should generally be true,
   1.204 +     *      unless there is an error which prevents further messages from
   1.205 +     *      being sent.
   1.206 +     */
   1.207 +    void finish(bool notifyReaders) {
   1.208 +        if (fDone) {
   1.209 +            return;
   1.210 +        }
   1.211 +        if (notifyReaders && this->needOpBytes()) {
   1.212 +            this->writeOp(kDone_DrawOp);
   1.213 +            this->doNotify();
   1.214 +        }
   1.215 +        if (shouldFlattenBitmaps(fFlags)) {
   1.216 +            // The following circular references exist:
   1.217 +            // fFlattenableHeap -> fWriteBuffer -> fBitmapStorage -> fExternalStorage -> fCanvas
   1.218 +            // fBitmapHeap -> fExternalStorage -> fCanvas
   1.219 +            // fFlattenableHeap -> fBitmapStorage -> fExternalStorage -> fCanvas
   1.220 +
   1.221 +            // Break them all by destroying the final link to this SkGPipeCanvas.
   1.222 +            fBitmapShuttle->removeCanvas();
   1.223 +        }
   1.224 +        fDone = true;
   1.225 +    }
   1.226 +
   1.227 +    void flushRecording(bool detachCurrentBlock);
   1.228 +    size_t freeMemoryIfPossible(size_t bytesToFree);
   1.229 +
   1.230 +    size_t storageAllocatedForRecording() {
   1.231 +        return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->bytesAllocated();
   1.232 +    }
   1.233 +
   1.234 +    // overrides from SkCanvas
   1.235 +    virtual bool isDrawingToLayer() const SK_OVERRIDE;
   1.236 +    virtual void clear(SkColor) SK_OVERRIDE;
   1.237 +    virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
   1.238 +    virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
   1.239 +                            const SkPaint&) SK_OVERRIDE;
   1.240 +    virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE;
   1.241 +    virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE;
   1.242 +    virtual void drawRRect(const SkRRect&, const SkPaint&) SK_OVERRIDE;
   1.243 +    virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE;
   1.244 +    virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
   1.245 +                            const SkPaint*) SK_OVERRIDE;
   1.246 +    virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src,
   1.247 +                                      const SkRect& dst, const SkPaint* paint,
   1.248 +                                      DrawBitmapRectFlags flags) SK_OVERRIDE;
   1.249 +    virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
   1.250 +                                  const SkPaint*) SK_OVERRIDE;
   1.251 +    virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
   1.252 +                                const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE;
   1.253 +    virtual void drawSprite(const SkBitmap&, int left, int top,
   1.254 +                            const SkPaint*) SK_OVERRIDE;
   1.255 +    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
   1.256 +                          SkScalar y, const SkPaint&) SK_OVERRIDE;
   1.257 +    virtual void drawPosText(const void* text, size_t byteLength,
   1.258 +                             const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
   1.259 +    virtual void drawPosTextH(const void* text, size_t byteLength,
   1.260 +                              const SkScalar xpos[], SkScalar constY,
   1.261 +                              const SkPaint&) SK_OVERRIDE;
   1.262 +    virtual void drawTextOnPath(const void* text, size_t byteLength,
   1.263 +                            const SkPath& path, const SkMatrix* matrix,
   1.264 +                                const SkPaint&) SK_OVERRIDE;
   1.265 +    virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
   1.266 +    virtual void drawVertices(VertexMode, int vertexCount,
   1.267 +                          const SkPoint vertices[], const SkPoint texs[],
   1.268 +                          const SkColor colors[], SkXfermode*,
   1.269 +                          const uint16_t indices[], int indexCount,
   1.270 +                              const SkPaint&) SK_OVERRIDE;
   1.271 +    virtual void drawData(const void*, size_t) SK_OVERRIDE;
   1.272 +    virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
   1.273 +    virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE;
   1.274 +    virtual void endCommentGroup() SK_OVERRIDE;
   1.275 +
   1.276 +    /**
   1.277 +     * Flatten an SkBitmap to send to the reader, where it will be referenced
   1.278 +     * according to slot.
   1.279 +     */
   1.280 +    bool shuttleBitmap(const SkBitmap&, int32_t slot);
   1.281 +
   1.282 +protected:
   1.283 +    virtual void willSave(SaveFlags) SK_OVERRIDE;
   1.284 +    virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
   1.285 +    virtual void willRestore() SK_OVERRIDE;
   1.286 +
   1.287 +    virtual void didTranslate(SkScalar, SkScalar) SK_OVERRIDE;
   1.288 +    virtual void didScale(SkScalar, SkScalar) SK_OVERRIDE;
   1.289 +    virtual void didRotate(SkScalar) SK_OVERRIDE;
   1.290 +    virtual void didSkew(SkScalar, SkScalar) SK_OVERRIDE;
   1.291 +    virtual void didConcat(const SkMatrix&) SK_OVERRIDE;
   1.292 +    virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
   1.293 +
   1.294 +    virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
   1.295 +
   1.296 +    virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
   1.297 +    virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
   1.298 +    virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
   1.299 +    virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
   1.300 +
   1.301 +private:
   1.302 +    enum {
   1.303 +        kNoSaveLayer = -1,
   1.304 +    };
   1.305 +    SkNamedFactorySet* fFactorySet;
   1.306 +    int                fFirstSaveLayerStackLevel;
   1.307 +    SkBitmapHeap*      fBitmapHeap;
   1.308 +    SkGPipeController* fController;
   1.309 +    SkWriter32&        fWriter;
   1.310 +    size_t             fBlockSize; // amount allocated for writer
   1.311 +    size_t             fBytesNotified;
   1.312 +    bool               fDone;
   1.313 +    const uint32_t     fFlags;
   1.314 +
   1.315 +    SkRefCntSet        fTypefaceSet;
   1.316 +
   1.317 +    uint32_t getTypefaceID(SkTypeface*);
   1.318 +
   1.319 +    inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
   1.320 +        fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
   1.321 +    }
   1.322 +
   1.323 +    inline void writeOp(DrawOps op) {
   1.324 +        fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
   1.325 +    }
   1.326 +
   1.327 +    bool needOpBytes(size_t size = 0);
   1.328 +
   1.329 +    inline void doNotify() {
   1.330 +        if (!fDone) {
   1.331 +            size_t bytes = fWriter.bytesWritten() - fBytesNotified;
   1.332 +            if (bytes > 0) {
   1.333 +                fController->notifyWritten(bytes);
   1.334 +                fBytesNotified += bytes;
   1.335 +            }
   1.336 +        }
   1.337 +    }
   1.338 +
   1.339 +    // Should be called after any calls to an SkFlatDictionary::findAndReplace
   1.340 +    // if a new SkFlatData was added when in cross process mode
   1.341 +    void flattenFactoryNames();
   1.342 +
   1.343 +    FlattenableHeap             fFlattenableHeap;
   1.344 +    FlatDictionary              fFlatDictionary;
   1.345 +    SkAutoTUnref<BitmapShuttle> fBitmapShuttle;
   1.346 +    int                         fCurrFlatIndex[kCount_PaintFlats];
   1.347 +
   1.348 +    int flattenToIndex(SkFlattenable* obj, PaintFlats);
   1.349 +
   1.350 +    // Common code used by drawBitmap*. Behaves differently depending on the
   1.351 +    // type of SkBitmapHeap being used, which is determined by the flags used.
   1.352 +    bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags,
   1.353 +                          size_t opBytesNeeded, const SkPaint* paint);
   1.354 +
   1.355 +    SkPaint fPaint;
   1.356 +    void writePaint(const SkPaint&);
   1.357 +
   1.358 +    class AutoPipeNotify {
   1.359 +    public:
   1.360 +        AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
   1.361 +        ~AutoPipeNotify() { fCanvas->doNotify(); }
   1.362 +    private:
   1.363 +        SkGPipeCanvas* fCanvas;
   1.364 +    };
   1.365 +    friend class AutoPipeNotify;
   1.366 +
   1.367 +    typedef SkCanvas INHERITED;
   1.368 +};
   1.369 +
   1.370 +void SkGPipeCanvas::flattenFactoryNames() {
   1.371 +    const char* name;
   1.372 +    while ((name = fFactorySet->getNextAddedFactoryName()) != NULL) {
   1.373 +        size_t len = strlen(name);
   1.374 +        if (this->needOpBytes(len)) {
   1.375 +            this->writeOp(kDef_Factory_DrawOp);
   1.376 +            fWriter.writeString(name, len);
   1.377 +        }
   1.378 +    }
   1.379 +}
   1.380 +
   1.381 +bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) {
   1.382 +    SkASSERT(shouldFlattenBitmaps(fFlags));
   1.383 +    SkWriteBuffer buffer;
   1.384 +    buffer.setNamedFactoryRecorder(fFactorySet);
   1.385 +    buffer.writeBitmap(bm);
   1.386 +    this->flattenFactoryNames();
   1.387 +    uint32_t size = buffer.bytesWritten();
   1.388 +    if (this->needOpBytes(size)) {
   1.389 +        this->writeOp(kDef_Bitmap_DrawOp, 0, slot);
   1.390 +        void* dst = static_cast<void*>(fWriter.reserve(size));
   1.391 +        buffer.writeToMemory(dst);
   1.392 +        return true;
   1.393 +    }
   1.394 +    return false;
   1.395 +}
   1.396 +
   1.397 +// return 0 for NULL (or unflattenable obj), or index-base-1
   1.398 +// return ~(index-base-1) if an old flattenable was replaced
   1.399 +int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
   1.400 +    SkASSERT(!fDone && fBitmapHeap != NULL);
   1.401 +    if (NULL == obj) {
   1.402 +        return 0;
   1.403 +    }
   1.404 +
   1.405 +    fBitmapHeap->deferAddingOwners();
   1.406 +    bool added, replaced;
   1.407 +    const SkFlatData* flat = fFlatDictionary.findAndReplace(*obj, fFlattenableHeap.flatToReplace(),
   1.408 +                                                            &added, &replaced);
   1.409 +    fBitmapHeap->endAddingOwnersDeferral(added);
   1.410 +    int index = flat->index();
   1.411 +    if (added) {
   1.412 +        if (isCrossProcess(fFlags)) {
   1.413 +            this->flattenFactoryNames();
   1.414 +        }
   1.415 +        size_t flatSize = flat->flatSize();
   1.416 +        if (this->needOpBytes(flatSize)) {
   1.417 +            this->writeOp(kDef_Flattenable_DrawOp, paintflat, index);
   1.418 +            fWriter.write(flat->data(), flatSize);
   1.419 +        }
   1.420 +    }
   1.421 +    if (replaced) {
   1.422 +        index = ~index;
   1.423 +    }
   1.424 +    return index;
   1.425 +}
   1.426 +
   1.427 +///////////////////////////////////////////////////////////////////////////////
   1.428 +
   1.429 +#define MIN_BLOCK_SIZE  (16 * 1024)
   1.430 +#define BITMAPS_TO_KEEP 5
   1.431 +#define FLATTENABLES_TO_KEEP 10
   1.432 +
   1.433 +SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
   1.434 +                             SkWriter32* writer, uint32_t flags,
   1.435 +                             uint32_t width, uint32_t height)
   1.436 +    : SkCanvas(width, height)
   1.437 +    , fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL)
   1.438 +    , fWriter(*writer)
   1.439 +    , fFlags(flags)
   1.440 +    , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, isCrossProcess(flags))
   1.441 +    , fFlatDictionary(&fFlattenableHeap)
   1.442 +{
   1.443 +    fController = controller;
   1.444 +    fDone = false;
   1.445 +    fBlockSize = 0; // need first block from controller
   1.446 +    fBytesNotified = 0;
   1.447 +    fFirstSaveLayerStackLevel = kNoSaveLayer;
   1.448 +    sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
   1.449 +
   1.450 +    // Tell the reader the appropriate flags to use.
   1.451 +    if (this->needOpBytes()) {
   1.452 +        this->writeOp(kReportFlags_DrawOp, fFlags, 0);
   1.453 +    }
   1.454 +
   1.455 +    if (shouldFlattenBitmaps(flags)) {
   1.456 +        fBitmapShuttle.reset(SkNEW_ARGS(BitmapShuttle, (this)));
   1.457 +        fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, (fBitmapShuttle.get(), BITMAPS_TO_KEEP));
   1.458 +    } else {
   1.459 +        fBitmapHeap = SkNEW_ARGS(SkBitmapHeap,
   1.460 +                                 (BITMAPS_TO_KEEP, controller->numberOfReaders()));
   1.461 +        if (this->needOpBytes(sizeof(void*))) {
   1.462 +            this->writeOp(kShareBitmapHeap_DrawOp);
   1.463 +            fWriter.writePtr(static_cast<void*>(fBitmapHeap));
   1.464 +        }
   1.465 +    }
   1.466 +    fFlattenableHeap.setBitmapStorage(fBitmapHeap);
   1.467 +    this->doNotify();
   1.468 +}
   1.469 +
   1.470 +SkGPipeCanvas::~SkGPipeCanvas() {
   1.471 +    this->finish(true);
   1.472 +    SkSafeUnref(fFactorySet);
   1.473 +    SkSafeUnref(fBitmapHeap);
   1.474 +}
   1.475 +
   1.476 +bool SkGPipeCanvas::needOpBytes(size_t needed) {
   1.477 +    if (fDone) {
   1.478 +        return false;
   1.479 +    }
   1.480 +
   1.481 +    needed += 4;  // size of DrawOp atom
   1.482 +    if (fWriter.bytesWritten() + needed > fBlockSize) {
   1.483 +        // Before we wipe out any data that has already been written, read it
   1.484 +        // out.
   1.485 +        this->doNotify();
   1.486 +        size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed);
   1.487 +        void* block = fController->requestBlock(blockSize, &fBlockSize);
   1.488 +        if (NULL == block) {
   1.489 +            // Do not notify the readers, which would call this function again.
   1.490 +            this->finish(false);
   1.491 +            return false;
   1.492 +        }
   1.493 +        SkASSERT(SkIsAlign4(fBlockSize));
   1.494 +        fWriter.reset(block, fBlockSize);
   1.495 +        fBytesNotified = 0;
   1.496 +    }
   1.497 +    return true;
   1.498 +}
   1.499 +
   1.500 +uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
   1.501 +    uint32_t id = 0; // 0 means default/null typeface
   1.502 +    if (face) {
   1.503 +        id = fTypefaceSet.find(face);
   1.504 +        if (0 == id) {
   1.505 +            id = fTypefaceSet.add(face);
   1.506 +            size_t size = writeTypeface(NULL, face);
   1.507 +            if (this->needOpBytes(size)) {
   1.508 +                this->writeOp(kDef_Typeface_DrawOp);
   1.509 +                writeTypeface(&fWriter, face);
   1.510 +            }
   1.511 +        }
   1.512 +    }
   1.513 +    return id;
   1.514 +}
   1.515 +
   1.516 +///////////////////////////////////////////////////////////////////////////////
   1.517 +
   1.518 +#define NOTIFY_SETUP(canvas)    \
   1.519 +    AutoPipeNotify apn(canvas)
   1.520 +
   1.521 +void SkGPipeCanvas::willSave(SaveFlags flags) {
   1.522 +    NOTIFY_SETUP(this);
   1.523 +    if (this->needOpBytes()) {
   1.524 +        this->writeOp(kSave_DrawOp, 0, flags);
   1.525 +    }
   1.526 +
   1.527 +    this->INHERITED::willSave(flags);
   1.528 +}
   1.529 +
   1.530 +SkCanvas::SaveLayerStrategy SkGPipeCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
   1.531 +                                                         SaveFlags saveFlags) {
   1.532 +    NOTIFY_SETUP(this);
   1.533 +    size_t size = 0;
   1.534 +    unsigned opFlags = 0;
   1.535 +
   1.536 +    if (bounds) {
   1.537 +        opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
   1.538 +        size += sizeof(SkRect);
   1.539 +    }
   1.540 +    if (paint) {
   1.541 +        opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
   1.542 +        this->writePaint(*paint);
   1.543 +    }
   1.544 +
   1.545 +    if (this->needOpBytes(size)) {
   1.546 +        this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
   1.547 +        if (bounds) {
   1.548 +            fWriter.writeRect(*bounds);
   1.549 +        }
   1.550 +    }
   1.551 +
   1.552 +    if (kNoSaveLayer == fFirstSaveLayerStackLevel){
   1.553 +        fFirstSaveLayerStackLevel = this->getSaveCount();
   1.554 +    }
   1.555 +
   1.556 +    this->INHERITED::willSaveLayer(bounds, paint, saveFlags);
   1.557 +    // we don't create a layer
   1.558 +    return kNoLayer_SaveLayerStrategy;
   1.559 +}
   1.560 +
   1.561 +void SkGPipeCanvas::willRestore() {
   1.562 +    NOTIFY_SETUP(this);
   1.563 +    if (this->needOpBytes()) {
   1.564 +        this->writeOp(kRestore_DrawOp);
   1.565 +    }
   1.566 +
   1.567 +    if (this->getSaveCount() - 1 == fFirstSaveLayerStackLevel){
   1.568 +        fFirstSaveLayerStackLevel = kNoSaveLayer;
   1.569 +    }
   1.570 +
   1.571 +    this->INHERITED::willRestore();
   1.572 +}
   1.573 +
   1.574 +bool SkGPipeCanvas::isDrawingToLayer() const {
   1.575 +    return kNoSaveLayer != fFirstSaveLayerStackLevel;
   1.576 +}
   1.577 +
   1.578 +void SkGPipeCanvas::didTranslate(SkScalar dx, SkScalar dy) {
   1.579 +    if (dx || dy) {
   1.580 +        NOTIFY_SETUP(this);
   1.581 +        if (this->needOpBytes(2 * sizeof(SkScalar))) {
   1.582 +            this->writeOp(kTranslate_DrawOp);
   1.583 +            fWriter.writeScalar(dx);
   1.584 +            fWriter.writeScalar(dy);
   1.585 +        }
   1.586 +    }
   1.587 +    this->INHERITED::didTranslate(dx, dy);
   1.588 +}
   1.589 +
   1.590 +void SkGPipeCanvas::didScale(SkScalar sx, SkScalar sy) {
   1.591 +    if (sx || sy) {
   1.592 +        NOTIFY_SETUP(this);
   1.593 +        if (this->needOpBytes(2 * sizeof(SkScalar))) {
   1.594 +            this->writeOp(kScale_DrawOp);
   1.595 +            fWriter.writeScalar(sx);
   1.596 +            fWriter.writeScalar(sy);
   1.597 +        }
   1.598 +    }
   1.599 +    this->INHERITED::didScale(sx, sy);
   1.600 +}
   1.601 +
   1.602 +void SkGPipeCanvas::didRotate(SkScalar degrees) {
   1.603 +    if (degrees) {
   1.604 +        NOTIFY_SETUP(this);
   1.605 +        if (this->needOpBytes(sizeof(SkScalar))) {
   1.606 +            this->writeOp(kRotate_DrawOp);
   1.607 +            fWriter.writeScalar(degrees);
   1.608 +        }
   1.609 +    }
   1.610 +    this->INHERITED::didRotate(degrees);
   1.611 +}
   1.612 +
   1.613 +void SkGPipeCanvas::didSkew(SkScalar sx, SkScalar sy) {
   1.614 +    if (sx || sy) {
   1.615 +        NOTIFY_SETUP(this);
   1.616 +        if (this->needOpBytes(2 * sizeof(SkScalar))) {
   1.617 +            this->writeOp(kSkew_DrawOp);
   1.618 +            fWriter.writeScalar(sx);
   1.619 +            fWriter.writeScalar(sy);
   1.620 +        }
   1.621 +    }
   1.622 +    this->INHERITED::didSkew(sx, sy);
   1.623 +}
   1.624 +
   1.625 +void SkGPipeCanvas::didConcat(const SkMatrix& matrix) {
   1.626 +    if (!matrix.isIdentity()) {
   1.627 +        NOTIFY_SETUP(this);
   1.628 +        if (this->needOpBytes(matrix.writeToMemory(NULL))) {
   1.629 +            this->writeOp(kConcat_DrawOp);
   1.630 +            fWriter.writeMatrix(matrix);
   1.631 +        }
   1.632 +    }
   1.633 +    this->INHERITED::didConcat(matrix);
   1.634 +}
   1.635 +
   1.636 +void SkGPipeCanvas::didSetMatrix(const SkMatrix& matrix) {
   1.637 +    NOTIFY_SETUP(this);
   1.638 +    if (this->needOpBytes(matrix.writeToMemory(NULL))) {
   1.639 +        this->writeOp(kSetMatrix_DrawOp);
   1.640 +        fWriter.writeMatrix(matrix);
   1.641 +    }
   1.642 +    this->INHERITED::didSetMatrix(matrix);
   1.643 +}
   1.644 +
   1.645 +void SkGPipeCanvas::onClipRect(const SkRect& rect, SkRegion::Op rgnOp,
   1.646 +                               ClipEdgeStyle edgeStyle) {
   1.647 +    NOTIFY_SETUP(this);
   1.648 +    if (this->needOpBytes(sizeof(SkRect))) {
   1.649 +        unsigned flags = 0;
   1.650 +        if (kSoft_ClipEdgeStyle == edgeStyle) {
   1.651 +            flags = kClip_HasAntiAlias_DrawOpFlag;
   1.652 +        }
   1.653 +        this->writeOp(kClipRect_DrawOp, flags, rgnOp);
   1.654 +        fWriter.writeRect(rect);
   1.655 +    }
   1.656 +    this->INHERITED::onClipRect(rect, rgnOp, edgeStyle);
   1.657 +}
   1.658 +
   1.659 +void SkGPipeCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op rgnOp,
   1.660 +                                ClipEdgeStyle edgeStyle) {
   1.661 +    NOTIFY_SETUP(this);
   1.662 +    if (this->needOpBytes(kSizeOfFlatRRect)) {
   1.663 +        unsigned flags = 0;
   1.664 +        if (kSoft_ClipEdgeStyle == edgeStyle) {
   1.665 +            flags = kClip_HasAntiAlias_DrawOpFlag;
   1.666 +        }
   1.667 +        this->writeOp(kClipRRect_DrawOp, flags, rgnOp);
   1.668 +        fWriter.writeRRect(rrect);
   1.669 +    }
   1.670 +    this->INHERITED::onClipRRect(rrect, rgnOp, edgeStyle);
   1.671 +}
   1.672 +
   1.673 +void SkGPipeCanvas::onClipPath(const SkPath& path, SkRegion::Op rgnOp,
   1.674 +                               ClipEdgeStyle edgeStyle) {
   1.675 +    NOTIFY_SETUP(this);
   1.676 +    if (this->needOpBytes(path.writeToMemory(NULL))) {
   1.677 +        unsigned flags = 0;
   1.678 +        if (kSoft_ClipEdgeStyle == edgeStyle) {
   1.679 +            flags = kClip_HasAntiAlias_DrawOpFlag;
   1.680 +        }
   1.681 +        this->writeOp(kClipPath_DrawOp, flags, rgnOp);
   1.682 +        fWriter.writePath(path);
   1.683 +    }
   1.684 +    // we just pass on the bounds of the path
   1.685 +    this->INHERITED::onClipRect(path.getBounds(), rgnOp, edgeStyle);
   1.686 +}
   1.687 +
   1.688 +void SkGPipeCanvas::onClipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
   1.689 +    NOTIFY_SETUP(this);
   1.690 +    if (this->needOpBytes(region.writeToMemory(NULL))) {
   1.691 +        this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
   1.692 +        fWriter.writeRegion(region);
   1.693 +    }
   1.694 +    this->INHERITED::onClipRegion(region, rgnOp);
   1.695 +}
   1.696 +
   1.697 +///////////////////////////////////////////////////////////////////////////////
   1.698 +
   1.699 +void SkGPipeCanvas::clear(SkColor color) {
   1.700 +    NOTIFY_SETUP(this);
   1.701 +    unsigned flags = 0;
   1.702 +    if (color) {
   1.703 +        flags |= kClear_HasColor_DrawOpFlag;
   1.704 +    }
   1.705 +    if (this->needOpBytes(sizeof(SkColor))) {
   1.706 +        this->writeOp(kDrawClear_DrawOp, flags, 0);
   1.707 +        if (color) {
   1.708 +            fWriter.write32(color);
   1.709 +        }
   1.710 +    }
   1.711 +}
   1.712 +
   1.713 +void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
   1.714 +    NOTIFY_SETUP(this);
   1.715 +    this->writePaint(paint);
   1.716 +    if (this->needOpBytes()) {
   1.717 +        this->writeOp(kDrawPaint_DrawOp);
   1.718 +    }
   1.719 +}
   1.720 +
   1.721 +void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
   1.722 +                               const SkPoint pts[], const SkPaint& paint) {
   1.723 +    if (count) {
   1.724 +        NOTIFY_SETUP(this);
   1.725 +        this->writePaint(paint);
   1.726 +        if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
   1.727 +            this->writeOp(kDrawPoints_DrawOp, mode, 0);
   1.728 +            fWriter.write32(count);
   1.729 +            fWriter.write(pts, count * sizeof(SkPoint));
   1.730 +        }
   1.731 +    }
   1.732 +}
   1.733 +
   1.734 +void SkGPipeCanvas::drawOval(const SkRect& rect, const SkPaint& paint) {
   1.735 +    NOTIFY_SETUP(this);
   1.736 +    this->writePaint(paint);
   1.737 +    if (this->needOpBytes(sizeof(SkRect))) {
   1.738 +        this->writeOp(kDrawOval_DrawOp);
   1.739 +        fWriter.writeRect(rect);
   1.740 +    }
   1.741 +}
   1.742 +
   1.743 +void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
   1.744 +    NOTIFY_SETUP(this);
   1.745 +    this->writePaint(paint);
   1.746 +    if (this->needOpBytes(sizeof(SkRect))) {
   1.747 +        this->writeOp(kDrawRect_DrawOp);
   1.748 +        fWriter.writeRect(rect);
   1.749 +    }
   1.750 +}
   1.751 +
   1.752 +void SkGPipeCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
   1.753 +    NOTIFY_SETUP(this);
   1.754 +    this->writePaint(paint);
   1.755 +    if (this->needOpBytes(kSizeOfFlatRRect)) {
   1.756 +        this->writeOp(kDrawRRect_DrawOp);
   1.757 +        fWriter.writeRRect(rrect);
   1.758 +    }
   1.759 +}
   1.760 +
   1.761 +void SkGPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
   1.762 +                                 const SkPaint& paint) {
   1.763 +    NOTIFY_SETUP(this);
   1.764 +    this->writePaint(paint);
   1.765 +    if (this->needOpBytes(kSizeOfFlatRRect * 2)) {
   1.766 +        this->writeOp(kDrawDRRect_DrawOp);
   1.767 +        fWriter.writeRRect(outer);
   1.768 +        fWriter.writeRRect(inner);
   1.769 +    }
   1.770 +}
   1.771 +
   1.772 +void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
   1.773 +    NOTIFY_SETUP(this);
   1.774 +    this->writePaint(paint);
   1.775 +    if (this->needOpBytes(path.writeToMemory(NULL))) {
   1.776 +        this->writeOp(kDrawPath_DrawOp);
   1.777 +        fWriter.writePath(path);
   1.778 +    }
   1.779 +}
   1.780 +
   1.781 +bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op,
   1.782 +                                     unsigned flags,
   1.783 +                                     size_t opBytesNeeded,
   1.784 +                                     const SkPaint* paint) {
   1.785 +    if (paint != NULL) {
   1.786 +        flags |= kDrawBitmap_HasPaint_DrawOpFlag;
   1.787 +        this->writePaint(*paint);
   1.788 +    }
   1.789 +    if (this->needOpBytes(opBytesNeeded)) {
   1.790 +        SkASSERT(fBitmapHeap != NULL);
   1.791 +        int32_t bitmapIndex = fBitmapHeap->insert(bm);
   1.792 +        if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) {
   1.793 +            return false;
   1.794 +        }
   1.795 +        this->writeOp(op, flags, bitmapIndex);
   1.796 +        return true;
   1.797 +    }
   1.798 +    return false;
   1.799 +}
   1.800 +
   1.801 +void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
   1.802 +                               const SkPaint* paint) {
   1.803 +    NOTIFY_SETUP(this);
   1.804 +    size_t opBytesNeeded = sizeof(SkScalar) * 2;
   1.805 +
   1.806 +    if (this->commonDrawBitmap(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) {
   1.807 +        fWriter.writeScalar(left);
   1.808 +        fWriter.writeScalar(top);
   1.809 +    }
   1.810 +}
   1.811 +
   1.812 +void SkGPipeCanvas::drawBitmapRectToRect(const SkBitmap& bm, const SkRect* src,
   1.813 +                                         const SkRect& dst, const SkPaint* paint,
   1.814 +                                         DrawBitmapRectFlags dbmrFlags) {
   1.815 +    NOTIFY_SETUP(this);
   1.816 +    size_t opBytesNeeded = sizeof(SkRect);
   1.817 +    bool hasSrc = src != NULL;
   1.818 +    unsigned flags;
   1.819 +    if (hasSrc) {
   1.820 +        flags = kDrawBitmap_HasSrcRect_DrawOpFlag;
   1.821 +        opBytesNeeded += sizeof(int32_t) * 4;
   1.822 +    } else {
   1.823 +        flags = 0;
   1.824 +    }
   1.825 +    if (dbmrFlags & kBleed_DrawBitmapRectFlag) {
   1.826 +        flags |= kDrawBitmap_Bleed_DrawOpFlag;
   1.827 +    }
   1.828 +
   1.829 +    if (this->commonDrawBitmap(bm, kDrawBitmapRectToRect_DrawOp, flags, opBytesNeeded, paint)) {
   1.830 +        if (hasSrc) {
   1.831 +            fWriter.writeRect(*src);
   1.832 +        }
   1.833 +        fWriter.writeRect(dst);
   1.834 +    }
   1.835 +}
   1.836 +
   1.837 +void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap& bm, const SkMatrix& matrix,
   1.838 +                                     const SkPaint* paint) {
   1.839 +    NOTIFY_SETUP(this);
   1.840 +    size_t opBytesNeeded = matrix.writeToMemory(NULL);
   1.841 +
   1.842 +    if (this->commonDrawBitmap(bm, kDrawBitmapMatrix_DrawOp, 0, opBytesNeeded, paint)) {
   1.843 +        fWriter.writeMatrix(matrix);
   1.844 +    }
   1.845 +}
   1.846 +
   1.847 +void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
   1.848 +                                   const SkRect& dst, const SkPaint* paint) {
   1.849 +    NOTIFY_SETUP(this);
   1.850 +    size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(SkRect);
   1.851 +
   1.852 +    if (this->commonDrawBitmap(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, paint)) {
   1.853 +        fWriter.write32(center.fLeft);
   1.854 +        fWriter.write32(center.fTop);
   1.855 +        fWriter.write32(center.fRight);
   1.856 +        fWriter.write32(center.fBottom);
   1.857 +        fWriter.writeRect(dst);
   1.858 +    }
   1.859 +}
   1.860 +
   1.861 +void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
   1.862 +                                   const SkPaint* paint) {
   1.863 +    NOTIFY_SETUP(this);
   1.864 +    size_t opBytesNeeded = sizeof(int32_t) * 2;
   1.865 +
   1.866 +    if (this->commonDrawBitmap(bm, kDrawSprite_DrawOp, 0, opBytesNeeded, paint)) {
   1.867 +        fWriter.write32(left);
   1.868 +        fWriter.write32(top);
   1.869 +    }
   1.870 +}
   1.871 +
   1.872 +void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
   1.873 +                                 SkScalar y, const SkPaint& paint) {
   1.874 +    if (byteLength) {
   1.875 +        NOTIFY_SETUP(this);
   1.876 +        this->writePaint(paint);
   1.877 +        if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
   1.878 +            this->writeOp(kDrawText_DrawOp);
   1.879 +            fWriter.write32(byteLength);
   1.880 +            fWriter.writePad(text, byteLength);
   1.881 +            fWriter.writeScalar(x);
   1.882 +            fWriter.writeScalar(y);
   1.883 +        }
   1.884 +    }
   1.885 +}
   1.886 +
   1.887 +void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
   1.888 +                                const SkPoint pos[], const SkPaint& paint) {
   1.889 +    if (byteLength) {
   1.890 +        NOTIFY_SETUP(this);
   1.891 +        this->writePaint(paint);
   1.892 +        int count = paint.textToGlyphs(text, byteLength, NULL);
   1.893 +        if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
   1.894 +            this->writeOp(kDrawPosText_DrawOp);
   1.895 +            fWriter.write32(byteLength);
   1.896 +            fWriter.writePad(text, byteLength);
   1.897 +            fWriter.write32(count);
   1.898 +            fWriter.write(pos, count * sizeof(SkPoint));
   1.899 +        }
   1.900 +    }
   1.901 +}
   1.902 +
   1.903 +void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
   1.904 +                                 const SkScalar xpos[], SkScalar constY,
   1.905 +                                 const SkPaint& paint) {
   1.906 +    if (byteLength) {
   1.907 +        NOTIFY_SETUP(this);
   1.908 +        this->writePaint(paint);
   1.909 +        int count = paint.textToGlyphs(text, byteLength, NULL);
   1.910 +        if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
   1.911 +            this->writeOp(kDrawPosTextH_DrawOp);
   1.912 +            fWriter.write32(byteLength);
   1.913 +            fWriter.writePad(text, byteLength);
   1.914 +            fWriter.write32(count);
   1.915 +            fWriter.write(xpos, count * sizeof(SkScalar));
   1.916 +            fWriter.writeScalar(constY);
   1.917 +        }
   1.918 +    }
   1.919 +}
   1.920 +
   1.921 +void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
   1.922 +                                   const SkPath& path, const SkMatrix* matrix,
   1.923 +                                   const SkPaint& paint) {
   1.924 +    if (byteLength) {
   1.925 +        NOTIFY_SETUP(this);
   1.926 +        unsigned flags = 0;
   1.927 +        size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(NULL);
   1.928 +        if (matrix) {
   1.929 +            flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
   1.930 +            size += matrix->writeToMemory(NULL);
   1.931 +        }
   1.932 +        this->writePaint(paint);
   1.933 +        if (this->needOpBytes(size)) {
   1.934 +            this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
   1.935 +
   1.936 +            fWriter.write32(byteLength);
   1.937 +            fWriter.writePad(text, byteLength);
   1.938 +
   1.939 +            fWriter.writePath(path);
   1.940 +            if (matrix) {
   1.941 +                fWriter.writeMatrix(*matrix);
   1.942 +            }
   1.943 +        }
   1.944 +    }
   1.945 +}
   1.946 +
   1.947 +void SkGPipeCanvas::drawPicture(SkPicture& picture) {
   1.948 +    // we want to playback the picture into individual draw calls
   1.949 +    this->INHERITED::drawPicture(picture);
   1.950 +}
   1.951 +
   1.952 +void SkGPipeCanvas::drawVertices(VertexMode vmode, int vertexCount,
   1.953 +                                 const SkPoint vertices[], const SkPoint texs[],
   1.954 +                                 const SkColor colors[], SkXfermode* xfer,
   1.955 +                                 const uint16_t indices[], int indexCount,
   1.956 +                                 const SkPaint& paint) {
   1.957 +    if (0 == vertexCount) {
   1.958 +        return;
   1.959 +    }
   1.960 +
   1.961 +    NOTIFY_SETUP(this);
   1.962 +    size_t size = 4 + vertexCount * sizeof(SkPoint);
   1.963 +    this->writePaint(paint);
   1.964 +    unsigned flags = 0;
   1.965 +    if (texs) {
   1.966 +        flags |= kDrawVertices_HasTexs_DrawOpFlag;
   1.967 +        size += vertexCount * sizeof(SkPoint);
   1.968 +    }
   1.969 +    if (colors) {
   1.970 +        flags |= kDrawVertices_HasColors_DrawOpFlag;
   1.971 +        size += vertexCount * sizeof(SkColor);
   1.972 +    }
   1.973 +    if (indices && indexCount > 0) {
   1.974 +        flags |= kDrawVertices_HasIndices_DrawOpFlag;
   1.975 +        size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
   1.976 +    }
   1.977 +    if (xfer && !SkXfermode::IsMode(xfer, SkXfermode::kModulate_Mode)) {
   1.978 +        flags |= kDrawVertices_HasXfermode_DrawOpFlag;
   1.979 +        size += sizeof(int32_t);    // mode enum
   1.980 +    }
   1.981 +
   1.982 +    if (this->needOpBytes(size)) {
   1.983 +        this->writeOp(kDrawVertices_DrawOp, flags, 0);
   1.984 +        fWriter.write32(vmode);
   1.985 +        fWriter.write32(vertexCount);
   1.986 +        fWriter.write(vertices, vertexCount * sizeof(SkPoint));
   1.987 +        if (texs) {
   1.988 +            fWriter.write(texs, vertexCount * sizeof(SkPoint));
   1.989 +        }
   1.990 +        if (colors) {
   1.991 +            fWriter.write(colors, vertexCount * sizeof(SkColor));
   1.992 +        }
   1.993 +        if (flags & kDrawVertices_HasXfermode_DrawOpFlag) {
   1.994 +            SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
   1.995 +            (void)xfer->asMode(&mode);
   1.996 +            fWriter.write32(mode);
   1.997 +        }
   1.998 +        if (indices && indexCount > 0) {
   1.999 +            fWriter.write32(indexCount);
  1.1000 +            fWriter.writePad(indices, indexCount * sizeof(uint16_t));
  1.1001 +        }
  1.1002 +    }
  1.1003 +}
  1.1004 +
  1.1005 +void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
  1.1006 +    if (size && ptr) {
  1.1007 +        NOTIFY_SETUP(this);
  1.1008 +        unsigned data = 0;
  1.1009 +        if (size < (1 << DRAWOPS_DATA_BITS)) {
  1.1010 +            data = (unsigned)size;
  1.1011 +        }
  1.1012 +        if (this->needOpBytes(4 + SkAlign4(size))) {
  1.1013 +            this->writeOp(kDrawData_DrawOp, 0, data);
  1.1014 +            if (0 == data) {
  1.1015 +                fWriter.write32(size);
  1.1016 +            }
  1.1017 +            fWriter.writePad(ptr, size);
  1.1018 +        }
  1.1019 +    }
  1.1020 +}
  1.1021 +
  1.1022 +void SkGPipeCanvas::beginCommentGroup(const char* description) {
  1.1023 +    // ignore for now
  1.1024 +}
  1.1025 +
  1.1026 +void SkGPipeCanvas::addComment(const char* kywd, const char* value) {
  1.1027 +    // ignore for now
  1.1028 +}
  1.1029 +
  1.1030 +void SkGPipeCanvas::endCommentGroup() {
  1.1031 +    // ignore for now
  1.1032 +}
  1.1033 +
  1.1034 +void SkGPipeCanvas::flushRecording(bool detachCurrentBlock) {
  1.1035 +    doNotify();
  1.1036 +    if (detachCurrentBlock) {
  1.1037 +        // force a new block to be requested for the next recorded command
  1.1038 +        fBlockSize = 0;
  1.1039 +    }
  1.1040 +}
  1.1041 +
  1.1042 +size_t SkGPipeCanvas::freeMemoryIfPossible(size_t bytesToFree) {
  1.1043 +    return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->freeMemoryIfPossible(bytesToFree);
  1.1044 +}
  1.1045 +
  1.1046 +///////////////////////////////////////////////////////////////////////////////
  1.1047 +
  1.1048 +template <typename T> uint32_t castToU32(T value) {
  1.1049 +    union {
  1.1050 +        T           fSrc;
  1.1051 +        uint32_t    fDst;
  1.1052 +    } data;
  1.1053 +    data.fSrc = value;
  1.1054 +    return data.fDst;
  1.1055 +}
  1.1056 +
  1.1057 +void SkGPipeCanvas::writePaint(const SkPaint& paint) {
  1.1058 +    if (fDone) {
  1.1059 +        return;
  1.1060 +    }
  1.1061 +    SkPaint& base = fPaint;
  1.1062 +    uint32_t storage[32];
  1.1063 +    uint32_t* ptr = storage;
  1.1064 +
  1.1065 +    if (base.getFlags() != paint.getFlags()) {
  1.1066 +        *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
  1.1067 +        base.setFlags(paint.getFlags());
  1.1068 +    }
  1.1069 +    if (base.getColor() != paint.getColor()) {
  1.1070 +        *ptr++ = PaintOp_packOp(kColor_PaintOp);
  1.1071 +        *ptr++ = paint.getColor();
  1.1072 +        base.setColor(paint.getColor());
  1.1073 +    }
  1.1074 +    if (base.getStyle() != paint.getStyle()) {
  1.1075 +        *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
  1.1076 +        base.setStyle(paint.getStyle());
  1.1077 +    }
  1.1078 +    if (base.getStrokeJoin() != paint.getStrokeJoin()) {
  1.1079 +        *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
  1.1080 +        base.setStrokeJoin(paint.getStrokeJoin());
  1.1081 +    }
  1.1082 +    if (base.getStrokeCap() != paint.getStrokeCap()) {
  1.1083 +        *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
  1.1084 +        base.setStrokeCap(paint.getStrokeCap());
  1.1085 +    }
  1.1086 +    if (base.getStrokeWidth() != paint.getStrokeWidth()) {
  1.1087 +        *ptr++ = PaintOp_packOp(kWidth_PaintOp);
  1.1088 +        *ptr++ = castToU32(paint.getStrokeWidth());
  1.1089 +        base.setStrokeWidth(paint.getStrokeWidth());
  1.1090 +    }
  1.1091 +    if (base.getStrokeMiter() != paint.getStrokeMiter()) {
  1.1092 +        *ptr++ = PaintOp_packOp(kMiter_PaintOp);
  1.1093 +        *ptr++ = castToU32(paint.getStrokeMiter());
  1.1094 +        base.setStrokeMiter(paint.getStrokeMiter());
  1.1095 +    }
  1.1096 +    if (base.getTextEncoding() != paint.getTextEncoding()) {
  1.1097 +        *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
  1.1098 +        base.setTextEncoding(paint.getTextEncoding());
  1.1099 +    }
  1.1100 +    if (base.getHinting() != paint.getHinting()) {
  1.1101 +        *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
  1.1102 +        base.setHinting(paint.getHinting());
  1.1103 +    }
  1.1104 +    if (base.getTextAlign() != paint.getTextAlign()) {
  1.1105 +        *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
  1.1106 +        base.setTextAlign(paint.getTextAlign());
  1.1107 +    }
  1.1108 +    if (base.getTextSize() != paint.getTextSize()) {
  1.1109 +        *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
  1.1110 +        *ptr++ = castToU32(paint.getTextSize());
  1.1111 +        base.setTextSize(paint.getTextSize());
  1.1112 +    }
  1.1113 +    if (base.getTextScaleX() != paint.getTextScaleX()) {
  1.1114 +        *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
  1.1115 +        *ptr++ = castToU32(paint.getTextScaleX());
  1.1116 +        base.setTextScaleX(paint.getTextScaleX());
  1.1117 +    }
  1.1118 +    if (base.getTextSkewX() != paint.getTextSkewX()) {
  1.1119 +        *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
  1.1120 +        *ptr++ = castToU32(paint.getTextSkewX());
  1.1121 +        base.setTextSkewX(paint.getTextSkewX());
  1.1122 +    }
  1.1123 +
  1.1124 +    if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
  1.1125 +        if (isCrossProcess(fFlags)) {
  1.1126 +            uint32_t id = this->getTypefaceID(paint.getTypeface());
  1.1127 +            *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
  1.1128 +        } else if (this->needOpBytes(sizeof(void*))) {
  1.1129 +            // Add to the set for ref counting.
  1.1130 +            fTypefaceSet.add(paint.getTypeface());
  1.1131 +            // It is safe to write the typeface to the stream before the rest
  1.1132 +            // of the paint unless we ever send a kReset_PaintOp, which we
  1.1133 +            // currently never do.
  1.1134 +            this->writeOp(kSetTypeface_DrawOp);
  1.1135 +            fWriter.writePtr(paint.getTypeface());
  1.1136 +        }
  1.1137 +        base.setTypeface(paint.getTypeface());
  1.1138 +    }
  1.1139 +
  1.1140 +    // This is a new paint, so all old flats can be safely purged, if necessary.
  1.1141 +    fFlattenableHeap.markAllFlatsSafeToDelete();
  1.1142 +    for (int i = 0; i < kCount_PaintFlats; i++) {
  1.1143 +        int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i);
  1.1144 +        bool replaced = index < 0;
  1.1145 +        if (replaced) {
  1.1146 +            index = ~index;
  1.1147 +        }
  1.1148 +        // Store the index of any flat that needs to be kept. 0 means no flat.
  1.1149 +        if (index > 0) {
  1.1150 +            fFlattenableHeap.markFlatForKeeping(index);
  1.1151 +        }
  1.1152 +        SkASSERT(index >= 0 && index <= fFlatDictionary.count());
  1.1153 +        if (index != fCurrFlatIndex[i] || replaced) {
  1.1154 +            *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index);
  1.1155 +            fCurrFlatIndex[i] = index;
  1.1156 +        }
  1.1157 +    }
  1.1158 +
  1.1159 +    size_t size = (char*)ptr - (char*)storage;
  1.1160 +    if (size && this->needOpBytes(size)) {
  1.1161 +        this->writeOp(kPaintOp_DrawOp, 0, size);
  1.1162 +        fWriter.write(storage, size);
  1.1163 +        for (size_t i = 0; i < size/4; i++) {
  1.1164 +//            SkDebugf("[%d] %08X\n", i, storage[i]);
  1.1165 +        }
  1.1166 +    }
  1.1167 +
  1.1168 +    //
  1.1169 +    //  Do these after we've written kPaintOp_DrawOp
  1.1170 +
  1.1171 +    if (base.getAnnotation() != paint.getAnnotation()) {
  1.1172 +        if (NULL == paint.getAnnotation()) {
  1.1173 +            if (this->needOpBytes()) {
  1.1174 +                this->writeOp(kSetAnnotation_DrawOp, 0, 0);
  1.1175 +            }
  1.1176 +        } else {
  1.1177 +            SkWriteBuffer buffer;
  1.1178 +            paint.getAnnotation()->writeToBuffer(buffer);
  1.1179 +            const size_t size = buffer.bytesWritten();
  1.1180 +            if (this->needOpBytes(size)) {
  1.1181 +                this->writeOp(kSetAnnotation_DrawOp, 0, size);
  1.1182 +                buffer.writeToMemory(fWriter.reserve(size));
  1.1183 +            }
  1.1184 +        }
  1.1185 +        base.setAnnotation(paint.getAnnotation());
  1.1186 +    }
  1.1187 +}
  1.1188 +
  1.1189 +///////////////////////////////////////////////////////////////////////////////
  1.1190 +
  1.1191 +#include "SkGPipe.h"
  1.1192 +
  1.1193 +SkGPipeController::~SkGPipeController() {
  1.1194 +    SkSafeUnref(fCanvas);
  1.1195 +}
  1.1196 +
  1.1197 +void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) {
  1.1198 +    SkRefCnt_SafeAssign(fCanvas, canvas);
  1.1199 +}
  1.1200 +
  1.1201 +///////////////////////////////////////////////////////////////////////////////
  1.1202 +
  1.1203 +SkGPipeWriter::SkGPipeWriter()
  1.1204 +: fWriter(0) {
  1.1205 +    fCanvas = NULL;
  1.1206 +}
  1.1207 +
  1.1208 +SkGPipeWriter::~SkGPipeWriter() {
  1.1209 +    this->endRecording();
  1.1210 +}
  1.1211 +
  1.1212 +SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags,
  1.1213 +                                        uint32_t width, uint32_t height) {
  1.1214 +    if (NULL == fCanvas) {
  1.1215 +        fWriter.reset(NULL, 0);
  1.1216 +        fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags, width, height));
  1.1217 +    }
  1.1218 +    controller->setCanvas(fCanvas);
  1.1219 +    return fCanvas;
  1.1220 +}
  1.1221 +
  1.1222 +void SkGPipeWriter::endRecording() {
  1.1223 +    if (fCanvas) {
  1.1224 +        fCanvas->finish(true);
  1.1225 +        fCanvas->unref();
  1.1226 +        fCanvas = NULL;
  1.1227 +    }
  1.1228 +}
  1.1229 +
  1.1230 +void SkGPipeWriter::flushRecording(bool detachCurrentBlock) {
  1.1231 +    if (fCanvas) {
  1.1232 +        fCanvas->flushRecording(detachCurrentBlock);
  1.1233 +    }
  1.1234 +}
  1.1235 +
  1.1236 +size_t SkGPipeWriter::freeMemoryIfPossible(size_t bytesToFree) {
  1.1237 +    if (fCanvas) {
  1.1238 +        return fCanvas->freeMemoryIfPossible(bytesToFree);
  1.1239 +    }
  1.1240 +    return 0;
  1.1241 +}
  1.1242 +
  1.1243 +size_t SkGPipeWriter::storageAllocatedForRecording() const {
  1.1244 +    return NULL == fCanvas ? 0 : fCanvas->storageAllocatedForRecording();
  1.1245 +}
  1.1246 +
  1.1247 +///////////////////////////////////////////////////////////////////////////////
  1.1248 +
  1.1249 +BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) {
  1.1250 +    SkASSERT(canvas != NULL);
  1.1251 +    fCanvas = canvas;
  1.1252 +    fCanvas->ref();
  1.1253 +}
  1.1254 +
  1.1255 +BitmapShuttle::~BitmapShuttle() {
  1.1256 +    this->removeCanvas();
  1.1257 +}
  1.1258 +
  1.1259 +bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) {
  1.1260 +    SkASSERT(fCanvas != NULL);
  1.1261 +    return fCanvas->shuttleBitmap(bitmap, slot);
  1.1262 +}
  1.1263 +
  1.1264 +void BitmapShuttle::removeCanvas() {
  1.1265 +    if (NULL == fCanvas) {
  1.1266 +        return;
  1.1267 +    }
  1.1268 +    fCanvas->unref();
  1.1269 +    fCanvas = NULL;
  1.1270 +}

mercurial