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