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