blob: 13b1f843e6f7e48317008f8f95213cce2c3c7d9b [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.combb6992a2011-04-26 17:41:56 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
reed@google.combb6992a2011-04-26 17:41:56 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.combb6992a2011-04-26 17:41:56 +000011#include "SkCanvas.h"
reed@google.com8a85d0c2011-06-24 19:12:12 +000012#include "SkData.h"
reed@google.combb6793b2011-05-05 15:18:15 +000013#include "SkDevice.h"
reed@google.combb6992a2011-04-26 17:41:56 +000014#include "SkPaint.h"
reed@google.com75a09722012-05-10 12:56:16 +000015#include "SkPathEffect.h"
reed@google.comacd471f2011-05-03 21:26:46 +000016#include "SkGPipe.h"
reed@google.combb6992a2011-04-26 17:41:56 +000017#include "SkGPipePriv.h"
scroggo@google.com16d1d0b2012-05-02 19:09:40 +000018#include "SkImageFilter.h"
reed@google.comf5842f72011-05-04 18:30:04 +000019#include "SkStream.h"
reed@google.comb55d1182011-05-11 00:42:04 +000020#include "SkTSearch.h"
reed@google.comf5842f72011-05-04 18:30:04 +000021#include "SkTypeface.h"
reed@google.combb6992a2011-04-26 17:41:56 +000022#include "SkWriter32.h"
reed@google.comb55d1182011-05-11 00:42:04 +000023#include "SkColorFilter.h"
reed@google.com0faac1e2011-05-11 05:58:58 +000024#include "SkDrawLooper.h"
reed@google.comb55d1182011-05-11 00:42:04 +000025#include "SkMaskFilter.h"
26#include "SkRasterizer.h"
27#include "SkShader.h"
djsollen@google.com2b2ede32012-04-12 13:24:04 +000028#include "SkOrderedWriteBuffer.h"
reed@google.comb55d1182011-05-11 00:42:04 +000029
30static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
31 SkASSERT(paintFlat < kCount_PaintFlats);
32 switch (paintFlat) {
33 case kColorFilter_PaintFlat: return paint.getColorFilter();
reed@google.com0faac1e2011-05-11 05:58:58 +000034 case kDrawLooper_PaintFlat: return paint.getLooper();
reed@google.comb55d1182011-05-11 00:42:04 +000035 case kMaskFilter_PaintFlat: return paint.getMaskFilter();
36 case kPathEffect_PaintFlat: return paint.getPathEffect();
37 case kRasterizer_PaintFlat: return paint.getRasterizer();
38 case kShader_PaintFlat: return paint.getShader();
scroggo@google.com16d1d0b2012-05-02 19:09:40 +000039 case kImageFilter_PaintFlat: return paint.getImageFilter();
reed@google.comb55d1182011-05-11 00:42:04 +000040 case kXfermode_PaintFlat: return paint.getXfermode();
41 }
tomhudson@google.com0c00f212011-12-28 14:59:50 +000042 SkDEBUGFAIL("never gets here");
reed@google.comb55d1182011-05-11 00:42:04 +000043 return NULL;
44}
reed@google.combb6992a2011-04-26 17:41:56 +000045
reed@google.comf5842f72011-05-04 18:30:04 +000046static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
47 SkASSERT(typeface);
48 SkDynamicMemoryWStream stream;
49 typeface->serialize(&stream);
50 size_t size = stream.getOffset();
51 if (writer) {
52 writer->write32(size);
reed@google.com8a85d0c2011-06-24 19:12:12 +000053 SkAutoDataUnref data(stream.copyToData());
robertphillips@google.com59f46b82012-07-10 17:30:58 +000054 writer->writePad(data->data(), size);
reed@google.comf5842f72011-05-04 18:30:04 +000055 }
scroggo@google.com5af9b202012-06-04 17:17:36 +000056 return 4 + SkAlign4(size);
reed@google.comf5842f72011-05-04 18:30:04 +000057}
58
reed@google.combb6992a2011-04-26 17:41:56 +000059///////////////////////////////////////////////////////////////////////////////
60
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000061/*
62 * Shared heap for storing large things that can be shared, for a stream
63 * used by multiple readers.
64 * TODO: Make the allocations all come from cross process safe address space
65 * TODO: Store paths (others?)
scroggo@google.com284bf502012-07-17 16:10:34 +000066 * TODO: Generalize the LRU caching mechanism
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000067 */
68class Heap {
69public:
scroggo@google.com284bf502012-07-17 16:10:34 +000070 Heap(bool shallow, int numOfReaders)
71 : fBitmapCount(0)
72 , fMostRecentlyUsed(NULL)
73 , fLeastRecentlyUsed(NULL)
74 , fCanDoShallowCopies(shallow)
75 , fNumberOfReaders(numOfReaders) {}
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000076 ~Heap() {
scroggo@google.com284bf502012-07-17 16:10:34 +000077 BitmapInfo* iter = fMostRecentlyUsed;
78 while (iter != NULL) {
79 BitmapInfo* next = iter->fLessRecentlyUsed;
80 SkDELETE(iter);
81 fBitmapCount--;
82 iter = next;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000083 }
scroggo@google.com284bf502012-07-17 16:10:34 +000084 SkASSERT(0 == fBitmapCount);
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000085 }
86
87 /*
88 * Add a copy of a bitmap to the heap.
89 * @param bm The SkBitmap to be copied and placed in the heap.
scroggo@google.com284bf502012-07-17 16:10:34 +000090 * @return void* Pointer to the BitmapInfo stored in the heap, which
91 * contains a copy of the SkBitmap. If NULL,
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000092 * the bitmap could not be copied.
93 */
scroggo@google.com284bf502012-07-17 16:10:34 +000094 const void* addBitmap(const SkBitmap& orig) {
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +000095 const uint32_t genID = orig.getGenerationID();
96 SkPixelRef* sharedPixelRef = NULL;
scroggo@google.com284bf502012-07-17 16:10:34 +000097 // When looking to see if we've previously used this bitmap, start at
98 // the end, assuming that the caller is more likely to reuse a recent
99 // one.
100 BitmapInfo* iter = fMostRecentlyUsed;
101 while (iter != NULL) {
102 if (genID == iter->fGenID) {
103 SkBitmap* storedBitmap = iter->fBitmap;
scroggo@google.com6ea165d2012-07-03 14:52:08 +0000104 if (orig.pixelRefOffset() != storedBitmap->pixelRefOffset()
105 || orig.width() != storedBitmap->width()
106 || orig.height() != storedBitmap->height()) {
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +0000107 // In this case, the bitmaps share a pixelRef, but have
scroggo@google.com6ea165d2012-07-03 14:52:08 +0000108 // different offsets or sizes. Keep track of the other
109 // bitmap so that instead of making another copy of the
110 // pixelRef we can use the copy we already made.
111 sharedPixelRef = storedBitmap->pixelRef();
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +0000112 break;
113 }
scroggo@google.com284bf502012-07-17 16:10:34 +0000114 iter->addDraws(fNumberOfReaders);
115 this->setMostRecentlyUsed(iter);
116 return iter;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000117 }
scroggo@google.com284bf502012-07-17 16:10:34 +0000118 iter = iter->fLessRecentlyUsed;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000119 }
scroggo@google.com284bf502012-07-17 16:10:34 +0000120 SkAutoRef ar((SkRefCnt*)sharedPixelRef);
121 BitmapInfo* replace = this->bitmapToReplace(orig);
scroggo@google.com565254b2012-06-28 15:41:32 +0000122 SkBitmap* copy;
123 // If the bitmap is mutable, we still need to do a deep copy, since the
124 // caller may modify it afterwards. That said, if the bitmap is mutable,
125 // but has no pixelRef, the copy constructor actually does a deep copy.
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +0000126 if (fCanDoShallowCopies && (orig.isImmutable() || !orig.pixelRef())) {
scroggo@google.com284bf502012-07-17 16:10:34 +0000127 if (NULL == replace) {
128 copy = SkNEW_ARGS(SkBitmap, (orig));
129 } else {
130 *replace->fBitmap = orig;
131 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000132 } else {
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +0000133 if (sharedPixelRef != NULL) {
scroggo@google.com284bf502012-07-17 16:10:34 +0000134 if (NULL == replace) {
135 // Do a shallow copy of the bitmap to get the width, height, etc
136 copy = SkNEW_ARGS(SkBitmap, (orig));
137 // Replace the pixelRef with the copy that was already made, and
138 // use the appropriate offset.
139 copy->setPixelRef(sharedPixelRef, orig.pixelRefOffset());
140 } else {
141 *replace->fBitmap = orig;
142 replace->fBitmap->setPixelRef(sharedPixelRef, orig.pixelRefOffset());
143 }
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +0000144 } else {
scroggo@google.com284bf502012-07-17 16:10:34 +0000145 if (NULL == replace) {
146 copy = SkNEW(SkBitmap);
147 if (!orig.copyTo(copy, orig.getConfig())) {
148 delete copy;
149 return NULL;
150 }
151 } else {
152 if (!orig.copyTo(replace->fBitmap, orig.getConfig())) {
153 return NULL;
154 }
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +0000155 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000156 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000157 }
scroggo@google.com284bf502012-07-17 16:10:34 +0000158 BitmapInfo* info;
159 if (NULL == replace) {
160 info = SkNEW_ARGS(BitmapInfo, (copy, genID, fNumberOfReaders));
161 fBitmapCount++;
162 } else {
163 replace->fGenID = genID;
164 replace->addDraws(fNumberOfReaders);
165 info = replace;
166 }
167 this->setMostRecentlyUsed(info);
168 return info;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000169 }
170private:
scroggo@google.com284bf502012-07-17 16:10:34 +0000171 void setMostRecentlyUsed(BitmapInfo* info);
172 BitmapInfo* bitmapToReplace(const SkBitmap& bm) const;
173
174 int fBitmapCount;
175 BitmapInfo* fLeastRecentlyUsed;
176 BitmapInfo* fMostRecentlyUsed;
177 const bool fCanDoShallowCopies;
178 const int fNumberOfReaders;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000179};
180
scroggo@google.com284bf502012-07-17 16:10:34 +0000181// We just "used" info. Update our LRU accordingly
182void Heap::setMostRecentlyUsed(BitmapInfo* info) {
183 SkASSERT(info != NULL);
184 if (info == fMostRecentlyUsed) {
185 return;
186 }
187 // Remove info from its prior place, and make sure to cover the hole.
188 if (fLeastRecentlyUsed == info) {
189 SkASSERT(info->fMoreRecentlyUsed != NULL);
190 fLeastRecentlyUsed = info->fMoreRecentlyUsed;
191 }
192 if (info->fMoreRecentlyUsed != NULL) {
193 SkASSERT(fMostRecentlyUsed != info);
194 info->fMoreRecentlyUsed->fLessRecentlyUsed = info->fLessRecentlyUsed;
195 }
196 if (info->fLessRecentlyUsed != NULL) {
197 SkASSERT(fLeastRecentlyUsed != info);
198 info->fLessRecentlyUsed->fMoreRecentlyUsed = info->fMoreRecentlyUsed;
199 }
200 info->fMoreRecentlyUsed = NULL;
201 // Set up the head and tail pointers properly.
202 if (fMostRecentlyUsed != NULL) {
203 SkASSERT(NULL == fMostRecentlyUsed->fMoreRecentlyUsed);
204 fMostRecentlyUsed->fMoreRecentlyUsed = info;
205 info->fLessRecentlyUsed = fMostRecentlyUsed;
206 }
207 fMostRecentlyUsed = info;
208 if (NULL == fLeastRecentlyUsed) {
209 fLeastRecentlyUsed = info;
210 }
211}
212
213/**
214 * Given a new bitmap to be added to the cache, return an existing one that
215 * should be removed to make room, or NULL if there is already room.
216 */
217BitmapInfo* Heap::bitmapToReplace(const SkBitmap& bm) const {
218 // Arbitrarily set a limit of 5. We should test to find the best tradeoff
219 // between time and space. A lower limit means that we use less space, but
220 // it also means that we may have to insert the same bitmap into the heap
221 // multiple times (depending on the input), potentially taking more time.
222 // On the other hand, a lower limit also means searching through our stored
223 // bitmaps takes less time.
224 if (fBitmapCount > 5) {
225 BitmapInfo* iter = fLeastRecentlyUsed;
226 while (iter != NULL) {
227 if (iter->drawCount() > 0) {
228 // If the least recently used bitmap has not been drawn by some
229 // reader, then a more recently used one will not have been
230 // drawn yet either.
231 return NULL;
232 }
233 if (bm.pixelRef() != NULL
234 && bm.pixelRef() == iter->fBitmap->pixelRef()) {
235 // Do not replace a bitmap with a new one using the same
236 // pixel ref. Instead look for a different one that will
237 // potentially free up more space.
238 iter = iter->fMoreRecentlyUsed;
239 } else {
240 return iter;
241 }
242 }
243 }
244 return NULL;
245}
246
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000247///////////////////////////////////////////////////////////////////////////////
248
reed@google.combb6992a2011-04-26 17:41:56 +0000249class SkGPipeCanvas : public SkCanvas {
250public:
scroggo@google.com565254b2012-06-28 15:41:32 +0000251 SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*, uint32_t flags);
reed@google.combb6992a2011-04-26 17:41:56 +0000252 virtual ~SkGPipeCanvas();
253
254 void finish() {
255 if (!fDone) {
reed@google.comdbccc882011-07-08 18:53:39 +0000256 if (this->needOpBytes()) {
257 this->writeOp(kDone_DrawOp);
258 this->doNotify();
259 }
reed@google.combb6992a2011-04-26 17:41:56 +0000260 fDone = true;
261 }
262 }
263
264 // overrides from SkCanvas
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000265 virtual int save(SaveFlags) SK_OVERRIDE;
266 virtual int saveLayer(const SkRect* bounds, const SkPaint*,
267 SaveFlags) SK_OVERRIDE;
268 virtual void restore() SK_OVERRIDE;
269 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
270 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
271 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
272 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
273 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
274 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
275 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
276 bool doAntiAlias = false) SK_OVERRIDE;
277 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
278 bool doAntiAlias = false) SK_OVERRIDE;
279 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) SK_OVERRIDE;
280 virtual void clear(SkColor) SK_OVERRIDE;
281 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000282 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000283 const SkPaint&) SK_OVERRIDE;
284 virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE;
285 virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000286 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000287 const SkPaint*) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000288 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000289 const SkRect& dst, const SkPaint*) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000290 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000291 const SkPaint*) SK_OVERRIDE;
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000292 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
293 const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000294 virtual void drawSprite(const SkBitmap&, int left, int top,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000295 const SkPaint*) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000296 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000297 SkScalar y, const SkPaint&) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000298 virtual void drawPosText(const void* text, size_t byteLength,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000299 const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000300 virtual void drawPosTextH(const void* text, size_t byteLength,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000301 const SkScalar xpos[], SkScalar constY,
302 const SkPaint&) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000303 virtual void drawTextOnPath(const void* text, size_t byteLength,
304 const SkPath& path, const SkMatrix* matrix,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000305 const SkPaint&) SK_OVERRIDE;
306 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000307 virtual void drawVertices(VertexMode, int vertexCount,
308 const SkPoint vertices[], const SkPoint texs[],
309 const SkColor colors[], SkXfermode*,
310 const uint16_t indices[], int indexCount,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000311 const SkPaint&) SK_OVERRIDE;
312 virtual void drawData(const void*, size_t) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000313
314private:
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000315 Heap fHeap;
reed@google.comdde09562011-05-23 12:21:05 +0000316 SkFactorySet* fFactorySet; // optional, only used if cross-process
reed@google.comacd471f2011-05-03 21:26:46 +0000317 SkGPipeController* fController;
reed@google.combb6992a2011-04-26 17:41:56 +0000318 SkWriter32& fWriter;
reed@google.comacd471f2011-05-03 21:26:46 +0000319 size_t fBlockSize; // amount allocated for writer
320 size_t fBytesNotified;
reed@google.combb6992a2011-04-26 17:41:56 +0000321 bool fDone;
scroggo@google.com565254b2012-06-28 15:41:32 +0000322 uint32_t fFlags;
reed@google.combb6992a2011-04-26 17:41:56 +0000323
reed@google.comf5842f72011-05-04 18:30:04 +0000324 SkRefCntSet fTypefaceSet;
325
326 uint32_t getTypefaceID(SkTypeface*);
327
reed@google.comacd471f2011-05-03 21:26:46 +0000328 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
reed@google.combb6992a2011-04-26 17:41:56 +0000329 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
330 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000331
reed@google.comacd471f2011-05-03 21:26:46 +0000332 inline void writeOp(DrawOps op) {
reed@google.combb6992a2011-04-26 17:41:56 +0000333 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
334 }
reed@google.comacd471f2011-05-03 21:26:46 +0000335
336 bool needOpBytes(size_t size = 0);
337
338 inline void doNotify() {
339 if (!fDone) {
340 size_t bytes = fWriter.size() - fBytesNotified;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000341 if (bytes > 0) {
342 fController->notifyWritten(bytes);
343 fBytesNotified += bytes;
344 }
reed@google.comacd471f2011-05-03 21:26:46 +0000345 }
346 }
reed@google.comb55d1182011-05-11 00:42:04 +0000347
348 struct FlatData {
349 uint32_t fIndex; // always > 0
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +0000350 PaintFlats fPaintFlat; // deliberately before fSize so that Compare
351 // will ignore it.
reed@google.comb55d1182011-05-11 00:42:04 +0000352 uint32_t fSize;
353
354 void* data() { return (char*)this + sizeof(*this); }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000355
reed@google.comb55d1182011-05-11 00:42:04 +0000356 static int Compare(const FlatData* a, const FlatData* b) {
357 return memcmp(&a->fSize, &b->fSize, a->fSize + sizeof(a->fSize));
358 }
359 };
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000360
361 SkTDArray<FlatData*> fBitmapArray;
362 int flattenToIndex(const SkBitmap&);
363
reed@google.comb55d1182011-05-11 00:42:04 +0000364 SkTDArray<FlatData*> fFlatArray;
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +0000365 size_t fBytesOfFlatData;
reed@google.comb55d1182011-05-11 00:42:04 +0000366 int fCurrFlatIndex[kCount_PaintFlats];
367 int flattenToIndex(SkFlattenable* obj, PaintFlats);
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +0000368 int flattenableToReplace(const FlatData& newFlat);
reed@google.comb55d1182011-05-11 00:42:04 +0000369
reed@google.com31891582011-05-12 03:03:56 +0000370 SkPaint fPaint;
371 void writePaint(const SkPaint&);
reed@google.combb6992a2011-04-26 17:41:56 +0000372
reed@google.comacd471f2011-05-03 21:26:46 +0000373 class AutoPipeNotify {
374 public:
375 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
376 ~AutoPipeNotify() { fCanvas->doNotify(); }
377 private:
378 SkGPipeCanvas* fCanvas;
379 };
380 friend class AutoPipeNotify;
381
reed@google.combb6992a2011-04-26 17:41:56 +0000382 typedef SkCanvas INHERITED;
383};
384
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000385int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000386 SkASSERT(shouldFlattenBitmaps(fFlags));
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000387 SkOrderedWriteBuffer tmpWriter(1024);
scroggo@google.com565254b2012-06-28 15:41:32 +0000388 tmpWriter.setFlags((SkFlattenableWriteBuffer::Flags)
389 (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
390 | SkFlattenableWriteBuffer::kCrossProcess_Flag));
391 tmpWriter.setFactoryRecorder(fFactorySet);
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000392 bitmap.flatten(tmpWriter);
393
394 size_t len = tmpWriter.size();
395 size_t allocSize = len + sizeof(FlatData);
396
397 SkAutoSMalloc<1024> storage(allocSize);
398 FlatData* flat = (FlatData*)storage.get();
399 flat->fSize = len;
400 tmpWriter.flatten(flat->data());
401
402 int index = SkTSearch<FlatData>((const FlatData**)fBitmapArray.begin(),
403 fBitmapArray.count(), flat, sizeof(flat),
404 &FlatData::Compare);
405 if (index < 0) {
406 index = ~index;
407 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
408 memcpy(copy, flat, allocSize);
409 // For bitmaps, we can use zero based indices, since we will never ask
410 // for a NULL bitmap (unlike with paint flattenables).
411 copy->fIndex = fBitmapArray.count();
412 *fBitmapArray.insert(index) = copy;
scroggo@google.com565254b2012-06-28 15:41:32 +0000413 if (this->needOpBytes(len)) {
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000414 this->writeOp(kDef_Bitmap_DrawOp, 0, copy->fIndex);
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000415 fWriter.write(copy->data(), len);
416 }
417 }
418 return fBitmapArray[index]->fIndex;
419}
420
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +0000421// Return -1 if there is no need to replace a flattenable, or there was not an
422// appropriate one to replace. Otherwise return the index of a flattenable to
423// replace.
424int SkGPipeCanvas::flattenableToReplace(const FlatData& newFlat) {
425 // For now, set an arbitrary limit on the size of FlatData we have stored.
426 // Note that this is currently a soft limit. If we have reached the limit,
427 // we replace one, but do not ensure that we return to below the limit.
428 if (fBytesOfFlatData + fFlatArray.bytes() > 1024) {
429 for (int i = 0; i < fFlatArray.count(); i++) {
430 // Only replace the same paint flat. Since a paint can only have
431 // one of each type, replacing one of the same type means that
432 // we will not be purging a flat on the same paint.
433 if (newFlat.fPaintFlat == fFlatArray[i]->fPaintFlat) {
434 return i;
435 }
436 }
437 }
438 return -1;
439}
440
reed@google.comb55d1182011-05-11 00:42:04 +0000441// return 0 for NULL (or unflattenable obj), or index-base-1
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +0000442// return ~(index-base-1) if an old flattenable was replaced
reed@google.comb55d1182011-05-11 00:42:04 +0000443int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
444 if (NULL == obj) {
445 return 0;
446 }
reed@google.comb55d1182011-05-11 00:42:04 +0000447
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000448 SkOrderedWriteBuffer tmpWriter(1024);
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000449
scroggo@google.com565254b2012-06-28 15:41:32 +0000450 if (fFlags & SkGPipeWriter::kCrossProcess_Flag) {
451 tmpWriter.setFlags((SkFlattenableWriteBuffer::Flags)
452 (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
453 | SkFlattenableWriteBuffer::kCrossProcess_Flag));
454 tmpWriter.setFactoryRecorder(fFactorySet);
455 } else {
456 // Needed for bitmap shaders.
457 tmpWriter.setFlags(SkFlattenableWriteBuffer::kForceFlattenBitmapPixels_Flag);
458 }
reed@google.comdde09562011-05-23 12:21:05 +0000459
reed@google.comb55d1182011-05-11 00:42:04 +0000460 tmpWriter.writeFlattenable(obj);
461 size_t len = tmpWriter.size();
462 size_t allocSize = len + sizeof(FlatData);
463
464 SkAutoSMalloc<1024> storage(allocSize);
465 FlatData* flat = (FlatData*)storage.get();
466 flat->fSize = len;
467 tmpWriter.flatten(flat->data());
468
469 int index = SkTSearch<FlatData>((const FlatData**)fFlatArray.begin(),
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +0000470 fFlatArray.count(), flat, sizeof(FlatData*),
reed@google.comb55d1182011-05-11 00:42:04 +0000471 &FlatData::Compare);
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +0000472 bool replacedAFlat = false;
reed@google.comb55d1182011-05-11 00:42:04 +0000473 if (index < 0) {
474 index = ~index;
475 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
476 memcpy(copy, flat, allocSize);
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +0000477 copy->fPaintFlat = paintflat;
478 int indexToReplace = this->flattenableToReplace(*copy);
479 if (indexToReplace >= 0) {
480 replacedAFlat = true;
481 FlatData* oldData = fFlatArray[indexToReplace];
482 copy->fIndex = oldData->fIndex;
483 fBytesOfFlatData -= (sizeof(FlatData) + oldData->fSize);
484 sk_free(oldData);
485 fFlatArray.remove(indexToReplace);
486 if (indexToReplace < index) {
487 index--;
488 }
489 }
reed@google.comb55d1182011-05-11 00:42:04 +0000490 *fFlatArray.insert(index) = copy;
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +0000491 fBytesOfFlatData += allocSize;
492 if (!replacedAFlat) {
493 // Call this after the insert, so that count() will have been grown
494 // (unless we replaced one, in which case fIndex has already been
495 // set properly).
496 copy->fIndex = fFlatArray.count();
497// SkDebugf("--- add flattenable[%d] size=%d index=%d\n", paintflat, len, copy->fIndex);
498 }
reed@google.comb55d1182011-05-11 00:42:04 +0000499
500 if (this->needOpBytes(len)) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000501 this->writeOp(kDef_Flattenable_DrawOp, paintflat, copy->fIndex);
reed@google.comb55d1182011-05-11 00:42:04 +0000502 fWriter.write(copy->data(), len);
503 }
504 }
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +0000505 int retVal = fFlatArray[index]->fIndex;
506 if (replacedAFlat) {
507 retVal = ~retVal;
508 }
509 return retVal;
reed@google.comb55d1182011-05-11 00:42:04 +0000510}
511
reed@google.combb6992a2011-04-26 17:41:56 +0000512///////////////////////////////////////////////////////////////////////////////
513
reed@google.comacd471f2011-05-03 21:26:46 +0000514#define MIN_BLOCK_SIZE (16 * 1024)
reed@google.combb6992a2011-04-26 17:41:56 +0000515
reed@google.comacd471f2011-05-03 21:26:46 +0000516SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
scroggo@google.com565254b2012-06-28 15:41:32 +0000517 SkWriter32* writer, SkFactorySet* fset, uint32_t flags)
scroggo@google.com284bf502012-07-17 16:10:34 +0000518: fHeap(!(flags & SkGPipeWriter::kCrossProcess_Flag), controller->numberOfReaders())
519, fWriter(*writer), fFlags(flags), fBytesOfFlatData(0) {
reed@google.com67908f22011-06-27 14:47:50 +0000520 fFactorySet = fset;
reed@google.comacd471f2011-05-03 21:26:46 +0000521 fController = controller;
reed@google.combb6992a2011-04-26 17:41:56 +0000522 fDone = false;
reed@google.comacd471f2011-05-03 21:26:46 +0000523 fBlockSize = 0; // need first block from controller
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000524 fBytesNotified = 0;
reed@google.comb55d1182011-05-11 00:42:04 +0000525 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
reed@google.comacd471f2011-05-03 21:26:46 +0000526
reed@google.combb6793b2011-05-05 15:18:15 +0000527 // we need a device to limit our clip
528 // should the caller give us the bounds?
yangsu@google.com06b4da162011-06-17 15:04:40 +0000529 // We don't allocate pixels for the bitmap
reed@google.combb6793b2011-05-05 15:18:15 +0000530 SkBitmap bitmap;
531 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32767, 32767);
yangsu@google.com06b4da162011-06-17 15:04:40 +0000532 SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
reed@google.combb6793b2011-05-05 15:18:15 +0000533 this->setDevice(device)->unref();
scroggo@google.com565254b2012-06-28 15:41:32 +0000534 // Tell the reader the appropriate flags to use.
535 if (this->needOpBytes()) {
536 this->writeOp(kReportFlags_DrawOp, fFlags, 0);
537 }
reed@google.combb6992a2011-04-26 17:41:56 +0000538}
539
540SkGPipeCanvas::~SkGPipeCanvas() {
541 this->finish();
542
reed@google.comb55d1182011-05-11 00:42:04 +0000543 fFlatArray.freeAll();
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000544 fBitmapArray.freeAll();
reed@google.combb6992a2011-04-26 17:41:56 +0000545}
546
reed@google.comacd471f2011-05-03 21:26:46 +0000547bool SkGPipeCanvas::needOpBytes(size_t needed) {
548 if (fDone) {
549 return false;
550 }
551
552 needed += 4; // size of DrawOp atom
553 if (fWriter.size() + needed > fBlockSize) {
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000554 // Before we wipe out any data that has already been written, read it
555 // out.
556 this->doNotify();
557 size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed);
558 void* block = fController->requestBlock(blockSize, &fBlockSize);
reed@google.comacd471f2011-05-03 21:26:46 +0000559 if (NULL == block) {
560 fDone = true;
561 return false;
562 }
563 fWriter.reset(block, fBlockSize);
564 fBytesNotified = 0;
565 }
566 return true;
567}
568
reed@google.comf5842f72011-05-04 18:30:04 +0000569uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
570 uint32_t id = 0; // 0 means default/null typeface
571 if (face) {
572 id = fTypefaceSet.find(face);
573 if (0 == id) {
574 id = fTypefaceSet.add(face);
575 size_t size = writeTypeface(NULL, face);
576 if (this->needOpBytes(size)) {
reed@google.combb6793b2011-05-05 15:18:15 +0000577 this->writeOp(kDef_Typeface_DrawOp);
reed@google.comf5842f72011-05-04 18:30:04 +0000578 writeTypeface(&fWriter, face);
579 }
580 }
581 }
582 return id;
583}
584
reed@google.combb6992a2011-04-26 17:41:56 +0000585///////////////////////////////////////////////////////////////////////////////
586
reed@google.comacd471f2011-05-03 21:26:46 +0000587#define NOTIFY_SETUP(canvas) \
588 AutoPipeNotify apn(canvas)
589
reed@google.combb6992a2011-04-26 17:41:56 +0000590int SkGPipeCanvas::save(SaveFlags flags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000591 NOTIFY_SETUP(this);
592 if (this->needOpBytes()) {
593 this->writeOp(kSave_DrawOp, 0, flags);
594 }
reed@google.combb6992a2011-04-26 17:41:56 +0000595 return this->INHERITED::save(flags);
596}
597
598int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
599 SaveFlags saveFlags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000600 NOTIFY_SETUP(this);
601 size_t size = 0;
reed@google.combb6992a2011-04-26 17:41:56 +0000602 unsigned opFlags = 0;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000603
reed@google.combb6992a2011-04-26 17:41:56 +0000604 if (bounds) {
605 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000606 size += sizeof(SkRect);
reed@google.combb6992a2011-04-26 17:41:56 +0000607 }
608 if (paint) {
609 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
reed@google.com31891582011-05-12 03:03:56 +0000610 this->writePaint(*paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000611 }
612
reed@google.comacd471f2011-05-03 21:26:46 +0000613 if (this->needOpBytes(size)) {
614 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
615 if (bounds) {
616 fWriter.writeRect(*bounds);
617 }
reed@google.combb6992a2011-04-26 17:41:56 +0000618 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000619
reed@google.combb6992a2011-04-26 17:41:56 +0000620 // we just pass on the save, so we don't create a layer
621 return this->INHERITED::save(saveFlags);
622}
623
624void SkGPipeCanvas::restore() {
reed@google.comacd471f2011-05-03 21:26:46 +0000625 NOTIFY_SETUP(this);
626 if (this->needOpBytes()) {
627 this->writeOp(kRestore_DrawOp);
628 }
reed@google.combb6992a2011-04-26 17:41:56 +0000629 this->INHERITED::restore();
630}
631
632bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
633 if (dx || dy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000634 NOTIFY_SETUP(this);
635 if (this->needOpBytes(2 * sizeof(SkScalar))) {
636 this->writeOp(kTranslate_DrawOp);
637 fWriter.writeScalar(dx);
638 fWriter.writeScalar(dy);
639 }
reed@google.combb6992a2011-04-26 17:41:56 +0000640 }
641 return this->INHERITED::translate(dx, dy);
642}
643
644bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
645 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000646 NOTIFY_SETUP(this);
647 if (this->needOpBytes(2 * sizeof(SkScalar))) {
648 this->writeOp(kScale_DrawOp);
649 fWriter.writeScalar(sx);
650 fWriter.writeScalar(sy);
651 }
reed@google.combb6992a2011-04-26 17:41:56 +0000652 }
653 return this->INHERITED::scale(sx, sy);
654}
655
656bool SkGPipeCanvas::rotate(SkScalar degrees) {
657 if (degrees) {
reed@google.comacd471f2011-05-03 21:26:46 +0000658 NOTIFY_SETUP(this);
659 if (this->needOpBytes(sizeof(SkScalar))) {
660 this->writeOp(kRotate_DrawOp);
661 fWriter.writeScalar(degrees);
662 }
reed@google.combb6992a2011-04-26 17:41:56 +0000663 }
664 return this->INHERITED::rotate(degrees);
665}
666
667bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
668 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000669 NOTIFY_SETUP(this);
670 if (this->needOpBytes(2 * sizeof(SkScalar))) {
671 this->writeOp(kSkew_DrawOp);
672 fWriter.writeScalar(sx);
673 fWriter.writeScalar(sy);
674 }
reed@google.combb6992a2011-04-26 17:41:56 +0000675 }
676 return this->INHERITED::skew(sx, sy);
677}
678
679bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
680 if (!matrix.isIdentity()) {
reed@google.comacd471f2011-05-03 21:26:46 +0000681 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000682 if (this->needOpBytes(matrix.writeToMemory(NULL))) {
reed@google.comacd471f2011-05-03 21:26:46 +0000683 this->writeOp(kConcat_DrawOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000684 fWriter.writeMatrix(matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000685 }
reed@google.combb6992a2011-04-26 17:41:56 +0000686 }
687 return this->INHERITED::concat(matrix);
688}
689
690void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
reed@google.comacd471f2011-05-03 21:26:46 +0000691 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000692 if (this->needOpBytes(matrix.writeToMemory(NULL))) {
reed@google.comacd471f2011-05-03 21:26:46 +0000693 this->writeOp(kSetMatrix_DrawOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000694 fWriter.writeMatrix(matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000695 }
reed@google.combb6992a2011-04-26 17:41:56 +0000696 this->INHERITED::setMatrix(matrix);
697}
698
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000699bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp,
700 bool doAntiAlias) {
reed@google.comacd471f2011-05-03 21:26:46 +0000701 NOTIFY_SETUP(this);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000702 if (this->needOpBytes(sizeof(SkRect)) + sizeof(bool)) {
reed@google.comacd471f2011-05-03 21:26:46 +0000703 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
704 fWriter.writeRect(rect);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000705 fWriter.writeBool(doAntiAlias);
reed@google.comacd471f2011-05-03 21:26:46 +0000706 }
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000707 return this->INHERITED::clipRect(rect, rgnOp, doAntiAlias);
reed@google.combb6992a2011-04-26 17:41:56 +0000708}
709
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000710bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp,
711 bool doAntiAlias) {
reed@google.comacd471f2011-05-03 21:26:46 +0000712 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000713 if (this->needOpBytes(path.writeToMemory(NULL)) + sizeof(bool)) {
reed@google.comacd471f2011-05-03 21:26:46 +0000714 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000715 fWriter.writePath(path);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000716 fWriter.writeBool(doAntiAlias);
reed@google.comacd471f2011-05-03 21:26:46 +0000717 }
reed@google.combb6992a2011-04-26 17:41:56 +0000718 // we just pass on the bounds of the path
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000719 return this->INHERITED::clipRect(path.getBounds(), rgnOp, doAntiAlias);
reed@google.combb6992a2011-04-26 17:41:56 +0000720}
721
722bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000723 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000724 if (this->needOpBytes(region.writeToMemory(NULL))) {
reed@google.comacd471f2011-05-03 21:26:46 +0000725 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000726 fWriter.writeRegion(region);
reed@google.comacd471f2011-05-03 21:26:46 +0000727 }
reed@google.combb6992a2011-04-26 17:41:56 +0000728 return this->INHERITED::clipRegion(region, rgnOp);
729}
730
731///////////////////////////////////////////////////////////////////////////////
732
733void SkGPipeCanvas::clear(SkColor color) {
reed@google.comacd471f2011-05-03 21:26:46 +0000734 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000735 unsigned flags = 0;
736 if (color) {
737 flags |= kClear_HasColor_DrawOpFlag;
738 }
reed@google.comacd471f2011-05-03 21:26:46 +0000739 if (this->needOpBytes(sizeof(SkColor))) {
740 this->writeOp(kDrawClear_DrawOp, flags, 0);
741 if (color) {
742 fWriter.write32(color);
743 }
reed@google.combb6992a2011-04-26 17:41:56 +0000744 }
745}
746
747void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000748 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000749 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000750 if (this->needOpBytes()) {
reed@google.com31891582011-05-12 03:03:56 +0000751 this->writeOp(kDrawPaint_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000752 }
reed@google.combb6992a2011-04-26 17:41:56 +0000753}
754
755void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
756 const SkPoint pts[], const SkPaint& paint) {
757 if (count) {
reed@google.comacd471f2011-05-03 21:26:46 +0000758 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000759 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000760 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000761 this->writeOp(kDrawPoints_DrawOp, mode, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000762 fWriter.write32(count);
763 fWriter.write(pts, count * sizeof(SkPoint));
764 }
reed@google.combb6992a2011-04-26 17:41:56 +0000765 }
766}
767
768void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000769 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000770 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000771 if (this->needOpBytes(sizeof(SkRect))) {
reed@google.com31891582011-05-12 03:03:56 +0000772 this->writeOp(kDrawRect_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000773 fWriter.writeRect(rect);
774 }
reed@google.combb6992a2011-04-26 17:41:56 +0000775}
776
777void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000778 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000779 this->writePaint(paint);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000780 if (this->needOpBytes(path.writeToMemory(NULL))) {
reed@google.com31891582011-05-12 03:03:56 +0000781 this->writeOp(kDrawPath_DrawOp);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000782 fWriter.writePath(path);
reed@google.comacd471f2011-05-03 21:26:46 +0000783 }
reed@google.combb6992a2011-04-26 17:41:56 +0000784}
785
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000786void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
787 const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000788 bool flatten = shouldFlattenBitmaps(fFlags);
789 const void* ptr = 0;
790 int bitmapIndex = 0;
791 if (flatten) {
792 bitmapIndex = this->flattenToIndex(bm);
793 } else {
794 ptr = fHeap.addBitmap(bm);
795 if (NULL == ptr) {
796 return;
797 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000798 }
799
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000800 NOTIFY_SETUP(this);
801 if (paint) {
802 this->writePaint(*paint);
803 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000804
scroggo@google.com565254b2012-06-28 15:41:32 +0000805 size_t opBytesNeeded = sizeof(SkScalar) * 2 + sizeof(bool);
806 if (!flatten) {
807 opBytesNeeded += sizeof(void*);
808 }
809 if (this->needOpBytes(opBytesNeeded)) {
810 this->writeOp(kDrawBitmap_DrawOp, 0, bitmapIndex);
811 if (!flatten) {
812 fWriter.writePtr(const_cast<void*>(ptr));
813 }
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000814 fWriter.writeBool(paint != NULL);
815 fWriter.writeScalar(left);
816 fWriter.writeScalar(top);
817 }
reed@google.combb6992a2011-04-26 17:41:56 +0000818}
819
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000820void SkGPipeCanvas::drawBitmapRect(const SkBitmap& bm, const SkIRect* src,
821 const SkRect& dst, const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000822 bool flatten = shouldFlattenBitmaps(fFlags);
823 const void* ptr = 0;
824 int bitmapIndex = 0;
825 if (flatten) {
826 bitmapIndex = this->flattenToIndex(bm);
827 } else {
828 ptr = fHeap.addBitmap(bm);
829 if (NULL == ptr) {
830 return;
831 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000832 }
833
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000834 NOTIFY_SETUP(this);
835 if (paint) {
836 this->writePaint(*paint);
837 }
838
scroggo@google.com565254b2012-06-28 15:41:32 +0000839 size_t opBytesNeeded = sizeof(SkRect) + sizeof(bool) * 2;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000840 bool hasSrc = src != NULL;
841 if (hasSrc) {
842 opBytesNeeded += sizeof(int32_t) * 4;
843 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000844 if (!flatten) {
845 opBytesNeeded += sizeof(void*);
846 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000847 if (this->needOpBytes(opBytesNeeded)) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000848 this->writeOp(kDrawBitmapRect_DrawOp, 0, bitmapIndex);
849 if (!flatten) {
850 fWriter.writePtr(const_cast<void*>(ptr));
851 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000852 fWriter.writeBool(paint != NULL);
853 fWriter.writeBool(hasSrc);
854 if (hasSrc) {
855 fWriter.write32(src->fLeft);
856 fWriter.write32(src->fTop);
857 fWriter.write32(src->fRight);
858 fWriter.write32(src->fBottom);
859 }
860 fWriter.writeRect(dst);
861 }
reed@google.combb6992a2011-04-26 17:41:56 +0000862}
863
864void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
865 const SkPaint*) {
866 UNIMPLEMENTED
867}
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000868
869void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000870 const SkRect& dst, const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000871 bool flatten = shouldFlattenBitmaps(fFlags);
872 const void* ptr = 0;
873 int bitmapIndex = 0;
874 if (flatten) {
875 bitmapIndex = this->flattenToIndex(bm);
876 } else {
877 ptr = fHeap.addBitmap(bm);
878 if (NULL == ptr) {
879 return;
880 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000881 }
882
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000883 NOTIFY_SETUP(this);
884 if (paint) {
885 this->writePaint(*paint);
886 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000887
scroggo@google.com565254b2012-06-28 15:41:32 +0000888 size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(bool) + sizeof(SkRect);
889 if (!flatten) {
890 opBytesNeeded += sizeof(void*);
891 }
892 if (this->needOpBytes(opBytesNeeded)) {
893 this->writeOp(kDrawBitmapNine_DrawOp, 0, bitmapIndex);
894 if (!flatten) {
895 fWriter.writePtr(const_cast<void*>(ptr));
896 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000897 fWriter.writeBool(paint != NULL);
898 fWriter.write32(center.fLeft);
899 fWriter.write32(center.fTop);
900 fWriter.write32(center.fRight);
901 fWriter.write32(center.fBottom);
902 fWriter.writeRect(dst);
903 }
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000904}
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000905
906void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
907 const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000908 bool flatten = shouldFlattenBitmaps(fFlags);
909 const void* ptr = 0;
910 int bitmapIndex = 0;
911 if (flatten) {
912 bitmapIndex = this->flattenToIndex(bm);
913 } else {
914 ptr = fHeap.addBitmap(bm);
915 if (NULL == ptr) {
916 return;
917 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000918 }
919
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000920 NOTIFY_SETUP(this);
921 if (paint) {
922 this->writePaint(*paint);
923 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000924
scroggo@google.com565254b2012-06-28 15:41:32 +0000925 size_t opBytesNeeded = sizeof(int32_t) * 2 + sizeof(bool);
926 if (!flatten) {
927 opBytesNeeded += sizeof(void*);
928 }
929 if (this->needOpBytes(opBytesNeeded)) {
930 this->writeOp(kDrawSprite_DrawOp, 0, bitmapIndex);
931 if (!flatten) {
932 fWriter.writePtr(const_cast<void*>(ptr));
933 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000934 fWriter.writeBool(paint != NULL);
935 fWriter.write32(left);
936 fWriter.write32(top);
937 }
reed@google.combb6992a2011-04-26 17:41:56 +0000938}
939
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000940void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
reed@google.combb6992a2011-04-26 17:41:56 +0000941 SkScalar y, const SkPaint& paint) {
942 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000943 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000944 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000945 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
reed@google.com31891582011-05-12 03:03:56 +0000946 this->writeOp(kDrawText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000947 fWriter.write32(byteLength);
948 fWriter.writePad(text, byteLength);
949 fWriter.writeScalar(x);
950 fWriter.writeScalar(y);
951 }
reed@google.combb6992a2011-04-26 17:41:56 +0000952 }
953}
954
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000955void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
reed@google.combb6992a2011-04-26 17:41:56 +0000956 const SkPoint pos[], const SkPaint& paint) {
957 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000958 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000959 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000960 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000961 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000962 this->writeOp(kDrawPosText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000963 fWriter.write32(byteLength);
964 fWriter.writePad(text, byteLength);
965 fWriter.write32(count);
966 fWriter.write(pos, count * sizeof(SkPoint));
967 }
reed@google.combb6992a2011-04-26 17:41:56 +0000968 }
969}
970
971void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
972 const SkScalar xpos[], SkScalar constY,
973 const SkPaint& paint) {
974 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000975 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000976 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000977 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000978 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
reed@google.com31891582011-05-12 03:03:56 +0000979 this->writeOp(kDrawPosTextH_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000980 fWriter.write32(byteLength);
981 fWriter.writePad(text, byteLength);
982 fWriter.write32(count);
983 fWriter.write(xpos, count * sizeof(SkScalar));
984 fWriter.writeScalar(constY);
985 }
reed@google.combb6992a2011-04-26 17:41:56 +0000986 }
987}
988
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000989void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
990 const SkPath& path, const SkMatrix* matrix,
reed@google.combb6992a2011-04-26 17:41:56 +0000991 const SkPaint& paint) {
992 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000993 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000994 unsigned flags = 0;
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000995 size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000996 if (matrix) {
997 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000998 size += matrix->writeToMemory(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000999 }
reed@google.com31891582011-05-12 03:03:56 +00001000 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +00001001 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +00001002 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
reed@google.combb6992a2011-04-26 17:41:56 +00001003
reed@google.comacd471f2011-05-03 21:26:46 +00001004 fWriter.write32(byteLength);
1005 fWriter.writePad(text, byteLength);
reed@google.combb6992a2011-04-26 17:41:56 +00001006
djsollen@google.com94e75ee2012-06-08 18:30:46 +00001007 fWriter.writePath(path);
reed@google.comacd471f2011-05-03 21:26:46 +00001008 if (matrix) {
djsollen@google.com2b2ede32012-04-12 13:24:04 +00001009 fWriter.writeMatrix(*matrix);
reed@google.comacd471f2011-05-03 21:26:46 +00001010 }
reed@google.combb6992a2011-04-26 17:41:56 +00001011 }
1012 }
1013}
1014
1015void SkGPipeCanvas::drawPicture(SkPicture& picture) {
reed@google.com0faac1e2011-05-11 05:58:58 +00001016 // we want to playback the picture into individual draw calls
1017 this->INHERITED::drawPicture(picture);
reed@google.combb6992a2011-04-26 17:41:56 +00001018}
1019
reed@google.combb6992a2011-04-26 17:41:56 +00001020void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
1021 const SkPoint vertices[], const SkPoint texs[],
1022 const SkColor colors[], SkXfermode*,
1023 const uint16_t indices[], int indexCount,
1024 const SkPaint& paint) {
1025 if (0 == vertexCount) {
1026 return;
1027 }
1028
reed@google.comacd471f2011-05-03 21:26:46 +00001029 NOTIFY_SETUP(this);
1030 size_t size = 4 + vertexCount * sizeof(SkPoint);
reed@google.com31891582011-05-12 03:03:56 +00001031 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +00001032 unsigned flags = 0;
1033 if (texs) {
1034 flags |= kDrawVertices_HasTexs_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +00001035 size += vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +00001036 }
1037 if (colors) {
1038 flags |= kDrawVertices_HasColors_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +00001039 size += vertexCount * sizeof(SkColor);
reed@google.combb6992a2011-04-26 17:41:56 +00001040 }
1041 if (indices && indexCount > 0) {
1042 flags |= kDrawVertices_HasIndices_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +00001043 size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
reed@google.combb6992a2011-04-26 17:41:56 +00001044 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +00001045
reed@google.comacd471f2011-05-03 21:26:46 +00001046 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +00001047 this->writeOp(kDrawVertices_DrawOp, flags, 0);
reed@google.comacd471f2011-05-03 21:26:46 +00001048 fWriter.write32(mode);
1049 fWriter.write32(vertexCount);
1050 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
1051 if (texs) {
1052 fWriter.write(texs, vertexCount * sizeof(SkPoint));
1053 }
1054 if (colors) {
1055 fWriter.write(colors, vertexCount * sizeof(SkColor));
1056 }
reed@google.combb6992a2011-04-26 17:41:56 +00001057
reed@google.comacd471f2011-05-03 21:26:46 +00001058 // TODO: flatten xfermode
reed@google.combb6992a2011-04-26 17:41:56 +00001059
reed@google.comacd471f2011-05-03 21:26:46 +00001060 if (indices && indexCount > 0) {
1061 fWriter.write32(indexCount);
1062 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
1063 }
reed@google.combb6992a2011-04-26 17:41:56 +00001064 }
1065}
1066
reed@google.comacd471f2011-05-03 21:26:46 +00001067void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
1068 if (size && ptr) {
1069 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +00001070 unsigned data = 0;
1071 if (size < (1 << DRAWOPS_DATA_BITS)) {
1072 data = (unsigned)size;
1073 }
reed@google.comacd471f2011-05-03 21:26:46 +00001074 if (this->needOpBytes(4 + SkAlign4(size))) {
1075 this->writeOp(kDrawData_DrawOp, 0, data);
1076 if (0 == data) {
1077 fWriter.write32(size);
1078 }
reed@google.combb6793b2011-05-05 15:18:15 +00001079 fWriter.writePad(ptr, size);
reed@google.combb6992a2011-04-26 17:41:56 +00001080 }
1081 }
1082}
1083
1084///////////////////////////////////////////////////////////////////////////////
1085
1086template <typename T> uint32_t castToU32(T value) {
1087 union {
1088 T fSrc;
1089 uint32_t fDst;
1090 } data;
1091 data.fSrc = value;
1092 return data.fDst;
1093}
1094
reed@google.com31891582011-05-12 03:03:56 +00001095void SkGPipeCanvas::writePaint(const SkPaint& paint) {
1096 SkPaint& base = fPaint;
reed@google.combb6992a2011-04-26 17:41:56 +00001097 uint32_t storage[32];
1098 uint32_t* ptr = storage;
reed@google.combb6992a2011-04-26 17:41:56 +00001099
1100 if (base.getFlags() != paint.getFlags()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001101 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
reed@google.comf5842f72011-05-04 18:30:04 +00001102 base.setFlags(paint.getFlags());
reed@google.combb6992a2011-04-26 17:41:56 +00001103 }
1104 if (base.getColor() != paint.getColor()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001105 *ptr++ = PaintOp_packOp(kColor_PaintOp);
1106 *ptr++ = paint.getColor();
reed@google.comf5842f72011-05-04 18:30:04 +00001107 base.setColor(paint.getColor());
reed@google.combb6992a2011-04-26 17:41:56 +00001108 }
1109 if (base.getStyle() != paint.getStyle()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001110 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
reed@google.comf5842f72011-05-04 18:30:04 +00001111 base.setStyle(paint.getStyle());
reed@google.combb6992a2011-04-26 17:41:56 +00001112 }
1113 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001114 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
reed@google.comf5842f72011-05-04 18:30:04 +00001115 base.setStrokeJoin(paint.getStrokeJoin());
reed@google.combb6992a2011-04-26 17:41:56 +00001116 }
1117 if (base.getStrokeCap() != paint.getStrokeCap()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001118 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
reed@google.comf5842f72011-05-04 18:30:04 +00001119 base.setStrokeCap(paint.getStrokeCap());
reed@google.combb6992a2011-04-26 17:41:56 +00001120 }
1121 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001122 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
1123 *ptr++ = castToU32(paint.getStrokeWidth());
reed@google.comf5842f72011-05-04 18:30:04 +00001124 base.setStrokeWidth(paint.getStrokeWidth());
reed@google.combb6992a2011-04-26 17:41:56 +00001125 }
1126 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001127 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
1128 *ptr++ = castToU32(paint.getStrokeMiter());
reed@google.comf5842f72011-05-04 18:30:04 +00001129 base.setStrokeMiter(paint.getStrokeMiter());
reed@google.combb6992a2011-04-26 17:41:56 +00001130 }
1131 if (base.getTextEncoding() != paint.getTextEncoding()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001132 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
reed@google.comf5842f72011-05-04 18:30:04 +00001133 base.setTextEncoding(paint.getTextEncoding());
reed@google.combb6992a2011-04-26 17:41:56 +00001134 }
1135 if (base.getHinting() != paint.getHinting()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001136 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
reed@google.comf5842f72011-05-04 18:30:04 +00001137 base.setHinting(paint.getHinting());
reed@google.combb6992a2011-04-26 17:41:56 +00001138 }
1139 if (base.getTextAlign() != paint.getTextAlign()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001140 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
reed@google.comf5842f72011-05-04 18:30:04 +00001141 base.setTextAlign(paint.getTextAlign());
reed@google.combb6992a2011-04-26 17:41:56 +00001142 }
1143 if (base.getTextSize() != paint.getTextSize()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001144 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
1145 *ptr++ = castToU32(paint.getTextSize());
reed@google.comf5842f72011-05-04 18:30:04 +00001146 base.setTextSize(paint.getTextSize());
reed@google.combb6992a2011-04-26 17:41:56 +00001147 }
1148 if (base.getTextScaleX() != paint.getTextScaleX()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001149 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
1150 *ptr++ = castToU32(paint.getTextScaleX());
reed@google.comf5842f72011-05-04 18:30:04 +00001151 base.setTextScaleX(paint.getTextScaleX());
reed@google.combb6992a2011-04-26 17:41:56 +00001152 }
1153 if (base.getTextSkewX() != paint.getTextSkewX()) {
reed@google.combb6992a2011-04-26 17:41:56 +00001154 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
1155 *ptr++ = castToU32(paint.getTextSkewX());
reed@google.comf5842f72011-05-04 18:30:04 +00001156 base.setTextSkewX(paint.getTextSkewX());
1157 }
1158
1159 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
1160 uint32_t id = this->getTypefaceID(paint.getTypeface());
reed@google.comf5842f72011-05-04 18:30:04 +00001161 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
1162 base.setTypeface(paint.getTypeface());
reed@google.combb6992a2011-04-26 17:41:56 +00001163 }
reed@google.combb6992a2011-04-26 17:41:56 +00001164
reed@google.comb55d1182011-05-11 00:42:04 +00001165 for (int i = 0; i < kCount_PaintFlats; i++) {
1166 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i);
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +00001167 bool replaced = index < 0;
1168 if (replaced) {
1169 index = ~index;
1170 }
reed@google.comb55d1182011-05-11 00:42:04 +00001171 SkASSERT(index >= 0 && index <= fFlatArray.count());
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +00001172 if (index != fCurrFlatIndex[i] || replaced) {
reed@google.comb55d1182011-05-11 00:42:04 +00001173 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index);
1174 fCurrFlatIndex[i] = index;
1175 }
1176 }
1177
reed@google.comacd471f2011-05-03 21:26:46 +00001178 size_t size = (char*)ptr - (char*)storage;
1179 if (size && this->needOpBytes(size)) {
reed@google.comb55d1182011-05-11 00:42:04 +00001180 this->writeOp(kPaintOp_DrawOp, 0, size);
reed@google.comb55d1182011-05-11 00:42:04 +00001181 fWriter.write(storage, size);
reed@google.combb6992a2011-04-26 17:41:56 +00001182 for (size_t i = 0; i < size/4; i++) {
reed@google.comb55d1182011-05-11 00:42:04 +00001183// SkDebugf("[%d] %08X\n", i, storage[i]);
reed@google.combb6992a2011-04-26 17:41:56 +00001184 }
1185 }
reed@google.combb6992a2011-04-26 17:41:56 +00001186}
1187
1188///////////////////////////////////////////////////////////////////////////////
1189
1190#include "SkGPipe.h"
1191
reed@google.comacd471f2011-05-03 21:26:46 +00001192SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
reed@google.combb6992a2011-04-26 17:41:56 +00001193 fCanvas = NULL;
1194}
1195
1196SkGPipeWriter::~SkGPipeWriter() {
reed@google.comacd471f2011-05-03 21:26:46 +00001197 this->endRecording();
reed@google.combb6992a2011-04-26 17:41:56 +00001198 SkSafeUnref(fCanvas);
1199}
1200
scroggo@google.com565254b2012-06-28 15:41:32 +00001201SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags) {
reed@google.combb6992a2011-04-26 17:41:56 +00001202 if (NULL == fCanvas) {
reed@google.comacd471f2011-05-03 21:26:46 +00001203 fWriter.reset(NULL, 0);
reed@google.comdde09562011-05-23 12:21:05 +00001204 fFactorySet.reset();
1205 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter,
1206 (flags & kCrossProcess_Flag) ?
scroggo@google.com565254b2012-06-28 15:41:32 +00001207 &fFactorySet : NULL, flags));
reed@google.combb6992a2011-04-26 17:41:56 +00001208 }
1209 return fCanvas;
1210}
1211
1212void SkGPipeWriter::endRecording() {
1213 if (fCanvas) {
1214 fCanvas->finish();
1215 fCanvas->unref();
1216 fCanvas = NULL;
1217 }
1218}
1219