blob: 5734a278006b3a36ed573e227aabccdd0eedffe0 [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());
scroggo@google.com5af9b202012-06-04 17:17:36 +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?)
66 * TODO: Allow reclaiming of memory. Will require us to know when all readers
67 * have used the object.
68 */
69class Heap {
70public:
scroggo@google.com565254b2012-06-28 15:41:32 +000071 Heap(bool shallow) : fCanDoShallowCopies(shallow) {}
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000072 ~Heap() {
73 for (int i = 0; i < fBitmaps.count(); i++) {
74 delete fBitmaps[i].fBitmap;
75 }
76 }
77
78 /*
79 * Add a copy of a bitmap to the heap.
80 * @param bm The SkBitmap to be copied and placed in the heap.
81 * @return void* Pointer to the heap's copy of the bitmap. If NULL,
82 * the bitmap could not be copied.
83 */
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +000084 const SkBitmap* addBitmap(const SkBitmap& orig) {
85 const uint32_t genID = orig.getGenerationID();
86 SkPixelRef* sharedPixelRef = NULL;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000087 for (int i = fBitmaps.count() - 1; i >= 0; i--) {
scroggo@google.com6ea165d2012-07-03 14:52:08 +000088 SkBitmap* storedBitmap = fBitmaps[i].fBitmap;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000089 if (genID == fBitmaps[i].fGenID) {
scroggo@google.com6ea165d2012-07-03 14:52:08 +000090 if (orig.pixelRefOffset() != storedBitmap->pixelRefOffset()
91 || orig.width() != storedBitmap->width()
92 || orig.height() != storedBitmap->height()) {
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +000093 // In this case, the bitmaps share a pixelRef, but have
scroggo@google.com6ea165d2012-07-03 14:52:08 +000094 // different offsets or sizes. Keep track of the other
95 // bitmap so that instead of making another copy of the
96 // pixelRef we can use the copy we already made.
97 sharedPixelRef = storedBitmap->pixelRef();
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +000098 break;
99 }
scroggo@google.com6ea165d2012-07-03 14:52:08 +0000100 return storedBitmap;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000101 }
102 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000103 SkBitmap* copy;
104 // If the bitmap is mutable, we still need to do a deep copy, since the
105 // caller may modify it afterwards. That said, if the bitmap is mutable,
106 // but has no pixelRef, the copy constructor actually does a deep copy.
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +0000107 if (fCanDoShallowCopies && (orig.isImmutable() || !orig.pixelRef())) {
108 copy = new SkBitmap(orig);
scroggo@google.com565254b2012-06-28 15:41:32 +0000109 } else {
scroggo@google.com4f1f6bf2012-07-02 13:35:09 +0000110 if (sharedPixelRef != NULL) {
111 // Do a shallow copy of the bitmap to get the width, height, etc
112 copy = new SkBitmap(orig);
113 // Replace the pixelRef with the copy that was already made, and
114 // use the appropriate offset.
115 copy->setPixelRef(sharedPixelRef, orig.pixelRefOffset());
116 } else {
117 copy = new SkBitmap();
118 if (!orig.copyTo(copy, orig.getConfig())) {
119 delete copy;
120 return NULL;
121 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000122 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000123 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000124 BitmapInfo* info = fBitmaps.append();
125 info->fBitmap = copy;
126 info->fGenID = genID;
127 return copy;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000128 }
129private:
130 struct BitmapInfo {
131 SkBitmap* fBitmap;
132 // Store the generation ID of the original bitmap, since copying does
133 // not copy this field, so fBitmap's generation ID will not be useful
134 // for comparing.
135 uint32_t fGenID;
136 };
scroggo@google.com565254b2012-06-28 15:41:32 +0000137 SkTDArray<BitmapInfo> fBitmaps;
138 const bool fCanDoShallowCopies;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000139};
140
141///////////////////////////////////////////////////////////////////////////////
142
reed@google.combb6992a2011-04-26 17:41:56 +0000143class SkGPipeCanvas : public SkCanvas {
144public:
scroggo@google.com565254b2012-06-28 15:41:32 +0000145 SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*, uint32_t flags);
reed@google.combb6992a2011-04-26 17:41:56 +0000146 virtual ~SkGPipeCanvas();
147
148 void finish() {
149 if (!fDone) {
reed@google.comdbccc882011-07-08 18:53:39 +0000150 if (this->needOpBytes()) {
151 this->writeOp(kDone_DrawOp);
152 this->doNotify();
153 }
reed@google.combb6992a2011-04-26 17:41:56 +0000154 fDone = true;
155 }
156 }
157
158 // overrides from SkCanvas
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000159 virtual int save(SaveFlags) SK_OVERRIDE;
160 virtual int saveLayer(const SkRect* bounds, const SkPaint*,
161 SaveFlags) SK_OVERRIDE;
162 virtual void restore() SK_OVERRIDE;
163 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
164 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
165 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
166 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
167 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
168 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
169 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
170 bool doAntiAlias = false) SK_OVERRIDE;
171 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
172 bool doAntiAlias = false) SK_OVERRIDE;
173 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) SK_OVERRIDE;
174 virtual void clear(SkColor) SK_OVERRIDE;
175 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000176 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000177 const SkPaint&) SK_OVERRIDE;
178 virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE;
179 virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000180 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000181 const SkPaint*) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000182 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000183 const SkRect& dst, const SkPaint*) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000184 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000185 const SkPaint*) SK_OVERRIDE;
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000186 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
187 const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000188 virtual void drawSprite(const SkBitmap&, int left, int top,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000189 const SkPaint*) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000190 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000191 SkScalar y, const SkPaint&) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000192 virtual void drawPosText(const void* text, size_t byteLength,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000193 const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000194 virtual void drawPosTextH(const void* text, size_t byteLength,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000195 const SkScalar xpos[], SkScalar constY,
196 const SkPaint&) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000197 virtual void drawTextOnPath(const void* text, size_t byteLength,
198 const SkPath& path, const SkMatrix* matrix,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000199 const SkPaint&) SK_OVERRIDE;
200 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000201 virtual void drawVertices(VertexMode, int vertexCount,
202 const SkPoint vertices[], const SkPoint texs[],
203 const SkColor colors[], SkXfermode*,
204 const uint16_t indices[], int indexCount,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000205 const SkPaint&) SK_OVERRIDE;
206 virtual void drawData(const void*, size_t) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000207
208private:
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000209 Heap fHeap;
reed@google.comdde09562011-05-23 12:21:05 +0000210 SkFactorySet* fFactorySet; // optional, only used if cross-process
reed@google.comacd471f2011-05-03 21:26:46 +0000211 SkGPipeController* fController;
reed@google.combb6992a2011-04-26 17:41:56 +0000212 SkWriter32& fWriter;
reed@google.comacd471f2011-05-03 21:26:46 +0000213 size_t fBlockSize; // amount allocated for writer
214 size_t fBytesNotified;
reed@google.combb6992a2011-04-26 17:41:56 +0000215 bool fDone;
scroggo@google.com565254b2012-06-28 15:41:32 +0000216 uint32_t fFlags;
reed@google.combb6992a2011-04-26 17:41:56 +0000217
reed@google.comf5842f72011-05-04 18:30:04 +0000218 SkRefCntSet fTypefaceSet;
219
220 uint32_t getTypefaceID(SkTypeface*);
221
reed@google.comacd471f2011-05-03 21:26:46 +0000222 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
reed@google.combb6992a2011-04-26 17:41:56 +0000223 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
224 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000225
reed@google.comacd471f2011-05-03 21:26:46 +0000226 inline void writeOp(DrawOps op) {
reed@google.combb6992a2011-04-26 17:41:56 +0000227 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
228 }
reed@google.comacd471f2011-05-03 21:26:46 +0000229
230 bool needOpBytes(size_t size = 0);
231
232 inline void doNotify() {
233 if (!fDone) {
234 size_t bytes = fWriter.size() - fBytesNotified;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000235 if (bytes > 0) {
236 fController->notifyWritten(bytes);
237 fBytesNotified += bytes;
238 }
reed@google.comacd471f2011-05-03 21:26:46 +0000239 }
240 }
reed@google.comb55d1182011-05-11 00:42:04 +0000241
242 struct FlatData {
243 uint32_t fIndex; // always > 0
244 uint32_t fSize;
245
246 void* data() { return (char*)this + sizeof(*this); }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000247
reed@google.comb55d1182011-05-11 00:42:04 +0000248 static int Compare(const FlatData* a, const FlatData* b) {
249 return memcmp(&a->fSize, &b->fSize, a->fSize + sizeof(a->fSize));
250 }
251 };
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000252
253 SkTDArray<FlatData*> fBitmapArray;
254 int flattenToIndex(const SkBitmap&);
255
reed@google.comb55d1182011-05-11 00:42:04 +0000256 SkTDArray<FlatData*> fFlatArray;
257 int fCurrFlatIndex[kCount_PaintFlats];
258 int flattenToIndex(SkFlattenable* obj, PaintFlats);
259
reed@google.com31891582011-05-12 03:03:56 +0000260 SkPaint fPaint;
261 void writePaint(const SkPaint&);
reed@google.combb6992a2011-04-26 17:41:56 +0000262
reed@google.comacd471f2011-05-03 21:26:46 +0000263 class AutoPipeNotify {
264 public:
265 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
266 ~AutoPipeNotify() { fCanvas->doNotify(); }
267 private:
268 SkGPipeCanvas* fCanvas;
269 };
270 friend class AutoPipeNotify;
271
reed@google.combb6992a2011-04-26 17:41:56 +0000272 typedef SkCanvas INHERITED;
273};
274
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000275int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000276 SkASSERT(shouldFlattenBitmaps(fFlags));
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000277 SkOrderedWriteBuffer tmpWriter(1024);
scroggo@google.com565254b2012-06-28 15:41:32 +0000278 tmpWriter.setFlags((SkFlattenableWriteBuffer::Flags)
279 (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
280 | SkFlattenableWriteBuffer::kCrossProcess_Flag));
281 tmpWriter.setFactoryRecorder(fFactorySet);
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000282 bitmap.flatten(tmpWriter);
283
284 size_t len = tmpWriter.size();
285 size_t allocSize = len + sizeof(FlatData);
286
287 SkAutoSMalloc<1024> storage(allocSize);
288 FlatData* flat = (FlatData*)storage.get();
289 flat->fSize = len;
290 tmpWriter.flatten(flat->data());
291
292 int index = SkTSearch<FlatData>((const FlatData**)fBitmapArray.begin(),
293 fBitmapArray.count(), flat, sizeof(flat),
294 &FlatData::Compare);
295 if (index < 0) {
296 index = ~index;
297 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
298 memcpy(copy, flat, allocSize);
299 // For bitmaps, we can use zero based indices, since we will never ask
300 // for a NULL bitmap (unlike with paint flattenables).
301 copy->fIndex = fBitmapArray.count();
302 *fBitmapArray.insert(index) = copy;
scroggo@google.com565254b2012-06-28 15:41:32 +0000303 if (this->needOpBytes(len)) {
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000304 this->writeOp(kDef_Bitmap_DrawOp, 0, copy->fIndex);
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000305 fWriter.write(copy->data(), len);
306 }
307 }
308 return fBitmapArray[index]->fIndex;
309}
310
reed@google.comb55d1182011-05-11 00:42:04 +0000311// return 0 for NULL (or unflattenable obj), or index-base-1
312int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
313 if (NULL == obj) {
314 return 0;
315 }
reed@google.comb55d1182011-05-11 00:42:04 +0000316
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000317 SkOrderedWriteBuffer tmpWriter(1024);
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000318
scroggo@google.com565254b2012-06-28 15:41:32 +0000319 if (fFlags & SkGPipeWriter::kCrossProcess_Flag) {
320 tmpWriter.setFlags((SkFlattenableWriteBuffer::Flags)
321 (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
322 | SkFlattenableWriteBuffer::kCrossProcess_Flag));
323 tmpWriter.setFactoryRecorder(fFactorySet);
324 } else {
325 // Needed for bitmap shaders.
326 tmpWriter.setFlags(SkFlattenableWriteBuffer::kForceFlattenBitmapPixels_Flag);
327 }
reed@google.comdde09562011-05-23 12:21:05 +0000328
reed@google.comb55d1182011-05-11 00:42:04 +0000329 tmpWriter.writeFlattenable(obj);
330 size_t len = tmpWriter.size();
331 size_t allocSize = len + sizeof(FlatData);
332
333 SkAutoSMalloc<1024> storage(allocSize);
334 FlatData* flat = (FlatData*)storage.get();
335 flat->fSize = len;
336 tmpWriter.flatten(flat->data());
337
338 int index = SkTSearch<FlatData>((const FlatData**)fFlatArray.begin(),
339 fFlatArray.count(), flat, sizeof(flat),
340 &FlatData::Compare);
341 if (index < 0) {
342 index = ~index;
343 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
344 memcpy(copy, flat, allocSize);
345 *fFlatArray.insert(index) = copy;
346 // call this after the insert, so that count() will have been grown
347 copy->fIndex = fFlatArray.count();
348// SkDebugf("--- add flattenable[%d] size=%d index=%d\n", paintflat, len, copy->fIndex);
349
350 if (this->needOpBytes(len)) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000351 this->writeOp(kDef_Flattenable_DrawOp, paintflat, copy->fIndex);
reed@google.comb55d1182011-05-11 00:42:04 +0000352 fWriter.write(copy->data(), len);
353 }
354 }
355 return fFlatArray[index]->fIndex;
356}
357
reed@google.combb6992a2011-04-26 17:41:56 +0000358///////////////////////////////////////////////////////////////////////////////
359
reed@google.comacd471f2011-05-03 21:26:46 +0000360#define MIN_BLOCK_SIZE (16 * 1024)
reed@google.combb6992a2011-04-26 17:41:56 +0000361
reed@google.comacd471f2011-05-03 21:26:46 +0000362SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
scroggo@google.com565254b2012-06-28 15:41:32 +0000363 SkWriter32* writer, SkFactorySet* fset, uint32_t flags)
scroggo@google.comd33819a2012-06-29 19:24:25 +0000364: fHeap(!(flags & SkGPipeWriter::kCrossProcess_Flag)), fWriter(*writer), fFlags(flags) {
reed@google.com67908f22011-06-27 14:47:50 +0000365 fFactorySet = fset;
reed@google.comacd471f2011-05-03 21:26:46 +0000366 fController = controller;
reed@google.combb6992a2011-04-26 17:41:56 +0000367 fDone = false;
reed@google.comacd471f2011-05-03 21:26:46 +0000368 fBlockSize = 0; // need first block from controller
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000369 fBytesNotified = 0;
reed@google.comb55d1182011-05-11 00:42:04 +0000370 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
reed@google.comacd471f2011-05-03 21:26:46 +0000371
reed@google.combb6793b2011-05-05 15:18:15 +0000372 // we need a device to limit our clip
373 // should the caller give us the bounds?
yangsu@google.com06b4da162011-06-17 15:04:40 +0000374 // We don't allocate pixels for the bitmap
reed@google.combb6793b2011-05-05 15:18:15 +0000375 SkBitmap bitmap;
376 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32767, 32767);
yangsu@google.com06b4da162011-06-17 15:04:40 +0000377 SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
reed@google.combb6793b2011-05-05 15:18:15 +0000378 this->setDevice(device)->unref();
scroggo@google.com565254b2012-06-28 15:41:32 +0000379 // Tell the reader the appropriate flags to use.
380 if (this->needOpBytes()) {
381 this->writeOp(kReportFlags_DrawOp, fFlags, 0);
382 }
reed@google.combb6992a2011-04-26 17:41:56 +0000383}
384
385SkGPipeCanvas::~SkGPipeCanvas() {
386 this->finish();
387
reed@google.comb55d1182011-05-11 00:42:04 +0000388 fFlatArray.freeAll();
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000389 fBitmapArray.freeAll();
reed@google.combb6992a2011-04-26 17:41:56 +0000390}
391
reed@google.comacd471f2011-05-03 21:26:46 +0000392bool SkGPipeCanvas::needOpBytes(size_t needed) {
393 if (fDone) {
394 return false;
395 }
396
397 needed += 4; // size of DrawOp atom
398 if (fWriter.size() + needed > fBlockSize) {
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000399 // Before we wipe out any data that has already been written, read it
400 // out.
401 this->doNotify();
402 size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed);
403 void* block = fController->requestBlock(blockSize, &fBlockSize);
reed@google.comacd471f2011-05-03 21:26:46 +0000404 if (NULL == block) {
405 fDone = true;
406 return false;
407 }
408 fWriter.reset(block, fBlockSize);
409 fBytesNotified = 0;
410 }
411 return true;
412}
413
reed@google.comf5842f72011-05-04 18:30:04 +0000414uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
415 uint32_t id = 0; // 0 means default/null typeface
416 if (face) {
417 id = fTypefaceSet.find(face);
418 if (0 == id) {
419 id = fTypefaceSet.add(face);
420 size_t size = writeTypeface(NULL, face);
421 if (this->needOpBytes(size)) {
reed@google.combb6793b2011-05-05 15:18:15 +0000422 this->writeOp(kDef_Typeface_DrawOp);
reed@google.comf5842f72011-05-04 18:30:04 +0000423 writeTypeface(&fWriter, face);
424 }
425 }
426 }
427 return id;
428}
429
reed@google.combb6992a2011-04-26 17:41:56 +0000430///////////////////////////////////////////////////////////////////////////////
431
reed@google.comacd471f2011-05-03 21:26:46 +0000432#define NOTIFY_SETUP(canvas) \
433 AutoPipeNotify apn(canvas)
434
reed@google.combb6992a2011-04-26 17:41:56 +0000435int SkGPipeCanvas::save(SaveFlags flags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000436 NOTIFY_SETUP(this);
437 if (this->needOpBytes()) {
438 this->writeOp(kSave_DrawOp, 0, flags);
439 }
reed@google.combb6992a2011-04-26 17:41:56 +0000440 return this->INHERITED::save(flags);
441}
442
443int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
444 SaveFlags saveFlags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000445 NOTIFY_SETUP(this);
446 size_t size = 0;
reed@google.combb6992a2011-04-26 17:41:56 +0000447 unsigned opFlags = 0;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000448
reed@google.combb6992a2011-04-26 17:41:56 +0000449 if (bounds) {
450 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000451 size += sizeof(SkRect);
reed@google.combb6992a2011-04-26 17:41:56 +0000452 }
453 if (paint) {
454 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
reed@google.com31891582011-05-12 03:03:56 +0000455 this->writePaint(*paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000456 }
457
reed@google.comacd471f2011-05-03 21:26:46 +0000458 if (this->needOpBytes(size)) {
459 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
460 if (bounds) {
461 fWriter.writeRect(*bounds);
462 }
reed@google.combb6992a2011-04-26 17:41:56 +0000463 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000464
reed@google.combb6992a2011-04-26 17:41:56 +0000465 // we just pass on the save, so we don't create a layer
466 return this->INHERITED::save(saveFlags);
467}
468
469void SkGPipeCanvas::restore() {
reed@google.comacd471f2011-05-03 21:26:46 +0000470 NOTIFY_SETUP(this);
471 if (this->needOpBytes()) {
472 this->writeOp(kRestore_DrawOp);
473 }
reed@google.combb6992a2011-04-26 17:41:56 +0000474 this->INHERITED::restore();
475}
476
477bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
478 if (dx || dy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000479 NOTIFY_SETUP(this);
480 if (this->needOpBytes(2 * sizeof(SkScalar))) {
481 this->writeOp(kTranslate_DrawOp);
482 fWriter.writeScalar(dx);
483 fWriter.writeScalar(dy);
484 }
reed@google.combb6992a2011-04-26 17:41:56 +0000485 }
486 return this->INHERITED::translate(dx, dy);
487}
488
489bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
490 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000491 NOTIFY_SETUP(this);
492 if (this->needOpBytes(2 * sizeof(SkScalar))) {
493 this->writeOp(kScale_DrawOp);
494 fWriter.writeScalar(sx);
495 fWriter.writeScalar(sy);
496 }
reed@google.combb6992a2011-04-26 17:41:56 +0000497 }
498 return this->INHERITED::scale(sx, sy);
499}
500
501bool SkGPipeCanvas::rotate(SkScalar degrees) {
502 if (degrees) {
reed@google.comacd471f2011-05-03 21:26:46 +0000503 NOTIFY_SETUP(this);
504 if (this->needOpBytes(sizeof(SkScalar))) {
505 this->writeOp(kRotate_DrawOp);
506 fWriter.writeScalar(degrees);
507 }
reed@google.combb6992a2011-04-26 17:41:56 +0000508 }
509 return this->INHERITED::rotate(degrees);
510}
511
512bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
513 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000514 NOTIFY_SETUP(this);
515 if (this->needOpBytes(2 * sizeof(SkScalar))) {
516 this->writeOp(kSkew_DrawOp);
517 fWriter.writeScalar(sx);
518 fWriter.writeScalar(sy);
519 }
reed@google.combb6992a2011-04-26 17:41:56 +0000520 }
521 return this->INHERITED::skew(sx, sy);
522}
523
524bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
525 if (!matrix.isIdentity()) {
reed@google.comacd471f2011-05-03 21:26:46 +0000526 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000527 if (this->needOpBytes(matrix.writeToMemory(NULL))) {
reed@google.comacd471f2011-05-03 21:26:46 +0000528 this->writeOp(kConcat_DrawOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000529 fWriter.writeMatrix(matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000530 }
reed@google.combb6992a2011-04-26 17:41:56 +0000531 }
532 return this->INHERITED::concat(matrix);
533}
534
535void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
reed@google.comacd471f2011-05-03 21:26:46 +0000536 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000537 if (this->needOpBytes(matrix.writeToMemory(NULL))) {
reed@google.comacd471f2011-05-03 21:26:46 +0000538 this->writeOp(kSetMatrix_DrawOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000539 fWriter.writeMatrix(matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000540 }
reed@google.combb6992a2011-04-26 17:41:56 +0000541 this->INHERITED::setMatrix(matrix);
542}
543
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000544bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp,
545 bool doAntiAlias) {
reed@google.comacd471f2011-05-03 21:26:46 +0000546 NOTIFY_SETUP(this);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000547 if (this->needOpBytes(sizeof(SkRect)) + sizeof(bool)) {
reed@google.comacd471f2011-05-03 21:26:46 +0000548 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
549 fWriter.writeRect(rect);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000550 fWriter.writeBool(doAntiAlias);
reed@google.comacd471f2011-05-03 21:26:46 +0000551 }
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000552 return this->INHERITED::clipRect(rect, rgnOp, doAntiAlias);
reed@google.combb6992a2011-04-26 17:41:56 +0000553}
554
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000555bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp,
556 bool doAntiAlias) {
reed@google.comacd471f2011-05-03 21:26:46 +0000557 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000558 if (this->needOpBytes(path.writeToMemory(NULL)) + sizeof(bool)) {
reed@google.comacd471f2011-05-03 21:26:46 +0000559 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000560 fWriter.writePath(path);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000561 fWriter.writeBool(doAntiAlias);
reed@google.comacd471f2011-05-03 21:26:46 +0000562 }
reed@google.combb6992a2011-04-26 17:41:56 +0000563 // we just pass on the bounds of the path
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000564 return this->INHERITED::clipRect(path.getBounds(), rgnOp, doAntiAlias);
reed@google.combb6992a2011-04-26 17:41:56 +0000565}
566
567bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000568 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000569 if (this->needOpBytes(region.writeToMemory(NULL))) {
reed@google.comacd471f2011-05-03 21:26:46 +0000570 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000571 fWriter.writeRegion(region);
reed@google.comacd471f2011-05-03 21:26:46 +0000572 }
reed@google.combb6992a2011-04-26 17:41:56 +0000573 return this->INHERITED::clipRegion(region, rgnOp);
574}
575
576///////////////////////////////////////////////////////////////////////////////
577
578void SkGPipeCanvas::clear(SkColor color) {
reed@google.comacd471f2011-05-03 21:26:46 +0000579 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000580 unsigned flags = 0;
581 if (color) {
582 flags |= kClear_HasColor_DrawOpFlag;
583 }
reed@google.comacd471f2011-05-03 21:26:46 +0000584 if (this->needOpBytes(sizeof(SkColor))) {
585 this->writeOp(kDrawClear_DrawOp, flags, 0);
586 if (color) {
587 fWriter.write32(color);
588 }
reed@google.combb6992a2011-04-26 17:41:56 +0000589 }
590}
591
592void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000593 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000594 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000595 if (this->needOpBytes()) {
reed@google.com31891582011-05-12 03:03:56 +0000596 this->writeOp(kDrawPaint_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000597 }
reed@google.combb6992a2011-04-26 17:41:56 +0000598}
599
600void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
601 const SkPoint pts[], const SkPaint& paint) {
602 if (count) {
reed@google.comacd471f2011-05-03 21:26:46 +0000603 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000604 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000605 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000606 this->writeOp(kDrawPoints_DrawOp, mode, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000607 fWriter.write32(count);
608 fWriter.write(pts, count * sizeof(SkPoint));
609 }
reed@google.combb6992a2011-04-26 17:41:56 +0000610 }
611}
612
613void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000614 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000615 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000616 if (this->needOpBytes(sizeof(SkRect))) {
reed@google.com31891582011-05-12 03:03:56 +0000617 this->writeOp(kDrawRect_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000618 fWriter.writeRect(rect);
619 }
reed@google.combb6992a2011-04-26 17:41:56 +0000620}
621
622void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000623 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000624 this->writePaint(paint);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000625 if (this->needOpBytes(path.writeToMemory(NULL))) {
reed@google.com31891582011-05-12 03:03:56 +0000626 this->writeOp(kDrawPath_DrawOp);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000627 fWriter.writePath(path);
reed@google.comacd471f2011-05-03 21:26:46 +0000628 }
reed@google.combb6992a2011-04-26 17:41:56 +0000629}
630
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000631void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
632 const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000633 bool flatten = shouldFlattenBitmaps(fFlags);
634 const void* ptr = 0;
635 int bitmapIndex = 0;
636 if (flatten) {
637 bitmapIndex = this->flattenToIndex(bm);
638 } else {
639 ptr = fHeap.addBitmap(bm);
640 if (NULL == ptr) {
641 return;
642 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000643 }
644
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000645 NOTIFY_SETUP(this);
646 if (paint) {
647 this->writePaint(*paint);
648 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000649
scroggo@google.com565254b2012-06-28 15:41:32 +0000650 size_t opBytesNeeded = sizeof(SkScalar) * 2 + sizeof(bool);
651 if (!flatten) {
652 opBytesNeeded += sizeof(void*);
653 }
654 if (this->needOpBytes(opBytesNeeded)) {
655 this->writeOp(kDrawBitmap_DrawOp, 0, bitmapIndex);
656 if (!flatten) {
657 fWriter.writePtr(const_cast<void*>(ptr));
658 }
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000659 fWriter.writeBool(paint != NULL);
660 fWriter.writeScalar(left);
661 fWriter.writeScalar(top);
662 }
reed@google.combb6992a2011-04-26 17:41:56 +0000663}
664
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000665void SkGPipeCanvas::drawBitmapRect(const SkBitmap& bm, const SkIRect* src,
666 const SkRect& dst, const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000667 bool flatten = shouldFlattenBitmaps(fFlags);
668 const void* ptr = 0;
669 int bitmapIndex = 0;
670 if (flatten) {
671 bitmapIndex = this->flattenToIndex(bm);
672 } else {
673 ptr = fHeap.addBitmap(bm);
674 if (NULL == ptr) {
675 return;
676 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000677 }
678
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000679 NOTIFY_SETUP(this);
680 if (paint) {
681 this->writePaint(*paint);
682 }
683
scroggo@google.com565254b2012-06-28 15:41:32 +0000684 size_t opBytesNeeded = sizeof(SkRect) + sizeof(bool) * 2;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000685 bool hasSrc = src != NULL;
686 if (hasSrc) {
687 opBytesNeeded += sizeof(int32_t) * 4;
688 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000689 if (!flatten) {
690 opBytesNeeded += sizeof(void*);
691 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000692 if (this->needOpBytes(opBytesNeeded)) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000693 this->writeOp(kDrawBitmapRect_DrawOp, 0, bitmapIndex);
694 if (!flatten) {
695 fWriter.writePtr(const_cast<void*>(ptr));
696 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000697 fWriter.writeBool(paint != NULL);
698 fWriter.writeBool(hasSrc);
699 if (hasSrc) {
700 fWriter.write32(src->fLeft);
701 fWriter.write32(src->fTop);
702 fWriter.write32(src->fRight);
703 fWriter.write32(src->fBottom);
704 }
705 fWriter.writeRect(dst);
706 }
reed@google.combb6992a2011-04-26 17:41:56 +0000707}
708
709void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
710 const SkPaint*) {
711 UNIMPLEMENTED
712}
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000713
714void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000715 const SkRect& dst, const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000716 bool flatten = shouldFlattenBitmaps(fFlags);
717 const void* ptr = 0;
718 int bitmapIndex = 0;
719 if (flatten) {
720 bitmapIndex = this->flattenToIndex(bm);
721 } else {
722 ptr = fHeap.addBitmap(bm);
723 if (NULL == ptr) {
724 return;
725 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000726 }
727
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000728 NOTIFY_SETUP(this);
729 if (paint) {
730 this->writePaint(*paint);
731 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000732
scroggo@google.com565254b2012-06-28 15:41:32 +0000733 size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(bool) + sizeof(SkRect);
734 if (!flatten) {
735 opBytesNeeded += sizeof(void*);
736 }
737 if (this->needOpBytes(opBytesNeeded)) {
738 this->writeOp(kDrawBitmapNine_DrawOp, 0, bitmapIndex);
739 if (!flatten) {
740 fWriter.writePtr(const_cast<void*>(ptr));
741 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000742 fWriter.writeBool(paint != NULL);
743 fWriter.write32(center.fLeft);
744 fWriter.write32(center.fTop);
745 fWriter.write32(center.fRight);
746 fWriter.write32(center.fBottom);
747 fWriter.writeRect(dst);
748 }
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000749}
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000750
751void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
752 const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000753 bool flatten = shouldFlattenBitmaps(fFlags);
754 const void* ptr = 0;
755 int bitmapIndex = 0;
756 if (flatten) {
757 bitmapIndex = this->flattenToIndex(bm);
758 } else {
759 ptr = fHeap.addBitmap(bm);
760 if (NULL == ptr) {
761 return;
762 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000763 }
764
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000765 NOTIFY_SETUP(this);
766 if (paint) {
767 this->writePaint(*paint);
768 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000769
scroggo@google.com565254b2012-06-28 15:41:32 +0000770 size_t opBytesNeeded = sizeof(int32_t) * 2 + sizeof(bool);
771 if (!flatten) {
772 opBytesNeeded += sizeof(void*);
773 }
774 if (this->needOpBytes(opBytesNeeded)) {
775 this->writeOp(kDrawSprite_DrawOp, 0, bitmapIndex);
776 if (!flatten) {
777 fWriter.writePtr(const_cast<void*>(ptr));
778 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000779 fWriter.writeBool(paint != NULL);
780 fWriter.write32(left);
781 fWriter.write32(top);
782 }
reed@google.combb6992a2011-04-26 17:41:56 +0000783}
784
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000785void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
reed@google.combb6992a2011-04-26 17:41:56 +0000786 SkScalar y, const SkPaint& paint) {
787 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000788 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000789 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000790 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
reed@google.com31891582011-05-12 03:03:56 +0000791 this->writeOp(kDrawText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000792 fWriter.write32(byteLength);
793 fWriter.writePad(text, byteLength);
794 fWriter.writeScalar(x);
795 fWriter.writeScalar(y);
796 }
reed@google.combb6992a2011-04-26 17:41:56 +0000797 }
798}
799
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000800void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
reed@google.combb6992a2011-04-26 17:41:56 +0000801 const SkPoint pos[], const SkPaint& paint) {
802 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000803 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000804 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000805 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000806 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000807 this->writeOp(kDrawPosText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000808 fWriter.write32(byteLength);
809 fWriter.writePad(text, byteLength);
810 fWriter.write32(count);
811 fWriter.write(pos, count * sizeof(SkPoint));
812 }
reed@google.combb6992a2011-04-26 17:41:56 +0000813 }
814}
815
816void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
817 const SkScalar xpos[], SkScalar constY,
818 const SkPaint& paint) {
819 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000820 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000821 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000822 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000823 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
reed@google.com31891582011-05-12 03:03:56 +0000824 this->writeOp(kDrawPosTextH_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000825 fWriter.write32(byteLength);
826 fWriter.writePad(text, byteLength);
827 fWriter.write32(count);
828 fWriter.write(xpos, count * sizeof(SkScalar));
829 fWriter.writeScalar(constY);
830 }
reed@google.combb6992a2011-04-26 17:41:56 +0000831 }
832}
833
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000834void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
835 const SkPath& path, const SkMatrix* matrix,
reed@google.combb6992a2011-04-26 17:41:56 +0000836 const SkPaint& paint) {
837 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000838 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000839 unsigned flags = 0;
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000840 size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000841 if (matrix) {
842 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000843 size += matrix->writeToMemory(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000844 }
reed@google.com31891582011-05-12 03:03:56 +0000845 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000846 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +0000847 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
reed@google.combb6992a2011-04-26 17:41:56 +0000848
reed@google.comacd471f2011-05-03 21:26:46 +0000849 fWriter.write32(byteLength);
850 fWriter.writePad(text, byteLength);
reed@google.combb6992a2011-04-26 17:41:56 +0000851
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000852 fWriter.writePath(path);
reed@google.comacd471f2011-05-03 21:26:46 +0000853 if (matrix) {
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000854 fWriter.writeMatrix(*matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000855 }
reed@google.combb6992a2011-04-26 17:41:56 +0000856 }
857 }
858}
859
860void SkGPipeCanvas::drawPicture(SkPicture& picture) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000861 // we want to playback the picture into individual draw calls
862 this->INHERITED::drawPicture(picture);
reed@google.combb6992a2011-04-26 17:41:56 +0000863}
864
reed@google.combb6992a2011-04-26 17:41:56 +0000865void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
866 const SkPoint vertices[], const SkPoint texs[],
867 const SkColor colors[], SkXfermode*,
868 const uint16_t indices[], int indexCount,
869 const SkPaint& paint) {
870 if (0 == vertexCount) {
871 return;
872 }
873
reed@google.comacd471f2011-05-03 21:26:46 +0000874 NOTIFY_SETUP(this);
875 size_t size = 4 + vertexCount * sizeof(SkPoint);
reed@google.com31891582011-05-12 03:03:56 +0000876 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000877 unsigned flags = 0;
878 if (texs) {
879 flags |= kDrawVertices_HasTexs_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000880 size += vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000881 }
882 if (colors) {
883 flags |= kDrawVertices_HasColors_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000884 size += vertexCount * sizeof(SkColor);
reed@google.combb6992a2011-04-26 17:41:56 +0000885 }
886 if (indices && indexCount > 0) {
887 flags |= kDrawVertices_HasIndices_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000888 size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
reed@google.combb6992a2011-04-26 17:41:56 +0000889 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000890
reed@google.comacd471f2011-05-03 21:26:46 +0000891 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +0000892 this->writeOp(kDrawVertices_DrawOp, flags, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000893 fWriter.write32(mode);
894 fWriter.write32(vertexCount);
895 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
896 if (texs) {
897 fWriter.write(texs, vertexCount * sizeof(SkPoint));
898 }
899 if (colors) {
900 fWriter.write(colors, vertexCount * sizeof(SkColor));
901 }
reed@google.combb6992a2011-04-26 17:41:56 +0000902
reed@google.comacd471f2011-05-03 21:26:46 +0000903 // TODO: flatten xfermode
reed@google.combb6992a2011-04-26 17:41:56 +0000904
reed@google.comacd471f2011-05-03 21:26:46 +0000905 if (indices && indexCount > 0) {
906 fWriter.write32(indexCount);
907 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
908 }
reed@google.combb6992a2011-04-26 17:41:56 +0000909 }
910}
911
reed@google.comacd471f2011-05-03 21:26:46 +0000912void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
913 if (size && ptr) {
914 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000915 unsigned data = 0;
916 if (size < (1 << DRAWOPS_DATA_BITS)) {
917 data = (unsigned)size;
918 }
reed@google.comacd471f2011-05-03 21:26:46 +0000919 if (this->needOpBytes(4 + SkAlign4(size))) {
920 this->writeOp(kDrawData_DrawOp, 0, data);
921 if (0 == data) {
922 fWriter.write32(size);
923 }
reed@google.combb6793b2011-05-05 15:18:15 +0000924 fWriter.writePad(ptr, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000925 }
926 }
927}
928
929///////////////////////////////////////////////////////////////////////////////
930
931template <typename T> uint32_t castToU32(T value) {
932 union {
933 T fSrc;
934 uint32_t fDst;
935 } data;
936 data.fSrc = value;
937 return data.fDst;
938}
939
reed@google.com31891582011-05-12 03:03:56 +0000940void SkGPipeCanvas::writePaint(const SkPaint& paint) {
941 SkPaint& base = fPaint;
reed@google.combb6992a2011-04-26 17:41:56 +0000942 uint32_t storage[32];
943 uint32_t* ptr = storage;
reed@google.combb6992a2011-04-26 17:41:56 +0000944
945 if (base.getFlags() != paint.getFlags()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000946 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
reed@google.comf5842f72011-05-04 18:30:04 +0000947 base.setFlags(paint.getFlags());
reed@google.combb6992a2011-04-26 17:41:56 +0000948 }
949 if (base.getColor() != paint.getColor()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000950 *ptr++ = PaintOp_packOp(kColor_PaintOp);
951 *ptr++ = paint.getColor();
reed@google.comf5842f72011-05-04 18:30:04 +0000952 base.setColor(paint.getColor());
reed@google.combb6992a2011-04-26 17:41:56 +0000953 }
954 if (base.getStyle() != paint.getStyle()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000955 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
reed@google.comf5842f72011-05-04 18:30:04 +0000956 base.setStyle(paint.getStyle());
reed@google.combb6992a2011-04-26 17:41:56 +0000957 }
958 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000959 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
reed@google.comf5842f72011-05-04 18:30:04 +0000960 base.setStrokeJoin(paint.getStrokeJoin());
reed@google.combb6992a2011-04-26 17:41:56 +0000961 }
962 if (base.getStrokeCap() != paint.getStrokeCap()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000963 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
reed@google.comf5842f72011-05-04 18:30:04 +0000964 base.setStrokeCap(paint.getStrokeCap());
reed@google.combb6992a2011-04-26 17:41:56 +0000965 }
966 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000967 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
968 *ptr++ = castToU32(paint.getStrokeWidth());
reed@google.comf5842f72011-05-04 18:30:04 +0000969 base.setStrokeWidth(paint.getStrokeWidth());
reed@google.combb6992a2011-04-26 17:41:56 +0000970 }
971 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000972 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
973 *ptr++ = castToU32(paint.getStrokeMiter());
reed@google.comf5842f72011-05-04 18:30:04 +0000974 base.setStrokeMiter(paint.getStrokeMiter());
reed@google.combb6992a2011-04-26 17:41:56 +0000975 }
976 if (base.getTextEncoding() != paint.getTextEncoding()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000977 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
reed@google.comf5842f72011-05-04 18:30:04 +0000978 base.setTextEncoding(paint.getTextEncoding());
reed@google.combb6992a2011-04-26 17:41:56 +0000979 }
980 if (base.getHinting() != paint.getHinting()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000981 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
reed@google.comf5842f72011-05-04 18:30:04 +0000982 base.setHinting(paint.getHinting());
reed@google.combb6992a2011-04-26 17:41:56 +0000983 }
984 if (base.getTextAlign() != paint.getTextAlign()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000985 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
reed@google.comf5842f72011-05-04 18:30:04 +0000986 base.setTextAlign(paint.getTextAlign());
reed@google.combb6992a2011-04-26 17:41:56 +0000987 }
988 if (base.getTextSize() != paint.getTextSize()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000989 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
990 *ptr++ = castToU32(paint.getTextSize());
reed@google.comf5842f72011-05-04 18:30:04 +0000991 base.setTextSize(paint.getTextSize());
reed@google.combb6992a2011-04-26 17:41:56 +0000992 }
993 if (base.getTextScaleX() != paint.getTextScaleX()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000994 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
995 *ptr++ = castToU32(paint.getTextScaleX());
reed@google.comf5842f72011-05-04 18:30:04 +0000996 base.setTextScaleX(paint.getTextScaleX());
reed@google.combb6992a2011-04-26 17:41:56 +0000997 }
998 if (base.getTextSkewX() != paint.getTextSkewX()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000999 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
1000 *ptr++ = castToU32(paint.getTextSkewX());
reed@google.comf5842f72011-05-04 18:30:04 +00001001 base.setTextSkewX(paint.getTextSkewX());
1002 }
1003
1004 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
1005 uint32_t id = this->getTypefaceID(paint.getTypeface());
reed@google.comf5842f72011-05-04 18:30:04 +00001006 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
1007 base.setTypeface(paint.getTypeface());
reed@google.combb6992a2011-04-26 17:41:56 +00001008 }
reed@google.combb6992a2011-04-26 17:41:56 +00001009
reed@google.comb55d1182011-05-11 00:42:04 +00001010 for (int i = 0; i < kCount_PaintFlats; i++) {
1011 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i);
1012 SkASSERT(index >= 0 && index <= fFlatArray.count());
1013 if (index != fCurrFlatIndex[i]) {
reed@google.comb55d1182011-05-11 00:42:04 +00001014 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index);
1015 fCurrFlatIndex[i] = index;
1016 }
1017 }
1018
reed@google.comacd471f2011-05-03 21:26:46 +00001019 size_t size = (char*)ptr - (char*)storage;
1020 if (size && this->needOpBytes(size)) {
reed@google.comb55d1182011-05-11 00:42:04 +00001021 this->writeOp(kPaintOp_DrawOp, 0, size);
reed@google.comb55d1182011-05-11 00:42:04 +00001022 fWriter.write(storage, size);
reed@google.combb6992a2011-04-26 17:41:56 +00001023 for (size_t i = 0; i < size/4; i++) {
reed@google.comb55d1182011-05-11 00:42:04 +00001024// SkDebugf("[%d] %08X\n", i, storage[i]);
reed@google.combb6992a2011-04-26 17:41:56 +00001025 }
1026 }
reed@google.combb6992a2011-04-26 17:41:56 +00001027}
1028
1029///////////////////////////////////////////////////////////////////////////////
1030
1031#include "SkGPipe.h"
1032
reed@google.comacd471f2011-05-03 21:26:46 +00001033SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
reed@google.combb6992a2011-04-26 17:41:56 +00001034 fCanvas = NULL;
1035}
1036
1037SkGPipeWriter::~SkGPipeWriter() {
reed@google.comacd471f2011-05-03 21:26:46 +00001038 this->endRecording();
reed@google.combb6992a2011-04-26 17:41:56 +00001039 SkSafeUnref(fCanvas);
1040}
1041
scroggo@google.com565254b2012-06-28 15:41:32 +00001042SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags) {
reed@google.combb6992a2011-04-26 17:41:56 +00001043 if (NULL == fCanvas) {
reed@google.comacd471f2011-05-03 21:26:46 +00001044 fWriter.reset(NULL, 0);
reed@google.comdde09562011-05-23 12:21:05 +00001045 fFactorySet.reset();
1046 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter,
1047 (flags & kCrossProcess_Flag) ?
scroggo@google.com565254b2012-06-28 15:41:32 +00001048 &fFactorySet : NULL, flags));
reed@google.combb6992a2011-04-26 17:41:56 +00001049 }
1050 return fCanvas;
1051}
1052
1053void SkGPipeWriter::endRecording() {
1054 if (fCanvas) {
1055 fCanvas->finish();
1056 fCanvas->unref();
1057 fCanvas = NULL;
1058 }
1059}
1060