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