blob: b06d40e8d188d8b1ec629d83fd81e871f1571cfe [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.comacd471f2011-05-03 21:26:46 +000015#include "SkGPipe.h"
reed@google.combb6992a2011-04-26 17:41:56 +000016#include "SkGPipePriv.h"
scroggo@google.com16d1d0b2012-05-02 19:09:40 +000017#include "SkImageFilter.h"
reed@google.comf5842f72011-05-04 18:30:04 +000018#include "SkStream.h"
reed@google.comb55d1182011-05-11 00:42:04 +000019#include "SkTSearch.h"
reed@google.comf5842f72011-05-04 18:30:04 +000020#include "SkTypeface.h"
reed@google.combb6992a2011-04-26 17:41:56 +000021#include "SkWriter32.h"
reed@google.comb55d1182011-05-11 00:42:04 +000022#include "SkColorFilter.h"
reed@google.com0faac1e2011-05-11 05:58:58 +000023#include "SkDrawLooper.h"
reed@google.comb55d1182011-05-11 00:42:04 +000024#include "SkMaskFilter.h"
25#include "SkRasterizer.h"
26#include "SkShader.h"
djsollen@google.com2b2ede32012-04-12 13:24:04 +000027#include "SkOrderedWriteBuffer.h"
reed@google.comb55d1182011-05-11 00:42:04 +000028
29static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
30 SkASSERT(paintFlat < kCount_PaintFlats);
31 switch (paintFlat) {
32 case kColorFilter_PaintFlat: return paint.getColorFilter();
reed@google.com0faac1e2011-05-11 05:58:58 +000033 case kDrawLooper_PaintFlat: return paint.getLooper();
reed@google.comb55d1182011-05-11 00:42:04 +000034 case kMaskFilter_PaintFlat: return paint.getMaskFilter();
35 case kPathEffect_PaintFlat: return paint.getPathEffect();
36 case kRasterizer_PaintFlat: return paint.getRasterizer();
37 case kShader_PaintFlat: return paint.getShader();
scroggo@google.com16d1d0b2012-05-02 19:09:40 +000038 case kImageFilter_PaintFlat: return paint.getImageFilter();
reed@google.comb55d1182011-05-11 00:42:04 +000039 case kXfermode_PaintFlat: return paint.getXfermode();
40 }
tomhudson@google.com0c00f212011-12-28 14:59:50 +000041 SkDEBUGFAIL("never gets here");
reed@google.comb55d1182011-05-11 00:42:04 +000042 return NULL;
43}
reed@google.combb6992a2011-04-26 17:41:56 +000044
reed@google.comacd471f2011-05-03 21:26:46 +000045static size_t estimateFlattenSize(const SkPath& path) {
46 int n = path.countPoints();
47 size_t bytes = 3 * sizeof(int32_t);
48 bytes += n * sizeof(SkPoint);
49 bytes += SkAlign4(n + 2); // verbs: add 2 for move/close extras
50
51#ifdef SK_DEBUG
52 {
53 SkWriter32 writer(1024);
54 path.flatten(writer);
55 SkASSERT(writer.size() <= bytes);
56 }
57#endif
58 return bytes;
59}
60
reed@google.comf5842f72011-05-04 18:30:04 +000061static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
62 SkASSERT(typeface);
63 SkDynamicMemoryWStream stream;
64 typeface->serialize(&stream);
65 size_t size = stream.getOffset();
66 if (writer) {
67 writer->write32(size);
reed@google.com8a85d0c2011-06-24 19:12:12 +000068 SkAutoDataUnref data(stream.copyToData());
69 writer->write(data.data(), size);
reed@google.comf5842f72011-05-04 18:30:04 +000070 }
71 return 4 + size;
72}
73
reed@google.combb6992a2011-04-26 17:41:56 +000074///////////////////////////////////////////////////////////////////////////////
75
76class SkGPipeCanvas : public SkCanvas {
77public:
reed@google.comdde09562011-05-23 12:21:05 +000078 SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*);
reed@google.combb6992a2011-04-26 17:41:56 +000079 virtual ~SkGPipeCanvas();
80
81 void finish() {
82 if (!fDone) {
reed@google.comdbccc882011-07-08 18:53:39 +000083 if (this->needOpBytes()) {
84 this->writeOp(kDone_DrawOp);
85 this->doNotify();
86 }
reed@google.combb6992a2011-04-26 17:41:56 +000087 fDone = true;
88 }
89 }
90
91 // overrides from SkCanvas
scroggo@google.com3b45cd52012-04-18 13:57:47 +000092 virtual int save(SaveFlags) SK_OVERRIDE;
93 virtual int saveLayer(const SkRect* bounds, const SkPaint*,
94 SaveFlags) SK_OVERRIDE;
95 virtual void restore() SK_OVERRIDE;
96 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
97 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
98 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
99 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
100 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
101 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
102 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
103 bool doAntiAlias = false) SK_OVERRIDE;
104 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
105 bool doAntiAlias = false) SK_OVERRIDE;
106 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) SK_OVERRIDE;
107 virtual void clear(SkColor) SK_OVERRIDE;
108 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000109 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000110 const SkPaint&) SK_OVERRIDE;
111 virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE;
112 virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000113 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000114 const SkPaint*) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000115 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000116 const SkRect& dst, const SkPaint*) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000117 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000118 const SkPaint*) SK_OVERRIDE;
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000119 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
120 const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000121 virtual void drawSprite(const SkBitmap&, int left, int top,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000122 const SkPaint*) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000123 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000124 SkScalar y, const SkPaint&) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000125 virtual void drawPosText(const void* text, size_t byteLength,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000126 const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000127 virtual void drawPosTextH(const void* text, size_t byteLength,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000128 const SkScalar xpos[], SkScalar constY,
129 const SkPaint&) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000130 virtual void drawTextOnPath(const void* text, size_t byteLength,
131 const SkPath& path, const SkMatrix* matrix,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000132 const SkPaint&) SK_OVERRIDE;
133 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000134 virtual void drawVertices(VertexMode, int vertexCount,
135 const SkPoint vertices[], const SkPoint texs[],
136 const SkColor colors[], SkXfermode*,
137 const uint16_t indices[], int indexCount,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000138 const SkPaint&) SK_OVERRIDE;
139 virtual void drawData(const void*, size_t) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000140
141private:
reed@google.comdde09562011-05-23 12:21:05 +0000142 SkFactorySet* fFactorySet; // optional, only used if cross-process
reed@google.comacd471f2011-05-03 21:26:46 +0000143 SkGPipeController* fController;
reed@google.combb6992a2011-04-26 17:41:56 +0000144 SkWriter32& fWriter;
reed@google.comacd471f2011-05-03 21:26:46 +0000145 size_t fBlockSize; // amount allocated for writer
146 size_t fBytesNotified;
reed@google.combb6992a2011-04-26 17:41:56 +0000147 bool fDone;
148
reed@google.comf5842f72011-05-04 18:30:04 +0000149 SkRefCntSet fTypefaceSet;
150
151 uint32_t getTypefaceID(SkTypeface*);
152
reed@google.comacd471f2011-05-03 21:26:46 +0000153 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
reed@google.combb6992a2011-04-26 17:41:56 +0000154 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
155 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000156
reed@google.comacd471f2011-05-03 21:26:46 +0000157 inline void writeOp(DrawOps op) {
reed@google.combb6992a2011-04-26 17:41:56 +0000158 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
159 }
reed@google.comacd471f2011-05-03 21:26:46 +0000160
161 bool needOpBytes(size_t size = 0);
162
163 inline void doNotify() {
164 if (!fDone) {
165 size_t bytes = fWriter.size() - fBytesNotified;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000166 if (bytes > 0) {
167 fController->notifyWritten(bytes);
168 fBytesNotified += bytes;
169 }
reed@google.comacd471f2011-05-03 21:26:46 +0000170 }
171 }
reed@google.comb55d1182011-05-11 00:42:04 +0000172
173 struct FlatData {
174 uint32_t fIndex; // always > 0
175 uint32_t fSize;
176
177 void* data() { return (char*)this + sizeof(*this); }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000178
reed@google.comb55d1182011-05-11 00:42:04 +0000179 static int Compare(const FlatData* a, const FlatData* b) {
180 return memcmp(&a->fSize, &b->fSize, a->fSize + sizeof(a->fSize));
181 }
182 };
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000183
184 SkTDArray<FlatData*> fBitmapArray;
185 int flattenToIndex(const SkBitmap&);
186
reed@google.comb55d1182011-05-11 00:42:04 +0000187 SkTDArray<FlatData*> fFlatArray;
188 int fCurrFlatIndex[kCount_PaintFlats];
189 int flattenToIndex(SkFlattenable* obj, PaintFlats);
190
reed@google.com31891582011-05-12 03:03:56 +0000191 SkPaint fPaint;
192 void writePaint(const SkPaint&);
reed@google.combb6992a2011-04-26 17:41:56 +0000193
reed@google.comacd471f2011-05-03 21:26:46 +0000194 class AutoPipeNotify {
195 public:
196 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
197 ~AutoPipeNotify() { fCanvas->doNotify(); }
198 private:
199 SkGPipeCanvas* fCanvas;
200 };
201 friend class AutoPipeNotify;
202
reed@google.combb6992a2011-04-26 17:41:56 +0000203 typedef SkCanvas INHERITED;
204};
205
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000206int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) {
207 SkOrderedWriteBuffer tmpWriter(1024);
208 // FIXME: Rather than forcing CrossProcess, we should create an SkRefCntSet
209 // so that we can store a pointer to a bitmap's pixels during flattening.
210 tmpWriter.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
211 bitmap.flatten(tmpWriter);
212
213 size_t len = tmpWriter.size();
214 size_t allocSize = len + sizeof(FlatData);
215
216 SkAutoSMalloc<1024> storage(allocSize);
217 FlatData* flat = (FlatData*)storage.get();
218 flat->fSize = len;
219 tmpWriter.flatten(flat->data());
220
221 int index = SkTSearch<FlatData>((const FlatData**)fBitmapArray.begin(),
222 fBitmapArray.count(), flat, sizeof(flat),
223 &FlatData::Compare);
224 if (index < 0) {
225 index = ~index;
226 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
227 memcpy(copy, flat, allocSize);
228 // For bitmaps, we can use zero based indices, since we will never ask
229 // for a NULL bitmap (unlike with paint flattenables).
230 copy->fIndex = fBitmapArray.count();
231 *fBitmapArray.insert(index) = copy;
232 if (this->needOpBytes(len + sizeof(uint32_t))) {
233 this->writeOp(kDef_Bitmap_DrawOp, 0, copy->fIndex);
234 fWriter.write32(len);
235 fWriter.write(copy->data(), len);
236 }
237 }
238 return fBitmapArray[index]->fIndex;
239}
240
reed@google.comb55d1182011-05-11 00:42:04 +0000241// return 0 for NULL (or unflattenable obj), or index-base-1
242int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
243 if (NULL == obj) {
244 return 0;
245 }
reed@google.comb55d1182011-05-11 00:42:04 +0000246
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000247 SkOrderedWriteBuffer tmpWriter(1024);
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000248
249 // Needs to be cross process so a bitmap shader will be preserved
250 // FIXME: Rather than forcing CrossProcess, we should create an SkRefCntSet
251 // so that we can store a pointer to a bitmap's pixels during flattening.
252 tmpWriter.setFlags((SkFlattenableWriteBuffer::Flags)
253 (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
254 | SkFlattenableWriteBuffer::kCrossProcess_Flag));
reed@google.comdde09562011-05-23 12:21:05 +0000255 tmpWriter.setFactoryRecorder(fFactorySet);
256
reed@google.comb55d1182011-05-11 00:42:04 +0000257 tmpWriter.writeFlattenable(obj);
258 size_t len = tmpWriter.size();
259 size_t allocSize = len + sizeof(FlatData);
260
261 SkAutoSMalloc<1024> storage(allocSize);
262 FlatData* flat = (FlatData*)storage.get();
263 flat->fSize = len;
264 tmpWriter.flatten(flat->data());
265
266 int index = SkTSearch<FlatData>((const FlatData**)fFlatArray.begin(),
267 fFlatArray.count(), flat, sizeof(flat),
268 &FlatData::Compare);
269 if (index < 0) {
270 index = ~index;
271 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
272 memcpy(copy, flat, allocSize);
273 *fFlatArray.insert(index) = copy;
274 // call this after the insert, so that count() will have been grown
275 copy->fIndex = fFlatArray.count();
276// SkDebugf("--- add flattenable[%d] size=%d index=%d\n", paintflat, len, copy->fIndex);
277
278 if (this->needOpBytes(len)) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000279 this->writeOp(kDef_Flattenable_DrawOp, paintflat, copy->fIndex);
reed@google.comb55d1182011-05-11 00:42:04 +0000280 fWriter.write(copy->data(), len);
281 }
282 }
283 return fFlatArray[index]->fIndex;
284}
285
reed@google.combb6992a2011-04-26 17:41:56 +0000286///////////////////////////////////////////////////////////////////////////////
287
reed@google.comacd471f2011-05-03 21:26:46 +0000288#define MIN_BLOCK_SIZE (16 * 1024)
reed@google.combb6992a2011-04-26 17:41:56 +0000289
reed@google.comacd471f2011-05-03 21:26:46 +0000290SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
reed@google.comdde09562011-05-23 12:21:05 +0000291 SkWriter32* writer, SkFactorySet* fset)
reed@google.com67908f22011-06-27 14:47:50 +0000292 : fWriter(*writer) {
293 fFactorySet = fset;
reed@google.comacd471f2011-05-03 21:26:46 +0000294 fController = controller;
reed@google.combb6992a2011-04-26 17:41:56 +0000295 fDone = false;
reed@google.comacd471f2011-05-03 21:26:46 +0000296 fBlockSize = 0; // need first block from controller
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000297 fBytesNotified = 0;
reed@google.comb55d1182011-05-11 00:42:04 +0000298 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
reed@google.comacd471f2011-05-03 21:26:46 +0000299
reed@google.combb6793b2011-05-05 15:18:15 +0000300 // we need a device to limit our clip
301 // should the caller give us the bounds?
yangsu@google.com06b4da162011-06-17 15:04:40 +0000302 // We don't allocate pixels for the bitmap
reed@google.combb6793b2011-05-05 15:18:15 +0000303 SkBitmap bitmap;
304 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32767, 32767);
yangsu@google.com06b4da162011-06-17 15:04:40 +0000305 SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
reed@google.combb6793b2011-05-05 15:18:15 +0000306 this->setDevice(device)->unref();
reed@google.combb6992a2011-04-26 17:41:56 +0000307}
308
309SkGPipeCanvas::~SkGPipeCanvas() {
310 this->finish();
311
reed@google.comb55d1182011-05-11 00:42:04 +0000312 fFlatArray.freeAll();
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000313 fBitmapArray.freeAll();
reed@google.combb6992a2011-04-26 17:41:56 +0000314}
315
reed@google.comacd471f2011-05-03 21:26:46 +0000316bool SkGPipeCanvas::needOpBytes(size_t needed) {
317 if (fDone) {
318 return false;
319 }
320
321 needed += 4; // size of DrawOp atom
322 if (fWriter.size() + needed > fBlockSize) {
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000323 // Before we wipe out any data that has already been written, read it
324 // out.
325 this->doNotify();
326 size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed);
327 void* block = fController->requestBlock(blockSize, &fBlockSize);
reed@google.comacd471f2011-05-03 21:26:46 +0000328 if (NULL == block) {
329 fDone = true;
330 return false;
331 }
332 fWriter.reset(block, fBlockSize);
333 fBytesNotified = 0;
334 }
335 return true;
336}
337
reed@google.comf5842f72011-05-04 18:30:04 +0000338uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
339 uint32_t id = 0; // 0 means default/null typeface
340 if (face) {
341 id = fTypefaceSet.find(face);
342 if (0 == id) {
343 id = fTypefaceSet.add(face);
344 size_t size = writeTypeface(NULL, face);
345 if (this->needOpBytes(size)) {
reed@google.combb6793b2011-05-05 15:18:15 +0000346 this->writeOp(kDef_Typeface_DrawOp);
reed@google.comf5842f72011-05-04 18:30:04 +0000347 writeTypeface(&fWriter, face);
348 }
349 }
350 }
351 return id;
352}
353
reed@google.combb6992a2011-04-26 17:41:56 +0000354///////////////////////////////////////////////////////////////////////////////
355
reed@google.comacd471f2011-05-03 21:26:46 +0000356#define NOTIFY_SETUP(canvas) \
357 AutoPipeNotify apn(canvas)
358
reed@google.combb6992a2011-04-26 17:41:56 +0000359int SkGPipeCanvas::save(SaveFlags flags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000360 NOTIFY_SETUP(this);
361 if (this->needOpBytes()) {
362 this->writeOp(kSave_DrawOp, 0, flags);
363 }
reed@google.combb6992a2011-04-26 17:41:56 +0000364 return this->INHERITED::save(flags);
365}
366
367int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
368 SaveFlags saveFlags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000369 NOTIFY_SETUP(this);
370 size_t size = 0;
reed@google.combb6992a2011-04-26 17:41:56 +0000371 unsigned opFlags = 0;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000372
reed@google.combb6992a2011-04-26 17:41:56 +0000373 if (bounds) {
374 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000375 size += sizeof(SkRect);
reed@google.combb6992a2011-04-26 17:41:56 +0000376 }
377 if (paint) {
378 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
reed@google.com31891582011-05-12 03:03:56 +0000379 this->writePaint(*paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000380 }
381
reed@google.comacd471f2011-05-03 21:26:46 +0000382 if (this->needOpBytes(size)) {
383 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
384 if (bounds) {
385 fWriter.writeRect(*bounds);
386 }
reed@google.combb6992a2011-04-26 17:41:56 +0000387 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000388
reed@google.combb6992a2011-04-26 17:41:56 +0000389 // we just pass on the save, so we don't create a layer
390 return this->INHERITED::save(saveFlags);
391}
392
393void SkGPipeCanvas::restore() {
reed@google.comacd471f2011-05-03 21:26:46 +0000394 NOTIFY_SETUP(this);
395 if (this->needOpBytes()) {
396 this->writeOp(kRestore_DrawOp);
397 }
reed@google.combb6992a2011-04-26 17:41:56 +0000398 this->INHERITED::restore();
399}
400
401bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
402 if (dx || dy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000403 NOTIFY_SETUP(this);
404 if (this->needOpBytes(2 * sizeof(SkScalar))) {
405 this->writeOp(kTranslate_DrawOp);
406 fWriter.writeScalar(dx);
407 fWriter.writeScalar(dy);
408 }
reed@google.combb6992a2011-04-26 17:41:56 +0000409 }
410 return this->INHERITED::translate(dx, dy);
411}
412
413bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
414 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000415 NOTIFY_SETUP(this);
416 if (this->needOpBytes(2 * sizeof(SkScalar))) {
417 this->writeOp(kScale_DrawOp);
418 fWriter.writeScalar(sx);
419 fWriter.writeScalar(sy);
420 }
reed@google.combb6992a2011-04-26 17:41:56 +0000421 }
422 return this->INHERITED::scale(sx, sy);
423}
424
425bool SkGPipeCanvas::rotate(SkScalar degrees) {
426 if (degrees) {
reed@google.comacd471f2011-05-03 21:26:46 +0000427 NOTIFY_SETUP(this);
428 if (this->needOpBytes(sizeof(SkScalar))) {
429 this->writeOp(kRotate_DrawOp);
430 fWriter.writeScalar(degrees);
431 }
reed@google.combb6992a2011-04-26 17:41:56 +0000432 }
433 return this->INHERITED::rotate(degrees);
434}
435
436bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
437 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000438 NOTIFY_SETUP(this);
439 if (this->needOpBytes(2 * sizeof(SkScalar))) {
440 this->writeOp(kSkew_DrawOp);
441 fWriter.writeScalar(sx);
442 fWriter.writeScalar(sy);
443 }
reed@google.combb6992a2011-04-26 17:41:56 +0000444 }
445 return this->INHERITED::skew(sx, sy);
446}
447
448bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
449 if (!matrix.isIdentity()) {
reed@google.comacd471f2011-05-03 21:26:46 +0000450 NOTIFY_SETUP(this);
451 if (this->needOpBytes(matrix.flatten(NULL))) {
452 this->writeOp(kConcat_DrawOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000453 fWriter.writeMatrix(matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000454 }
reed@google.combb6992a2011-04-26 17:41:56 +0000455 }
456 return this->INHERITED::concat(matrix);
457}
458
459void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
reed@google.comacd471f2011-05-03 21:26:46 +0000460 NOTIFY_SETUP(this);
461 if (this->needOpBytes(matrix.flatten(NULL))) {
462 this->writeOp(kSetMatrix_DrawOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000463 fWriter.writeMatrix(matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000464 }
reed@google.combb6992a2011-04-26 17:41:56 +0000465 this->INHERITED::setMatrix(matrix);
466}
467
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000468bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp,
469 bool doAntiAlias) {
reed@google.comacd471f2011-05-03 21:26:46 +0000470 NOTIFY_SETUP(this);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000471 if (this->needOpBytes(sizeof(SkRect)) + sizeof(bool)) {
reed@google.comacd471f2011-05-03 21:26:46 +0000472 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
473 fWriter.writeRect(rect);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000474 fWriter.writeBool(doAntiAlias);
reed@google.comacd471f2011-05-03 21:26:46 +0000475 }
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000476 return this->INHERITED::clipRect(rect, rgnOp, doAntiAlias);
reed@google.combb6992a2011-04-26 17:41:56 +0000477}
478
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000479bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp,
480 bool doAntiAlias) {
reed@google.comacd471f2011-05-03 21:26:46 +0000481 NOTIFY_SETUP(this);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000482 if (this->needOpBytes(estimateFlattenSize(path)) + sizeof(bool)) {
reed@google.comacd471f2011-05-03 21:26:46 +0000483 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
484 path.flatten(fWriter);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000485 fWriter.writeBool(doAntiAlias);
reed@google.comacd471f2011-05-03 21:26:46 +0000486 }
reed@google.combb6992a2011-04-26 17:41:56 +0000487 // we just pass on the bounds of the path
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000488 return this->INHERITED::clipRect(path.getBounds(), rgnOp, doAntiAlias);
reed@google.combb6992a2011-04-26 17:41:56 +0000489}
490
491bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000492 NOTIFY_SETUP(this);
493 if (this->needOpBytes(region.flatten(NULL))) {
494 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000495 fWriter.writeRegion(region);
reed@google.comacd471f2011-05-03 21:26:46 +0000496 }
reed@google.combb6992a2011-04-26 17:41:56 +0000497 return this->INHERITED::clipRegion(region, rgnOp);
498}
499
500///////////////////////////////////////////////////////////////////////////////
501
502void SkGPipeCanvas::clear(SkColor color) {
reed@google.comacd471f2011-05-03 21:26:46 +0000503 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000504 unsigned flags = 0;
505 if (color) {
506 flags |= kClear_HasColor_DrawOpFlag;
507 }
reed@google.comacd471f2011-05-03 21:26:46 +0000508 if (this->needOpBytes(sizeof(SkColor))) {
509 this->writeOp(kDrawClear_DrawOp, flags, 0);
510 if (color) {
511 fWriter.write32(color);
512 }
reed@google.combb6992a2011-04-26 17:41:56 +0000513 }
514}
515
516void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000517 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000518 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000519 if (this->needOpBytes()) {
reed@google.com31891582011-05-12 03:03:56 +0000520 this->writeOp(kDrawPaint_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000521 }
reed@google.combb6992a2011-04-26 17:41:56 +0000522}
523
524void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
525 const SkPoint pts[], const SkPaint& paint) {
526 if (count) {
reed@google.comacd471f2011-05-03 21:26:46 +0000527 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000528 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000529 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000530 this->writeOp(kDrawPoints_DrawOp, mode, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000531 fWriter.write32(count);
532 fWriter.write(pts, count * sizeof(SkPoint));
533 }
reed@google.combb6992a2011-04-26 17:41:56 +0000534 }
535}
536
537void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000538 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000539 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000540 if (this->needOpBytes(sizeof(SkRect))) {
reed@google.com31891582011-05-12 03:03:56 +0000541 this->writeOp(kDrawRect_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000542 fWriter.writeRect(rect);
543 }
reed@google.combb6992a2011-04-26 17:41:56 +0000544}
545
546void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000547 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000548 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000549 if (this->needOpBytes(estimateFlattenSize(path))) {
reed@google.com31891582011-05-12 03:03:56 +0000550 this->writeOp(kDrawPath_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000551 path.flatten(fWriter);
552 }
reed@google.combb6992a2011-04-26 17:41:56 +0000553}
554
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000555void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
556 const SkPaint* paint) {
557 // This is the brute-force solution
558 // TODO: add the notion of a shared, counted for large immutable resources
559 NOTIFY_SETUP(this);
560 if (paint) {
561 this->writePaint(*paint);
562 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000563
564 int bitmapIndex = this->flattenToIndex(bm);
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000565
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000566 if (this->needOpBytes(sizeof(SkScalar) * 2 + sizeof(bool))) {
567 this->writeOp(kDrawBitmap_DrawOp, 0, bitmapIndex);
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000568 fWriter.writeBool(paint != NULL);
569 fWriter.writeScalar(left);
570 fWriter.writeScalar(top);
571 }
reed@google.combb6992a2011-04-26 17:41:56 +0000572}
573
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000574void SkGPipeCanvas::drawBitmapRect(const SkBitmap& bm, const SkIRect* src,
575 const SkRect& dst, const SkPaint* paint) {
576 NOTIFY_SETUP(this);
577 if (paint) {
578 this->writePaint(*paint);
579 }
580
581 int bitmapIndex = this->flattenToIndex(bm);
582
583 size_t opBytesNeeded = sizeof(SkRect) + sizeof(bool) * 2;
584 bool hasSrc = src != NULL;
585 if (hasSrc) {
586 opBytesNeeded += sizeof(int32_t) * 4;
587 }
588 if (this->needOpBytes(opBytesNeeded)) {
589 this->writeOp(kDrawBitmapRect_DrawOp, 0, bitmapIndex);
590 fWriter.writeBool(paint != NULL);
591 fWriter.writeBool(hasSrc);
592 if (hasSrc) {
593 fWriter.write32(src->fLeft);
594 fWriter.write32(src->fTop);
595 fWriter.write32(src->fRight);
596 fWriter.write32(src->fBottom);
597 }
598 fWriter.writeRect(dst);
599 }
reed@google.combb6992a2011-04-26 17:41:56 +0000600}
601
602void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
603 const SkPaint*) {
604 UNIMPLEMENTED
605}
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000606
607void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000608 const SkRect& dst, const SkPaint* paint) {
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000609 NOTIFY_SETUP(this);
610 if (paint) {
611 this->writePaint(*paint);
612 }
613 int bitmapIndex = this->flattenToIndex(bm);
614
615 if (this->needOpBytes(sizeof(int32_t) * 4 + sizeof(bool)
616 + sizeof(SkRect))) {
617 this->writeOp(kDrawBitmapNine_DrawOp, 0, bitmapIndex);
618 fWriter.writeBool(paint != NULL);
619 fWriter.write32(center.fLeft);
620 fWriter.write32(center.fTop);
621 fWriter.write32(center.fRight);
622 fWriter.write32(center.fBottom);
623 fWriter.writeRect(dst);
624 }
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000625}
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000626
627void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
628 const SkPaint* paint) {
629 NOTIFY_SETUP(this);
630 if (paint) {
631 this->writePaint(*paint);
632 }
633 int bitmapIndex = this->flattenToIndex(bm);
634
635 if (this->needOpBytes(sizeof(int32_t) * 2 + sizeof(bool))) {
636 this->writeOp(kDrawSprite_DrawOp, 0, bitmapIndex);
637 fWriter.writeBool(paint != NULL);
638 fWriter.write32(left);
639 fWriter.write32(top);
640 }
reed@google.combb6992a2011-04-26 17:41:56 +0000641}
642
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000643void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
reed@google.combb6992a2011-04-26 17:41:56 +0000644 SkScalar y, const SkPaint& paint) {
645 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000646 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000647 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000648 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
reed@google.com31891582011-05-12 03:03:56 +0000649 this->writeOp(kDrawText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000650 fWriter.write32(byteLength);
651 fWriter.writePad(text, byteLength);
652 fWriter.writeScalar(x);
653 fWriter.writeScalar(y);
654 }
reed@google.combb6992a2011-04-26 17:41:56 +0000655 }
656}
657
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000658void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
reed@google.combb6992a2011-04-26 17:41:56 +0000659 const SkPoint pos[], const SkPaint& paint) {
660 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000661 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000662 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000663 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000664 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000665 this->writeOp(kDrawPosText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000666 fWriter.write32(byteLength);
667 fWriter.writePad(text, byteLength);
668 fWriter.write32(count);
669 fWriter.write(pos, count * sizeof(SkPoint));
670 }
reed@google.combb6992a2011-04-26 17:41:56 +0000671 }
672}
673
674void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
675 const SkScalar xpos[], SkScalar constY,
676 const SkPaint& paint) {
677 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000678 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000679 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000680 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000681 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
reed@google.com31891582011-05-12 03:03:56 +0000682 this->writeOp(kDrawPosTextH_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000683 fWriter.write32(byteLength);
684 fWriter.writePad(text, byteLength);
685 fWriter.write32(count);
686 fWriter.write(xpos, count * sizeof(SkScalar));
687 fWriter.writeScalar(constY);
688 }
reed@google.combb6992a2011-04-26 17:41:56 +0000689 }
690}
691
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000692void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
693 const SkPath& path, const SkMatrix* matrix,
reed@google.combb6992a2011-04-26 17:41:56 +0000694 const SkPaint& paint) {
695 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000696 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000697 unsigned flags = 0;
reed@google.comacd471f2011-05-03 21:26:46 +0000698 size_t size = 4 + SkAlign4(byteLength) + estimateFlattenSize(path);
reed@google.combb6992a2011-04-26 17:41:56 +0000699 if (matrix) {
700 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000701 size += matrix->flatten(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000702 }
reed@google.com31891582011-05-12 03:03:56 +0000703 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000704 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +0000705 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
reed@google.combb6992a2011-04-26 17:41:56 +0000706
reed@google.comacd471f2011-05-03 21:26:46 +0000707 fWriter.write32(byteLength);
708 fWriter.writePad(text, byteLength);
reed@google.combb6992a2011-04-26 17:41:56 +0000709
reed@google.comacd471f2011-05-03 21:26:46 +0000710 path.flatten(fWriter);
711 if (matrix) {
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000712 fWriter.writeMatrix(*matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000713 }
reed@google.combb6992a2011-04-26 17:41:56 +0000714 }
715 }
716}
717
718void SkGPipeCanvas::drawPicture(SkPicture& picture) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000719 // we want to playback the picture into individual draw calls
720 this->INHERITED::drawPicture(picture);
reed@google.combb6992a2011-04-26 17:41:56 +0000721}
722
reed@google.combb6992a2011-04-26 17:41:56 +0000723void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
724 const SkPoint vertices[], const SkPoint texs[],
725 const SkColor colors[], SkXfermode*,
726 const uint16_t indices[], int indexCount,
727 const SkPaint& paint) {
728 if (0 == vertexCount) {
729 return;
730 }
731
reed@google.comacd471f2011-05-03 21:26:46 +0000732 NOTIFY_SETUP(this);
733 size_t size = 4 + vertexCount * sizeof(SkPoint);
reed@google.com31891582011-05-12 03:03:56 +0000734 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000735 unsigned flags = 0;
736 if (texs) {
737 flags |= kDrawVertices_HasTexs_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000738 size += vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000739 }
740 if (colors) {
741 flags |= kDrawVertices_HasColors_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000742 size += vertexCount * sizeof(SkColor);
reed@google.combb6992a2011-04-26 17:41:56 +0000743 }
744 if (indices && indexCount > 0) {
745 flags |= kDrawVertices_HasIndices_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000746 size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
reed@google.combb6992a2011-04-26 17:41:56 +0000747 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000748
reed@google.comacd471f2011-05-03 21:26:46 +0000749 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +0000750 this->writeOp(kDrawVertices_DrawOp, flags, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000751 fWriter.write32(mode);
752 fWriter.write32(vertexCount);
753 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
754 if (texs) {
755 fWriter.write(texs, vertexCount * sizeof(SkPoint));
756 }
757 if (colors) {
758 fWriter.write(colors, vertexCount * sizeof(SkColor));
759 }
reed@google.combb6992a2011-04-26 17:41:56 +0000760
reed@google.comacd471f2011-05-03 21:26:46 +0000761 // TODO: flatten xfermode
reed@google.combb6992a2011-04-26 17:41:56 +0000762
reed@google.comacd471f2011-05-03 21:26:46 +0000763 if (indices && indexCount > 0) {
764 fWriter.write32(indexCount);
765 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
766 }
reed@google.combb6992a2011-04-26 17:41:56 +0000767 }
768}
769
reed@google.comacd471f2011-05-03 21:26:46 +0000770void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
771 if (size && ptr) {
772 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000773 unsigned data = 0;
774 if (size < (1 << DRAWOPS_DATA_BITS)) {
775 data = (unsigned)size;
776 }
reed@google.comacd471f2011-05-03 21:26:46 +0000777 if (this->needOpBytes(4 + SkAlign4(size))) {
778 this->writeOp(kDrawData_DrawOp, 0, data);
779 if (0 == data) {
780 fWriter.write32(size);
781 }
reed@google.combb6793b2011-05-05 15:18:15 +0000782 fWriter.writePad(ptr, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000783 }
784 }
785}
786
787///////////////////////////////////////////////////////////////////////////////
788
789template <typename T> uint32_t castToU32(T value) {
790 union {
791 T fSrc;
792 uint32_t fDst;
793 } data;
794 data.fSrc = value;
795 return data.fDst;
796}
797
reed@google.com31891582011-05-12 03:03:56 +0000798void SkGPipeCanvas::writePaint(const SkPaint& paint) {
799 SkPaint& base = fPaint;
reed@google.combb6992a2011-04-26 17:41:56 +0000800 uint32_t storage[32];
801 uint32_t* ptr = storage;
reed@google.combb6992a2011-04-26 17:41:56 +0000802
803 if (base.getFlags() != paint.getFlags()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000804 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
reed@google.comf5842f72011-05-04 18:30:04 +0000805 base.setFlags(paint.getFlags());
reed@google.combb6992a2011-04-26 17:41:56 +0000806 }
807 if (base.getColor() != paint.getColor()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000808 *ptr++ = PaintOp_packOp(kColor_PaintOp);
809 *ptr++ = paint.getColor();
reed@google.comf5842f72011-05-04 18:30:04 +0000810 base.setColor(paint.getColor());
reed@google.combb6992a2011-04-26 17:41:56 +0000811 }
812 if (base.getStyle() != paint.getStyle()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000813 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
reed@google.comf5842f72011-05-04 18:30:04 +0000814 base.setStyle(paint.getStyle());
reed@google.combb6992a2011-04-26 17:41:56 +0000815 }
816 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000817 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
reed@google.comf5842f72011-05-04 18:30:04 +0000818 base.setStrokeJoin(paint.getStrokeJoin());
reed@google.combb6992a2011-04-26 17:41:56 +0000819 }
820 if (base.getStrokeCap() != paint.getStrokeCap()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000821 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
reed@google.comf5842f72011-05-04 18:30:04 +0000822 base.setStrokeCap(paint.getStrokeCap());
reed@google.combb6992a2011-04-26 17:41:56 +0000823 }
824 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000825 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
826 *ptr++ = castToU32(paint.getStrokeWidth());
reed@google.comf5842f72011-05-04 18:30:04 +0000827 base.setStrokeWidth(paint.getStrokeWidth());
reed@google.combb6992a2011-04-26 17:41:56 +0000828 }
829 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000830 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
831 *ptr++ = castToU32(paint.getStrokeMiter());
reed@google.comf5842f72011-05-04 18:30:04 +0000832 base.setStrokeMiter(paint.getStrokeMiter());
reed@google.combb6992a2011-04-26 17:41:56 +0000833 }
834 if (base.getTextEncoding() != paint.getTextEncoding()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000835 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
reed@google.comf5842f72011-05-04 18:30:04 +0000836 base.setTextEncoding(paint.getTextEncoding());
reed@google.combb6992a2011-04-26 17:41:56 +0000837 }
838 if (base.getHinting() != paint.getHinting()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000839 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
reed@google.comf5842f72011-05-04 18:30:04 +0000840 base.setHinting(paint.getHinting());
reed@google.combb6992a2011-04-26 17:41:56 +0000841 }
842 if (base.getTextAlign() != paint.getTextAlign()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000843 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
reed@google.comf5842f72011-05-04 18:30:04 +0000844 base.setTextAlign(paint.getTextAlign());
reed@google.combb6992a2011-04-26 17:41:56 +0000845 }
846 if (base.getTextSize() != paint.getTextSize()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000847 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
848 *ptr++ = castToU32(paint.getTextSize());
reed@google.comf5842f72011-05-04 18:30:04 +0000849 base.setTextSize(paint.getTextSize());
reed@google.combb6992a2011-04-26 17:41:56 +0000850 }
851 if (base.getTextScaleX() != paint.getTextScaleX()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000852 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
853 *ptr++ = castToU32(paint.getTextScaleX());
reed@google.comf5842f72011-05-04 18:30:04 +0000854 base.setTextScaleX(paint.getTextScaleX());
reed@google.combb6992a2011-04-26 17:41:56 +0000855 }
856 if (base.getTextSkewX() != paint.getTextSkewX()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000857 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
858 *ptr++ = castToU32(paint.getTextSkewX());
reed@google.comf5842f72011-05-04 18:30:04 +0000859 base.setTextSkewX(paint.getTextSkewX());
860 }
861
862 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
863 uint32_t id = this->getTypefaceID(paint.getTypeface());
reed@google.comf5842f72011-05-04 18:30:04 +0000864 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
865 base.setTypeface(paint.getTypeface());
reed@google.combb6992a2011-04-26 17:41:56 +0000866 }
reed@google.combb6992a2011-04-26 17:41:56 +0000867
reed@google.comb55d1182011-05-11 00:42:04 +0000868 for (int i = 0; i < kCount_PaintFlats; i++) {
869 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i);
870 SkASSERT(index >= 0 && index <= fFlatArray.count());
871 if (index != fCurrFlatIndex[i]) {
reed@google.comb55d1182011-05-11 00:42:04 +0000872 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index);
873 fCurrFlatIndex[i] = index;
874 }
875 }
876
reed@google.comacd471f2011-05-03 21:26:46 +0000877 size_t size = (char*)ptr - (char*)storage;
878 if (size && this->needOpBytes(size)) {
reed@google.comb55d1182011-05-11 00:42:04 +0000879 this->writeOp(kPaintOp_DrawOp, 0, size);
reed@google.comb55d1182011-05-11 00:42:04 +0000880 fWriter.write(storage, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000881 for (size_t i = 0; i < size/4; i++) {
reed@google.comb55d1182011-05-11 00:42:04 +0000882// SkDebugf("[%d] %08X\n", i, storage[i]);
reed@google.combb6992a2011-04-26 17:41:56 +0000883 }
884 }
reed@google.combb6992a2011-04-26 17:41:56 +0000885}
886
887///////////////////////////////////////////////////////////////////////////////
888
889#include "SkGPipe.h"
890
reed@google.comacd471f2011-05-03 21:26:46 +0000891SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
reed@google.combb6992a2011-04-26 17:41:56 +0000892 fCanvas = NULL;
893}
894
895SkGPipeWriter::~SkGPipeWriter() {
reed@google.comacd471f2011-05-03 21:26:46 +0000896 this->endRecording();
reed@google.combb6992a2011-04-26 17:41:56 +0000897 SkSafeUnref(fCanvas);
898}
899
reed@google.comdde09562011-05-23 12:21:05 +0000900SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller,
901 uint32_t flags) {
reed@google.combb6992a2011-04-26 17:41:56 +0000902 if (NULL == fCanvas) {
reed@google.comacd471f2011-05-03 21:26:46 +0000903 fWriter.reset(NULL, 0);
reed@google.comdde09562011-05-23 12:21:05 +0000904 fFactorySet.reset();
905 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter,
906 (flags & kCrossProcess_Flag) ?
907 &fFactorySet : NULL));
reed@google.combb6992a2011-04-26 17:41:56 +0000908 }
909 return fCanvas;
910}
911
912void SkGPipeWriter::endRecording() {
913 if (fCanvas) {
914 fCanvas->finish();
915 fCanvas->unref();
916 fCanvas = NULL;
917 }
918}
919