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