blob: 08c6f49a399f213c1dfa50885b9d3f8bd82f2661 [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.comacd471f2011-05-03 21:26:46 +000046static size_t estimateFlattenSize(const SkPath& path) {
47 int n = path.countPoints();
48 size_t bytes = 3 * sizeof(int32_t);
49 bytes += n * sizeof(SkPoint);
50 bytes += SkAlign4(n + 2); // verbs: add 2 for move/close extras
51
52#ifdef SK_DEBUG
53 {
54 SkWriter32 writer(1024);
55 path.flatten(writer);
56 SkASSERT(writer.size() <= bytes);
57 }
58#endif
59 return bytes;
60}
61
reed@google.comf5842f72011-05-04 18:30:04 +000062static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
63 SkASSERT(typeface);
64 SkDynamicMemoryWStream stream;
65 typeface->serialize(&stream);
66 size_t size = stream.getOffset();
67 if (writer) {
68 writer->write32(size);
reed@google.com8a85d0c2011-06-24 19:12:12 +000069 SkAutoDataUnref data(stream.copyToData());
70 writer->write(data.data(), size);
reed@google.comf5842f72011-05-04 18:30:04 +000071 }
72 return 4 + size;
73}
74
reed@google.combb6992a2011-04-26 17:41:56 +000075///////////////////////////////////////////////////////////////////////////////
76
77class SkGPipeCanvas : public SkCanvas {
78public:
reed@google.comdde09562011-05-23 12:21:05 +000079 SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*);
reed@google.combb6992a2011-04-26 17:41:56 +000080 virtual ~SkGPipeCanvas();
81
82 void finish() {
83 if (!fDone) {
reed@google.comdbccc882011-07-08 18:53:39 +000084 if (this->needOpBytes()) {
85 this->writeOp(kDone_DrawOp);
86 this->doNotify();
87 }
reed@google.combb6992a2011-04-26 17:41:56 +000088 fDone = true;
89 }
90 }
91
92 // overrides from SkCanvas
scroggo@google.com3b45cd52012-04-18 13:57:47 +000093 virtual int save(SaveFlags) SK_OVERRIDE;
94 virtual int saveLayer(const SkRect* bounds, const SkPaint*,
95 SaveFlags) SK_OVERRIDE;
96 virtual void restore() SK_OVERRIDE;
97 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
98 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
99 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
100 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
101 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
102 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
103 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
104 bool doAntiAlias = false) SK_OVERRIDE;
105 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
106 bool doAntiAlias = false) SK_OVERRIDE;
107 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) SK_OVERRIDE;
108 virtual void clear(SkColor) SK_OVERRIDE;
109 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000110 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000111 const SkPaint&) SK_OVERRIDE;
112 virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE;
113 virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000114 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000115 const SkPaint*) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000116 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000117 const SkRect& dst, const SkPaint*) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000118 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000119 const SkPaint*) SK_OVERRIDE;
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000120 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
121 const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000122 virtual void drawSprite(const SkBitmap&, int left, int top,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000123 const SkPaint*) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000124 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000125 SkScalar y, const SkPaint&) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000126 virtual void drawPosText(const void* text, size_t byteLength,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000127 const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000128 virtual void drawPosTextH(const void* text, size_t byteLength,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000129 const SkScalar xpos[], SkScalar constY,
130 const SkPaint&) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000131 virtual void drawTextOnPath(const void* text, size_t byteLength,
132 const SkPath& path, const SkMatrix* matrix,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000133 const SkPaint&) SK_OVERRIDE;
134 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000135 virtual void drawVertices(VertexMode, int vertexCount,
136 const SkPoint vertices[], const SkPoint texs[],
137 const SkColor colors[], SkXfermode*,
138 const uint16_t indices[], int indexCount,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000139 const SkPaint&) SK_OVERRIDE;
140 virtual void drawData(const void*, size_t) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000141
142private:
reed@google.comdde09562011-05-23 12:21:05 +0000143 SkFactorySet* fFactorySet; // optional, only used if cross-process
reed@google.comacd471f2011-05-03 21:26:46 +0000144 SkGPipeController* fController;
reed@google.combb6992a2011-04-26 17:41:56 +0000145 SkWriter32& fWriter;
reed@google.comacd471f2011-05-03 21:26:46 +0000146 size_t fBlockSize; // amount allocated for writer
147 size_t fBytesNotified;
reed@google.combb6992a2011-04-26 17:41:56 +0000148 bool fDone;
149
reed@google.comf5842f72011-05-04 18:30:04 +0000150 SkRefCntSet fTypefaceSet;
151
152 uint32_t getTypefaceID(SkTypeface*);
153
reed@google.comacd471f2011-05-03 21:26:46 +0000154 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
reed@google.combb6992a2011-04-26 17:41:56 +0000155 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
156 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000157
reed@google.comacd471f2011-05-03 21:26:46 +0000158 inline void writeOp(DrawOps op) {
reed@google.combb6992a2011-04-26 17:41:56 +0000159 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
160 }
reed@google.comacd471f2011-05-03 21:26:46 +0000161
162 bool needOpBytes(size_t size = 0);
163
164 inline void doNotify() {
165 if (!fDone) {
166 size_t bytes = fWriter.size() - fBytesNotified;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000167 if (bytes > 0) {
168 fController->notifyWritten(bytes);
169 fBytesNotified += bytes;
170 }
reed@google.comacd471f2011-05-03 21:26:46 +0000171 }
172 }
reed@google.comb55d1182011-05-11 00:42:04 +0000173
174 struct FlatData {
175 uint32_t fIndex; // always > 0
176 uint32_t fSize;
177
178 void* data() { return (char*)this + sizeof(*this); }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000179
reed@google.comb55d1182011-05-11 00:42:04 +0000180 static int Compare(const FlatData* a, const FlatData* b) {
181 return memcmp(&a->fSize, &b->fSize, a->fSize + sizeof(a->fSize));
182 }
183 };
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000184
185 SkTDArray<FlatData*> fBitmapArray;
186 int flattenToIndex(const SkBitmap&);
187
reed@google.comb55d1182011-05-11 00:42:04 +0000188 SkTDArray<FlatData*> fFlatArray;
189 int fCurrFlatIndex[kCount_PaintFlats];
190 int flattenToIndex(SkFlattenable* obj, PaintFlats);
191
reed@google.com31891582011-05-12 03:03:56 +0000192 SkPaint fPaint;
193 void writePaint(const SkPaint&);
reed@google.combb6992a2011-04-26 17:41:56 +0000194
reed@google.comacd471f2011-05-03 21:26:46 +0000195 class AutoPipeNotify {
196 public:
197 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
198 ~AutoPipeNotify() { fCanvas->doNotify(); }
199 private:
200 SkGPipeCanvas* fCanvas;
201 };
202 friend class AutoPipeNotify;
203
reed@google.combb6992a2011-04-26 17:41:56 +0000204 typedef SkCanvas INHERITED;
205};
206
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000207int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) {
208 SkOrderedWriteBuffer tmpWriter(1024);
209 // FIXME: Rather than forcing CrossProcess, we should create an SkRefCntSet
210 // so that we can store a pointer to a bitmap's pixels during flattening.
211 tmpWriter.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
212 bitmap.flatten(tmpWriter);
213
214 size_t len = tmpWriter.size();
215 size_t allocSize = len + sizeof(FlatData);
216
217 SkAutoSMalloc<1024> storage(allocSize);
218 FlatData* flat = (FlatData*)storage.get();
219 flat->fSize = len;
220 tmpWriter.flatten(flat->data());
221
222 int index = SkTSearch<FlatData>((const FlatData**)fBitmapArray.begin(),
223 fBitmapArray.count(), flat, sizeof(flat),
224 &FlatData::Compare);
225 if (index < 0) {
226 index = ~index;
227 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
228 memcpy(copy, flat, allocSize);
229 // For bitmaps, we can use zero based indices, since we will never ask
230 // for a NULL bitmap (unlike with paint flattenables).
231 copy->fIndex = fBitmapArray.count();
232 *fBitmapArray.insert(index) = copy;
233 if (this->needOpBytes(len + sizeof(uint32_t))) {
234 this->writeOp(kDef_Bitmap_DrawOp, 0, copy->fIndex);
235 fWriter.write32(len);
236 fWriter.write(copy->data(), len);
237 }
238 }
239 return fBitmapArray[index]->fIndex;
240}
241
reed@google.comb55d1182011-05-11 00:42:04 +0000242// return 0 for NULL (or unflattenable obj), or index-base-1
243int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
244 if (NULL == obj) {
245 return 0;
246 }
reed@google.comb55d1182011-05-11 00:42:04 +0000247
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000248 SkOrderedWriteBuffer tmpWriter(1024);
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000249
250 // Needs to be cross process so a bitmap shader will be preserved
251 // FIXME: Rather than forcing CrossProcess, we should create an SkRefCntSet
252 // so that we can store a pointer to a bitmap's pixels during flattening.
253 tmpWriter.setFlags((SkFlattenableWriteBuffer::Flags)
254 (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
255 | SkFlattenableWriteBuffer::kCrossProcess_Flag));
reed@google.comdde09562011-05-23 12:21:05 +0000256 tmpWriter.setFactoryRecorder(fFactorySet);
257
reed@google.comb55d1182011-05-11 00:42:04 +0000258 tmpWriter.writeFlattenable(obj);
259 size_t len = tmpWriter.size();
260 size_t allocSize = len + sizeof(FlatData);
261
262 SkAutoSMalloc<1024> storage(allocSize);
263 FlatData* flat = (FlatData*)storage.get();
264 flat->fSize = len;
265 tmpWriter.flatten(flat->data());
266
267 int index = SkTSearch<FlatData>((const FlatData**)fFlatArray.begin(),
268 fFlatArray.count(), flat, sizeof(flat),
269 &FlatData::Compare);
270 if (index < 0) {
271 index = ~index;
272 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
273 memcpy(copy, flat, allocSize);
274 *fFlatArray.insert(index) = copy;
275 // call this after the insert, so that count() will have been grown
276 copy->fIndex = fFlatArray.count();
277// SkDebugf("--- add flattenable[%d] size=%d index=%d\n", paintflat, len, copy->fIndex);
278
279 if (this->needOpBytes(len)) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000280 this->writeOp(kDef_Flattenable_DrawOp, paintflat, copy->fIndex);
reed@google.comb55d1182011-05-11 00:42:04 +0000281 fWriter.write(copy->data(), len);
282 }
283 }
284 return fFlatArray[index]->fIndex;
285}
286
reed@google.combb6992a2011-04-26 17:41:56 +0000287///////////////////////////////////////////////////////////////////////////////
288
reed@google.comacd471f2011-05-03 21:26:46 +0000289#define MIN_BLOCK_SIZE (16 * 1024)
reed@google.combb6992a2011-04-26 17:41:56 +0000290
reed@google.comacd471f2011-05-03 21:26:46 +0000291SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
reed@google.comdde09562011-05-23 12:21:05 +0000292 SkWriter32* writer, SkFactorySet* fset)
reed@google.com67908f22011-06-27 14:47:50 +0000293 : fWriter(*writer) {
294 fFactorySet = fset;
reed@google.comacd471f2011-05-03 21:26:46 +0000295 fController = controller;
reed@google.combb6992a2011-04-26 17:41:56 +0000296 fDone = false;
reed@google.comacd471f2011-05-03 21:26:46 +0000297 fBlockSize = 0; // need first block from controller
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000298 fBytesNotified = 0;
reed@google.comb55d1182011-05-11 00:42:04 +0000299 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
reed@google.comacd471f2011-05-03 21:26:46 +0000300
reed@google.combb6793b2011-05-05 15:18:15 +0000301 // we need a device to limit our clip
302 // should the caller give us the bounds?
yangsu@google.com06b4da162011-06-17 15:04:40 +0000303 // We don't allocate pixels for the bitmap
reed@google.combb6793b2011-05-05 15:18:15 +0000304 SkBitmap bitmap;
305 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32767, 32767);
yangsu@google.com06b4da162011-06-17 15:04:40 +0000306 SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
reed@google.combb6793b2011-05-05 15:18:15 +0000307 this->setDevice(device)->unref();
reed@google.combb6992a2011-04-26 17:41:56 +0000308}
309
310SkGPipeCanvas::~SkGPipeCanvas() {
311 this->finish();
312
reed@google.comb55d1182011-05-11 00:42:04 +0000313 fFlatArray.freeAll();
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000314 fBitmapArray.freeAll();
reed@google.combb6992a2011-04-26 17:41:56 +0000315}
316
reed@google.comacd471f2011-05-03 21:26:46 +0000317bool SkGPipeCanvas::needOpBytes(size_t needed) {
318 if (fDone) {
319 return false;
320 }
321
322 needed += 4; // size of DrawOp atom
323 if (fWriter.size() + needed > fBlockSize) {
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000324 // Before we wipe out any data that has already been written, read it
325 // out.
326 this->doNotify();
327 size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed);
328 void* block = fController->requestBlock(blockSize, &fBlockSize);
reed@google.comacd471f2011-05-03 21:26:46 +0000329 if (NULL == block) {
330 fDone = true;
331 return false;
332 }
333 fWriter.reset(block, fBlockSize);
334 fBytesNotified = 0;
335 }
336 return true;
337}
338
reed@google.comf5842f72011-05-04 18:30:04 +0000339uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
340 uint32_t id = 0; // 0 means default/null typeface
341 if (face) {
342 id = fTypefaceSet.find(face);
343 if (0 == id) {
344 id = fTypefaceSet.add(face);
345 size_t size = writeTypeface(NULL, face);
346 if (this->needOpBytes(size)) {
reed@google.combb6793b2011-05-05 15:18:15 +0000347 this->writeOp(kDef_Typeface_DrawOp);
reed@google.comf5842f72011-05-04 18:30:04 +0000348 writeTypeface(&fWriter, face);
349 }
350 }
351 }
352 return id;
353}
354
reed@google.combb6992a2011-04-26 17:41:56 +0000355///////////////////////////////////////////////////////////////////////////////
356
reed@google.comacd471f2011-05-03 21:26:46 +0000357#define NOTIFY_SETUP(canvas) \
358 AutoPipeNotify apn(canvas)
359
reed@google.combb6992a2011-04-26 17:41:56 +0000360int SkGPipeCanvas::save(SaveFlags flags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000361 NOTIFY_SETUP(this);
362 if (this->needOpBytes()) {
363 this->writeOp(kSave_DrawOp, 0, flags);
364 }
reed@google.combb6992a2011-04-26 17:41:56 +0000365 return this->INHERITED::save(flags);
366}
367
368int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
369 SaveFlags saveFlags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000370 NOTIFY_SETUP(this);
371 size_t size = 0;
reed@google.combb6992a2011-04-26 17:41:56 +0000372 unsigned opFlags = 0;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000373
reed@google.combb6992a2011-04-26 17:41:56 +0000374 if (bounds) {
375 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000376 size += sizeof(SkRect);
reed@google.combb6992a2011-04-26 17:41:56 +0000377 }
378 if (paint) {
379 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
reed@google.com31891582011-05-12 03:03:56 +0000380 this->writePaint(*paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000381 }
382
reed@google.comacd471f2011-05-03 21:26:46 +0000383 if (this->needOpBytes(size)) {
384 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
385 if (bounds) {
386 fWriter.writeRect(*bounds);
387 }
reed@google.combb6992a2011-04-26 17:41:56 +0000388 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000389
reed@google.combb6992a2011-04-26 17:41:56 +0000390 // we just pass on the save, so we don't create a layer
391 return this->INHERITED::save(saveFlags);
392}
393
394void SkGPipeCanvas::restore() {
reed@google.comacd471f2011-05-03 21:26:46 +0000395 NOTIFY_SETUP(this);
396 if (this->needOpBytes()) {
397 this->writeOp(kRestore_DrawOp);
398 }
reed@google.combb6992a2011-04-26 17:41:56 +0000399 this->INHERITED::restore();
400}
401
402bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
403 if (dx || dy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000404 NOTIFY_SETUP(this);
405 if (this->needOpBytes(2 * sizeof(SkScalar))) {
406 this->writeOp(kTranslate_DrawOp);
407 fWriter.writeScalar(dx);
408 fWriter.writeScalar(dy);
409 }
reed@google.combb6992a2011-04-26 17:41:56 +0000410 }
411 return this->INHERITED::translate(dx, dy);
412}
413
414bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
415 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000416 NOTIFY_SETUP(this);
417 if (this->needOpBytes(2 * sizeof(SkScalar))) {
418 this->writeOp(kScale_DrawOp);
419 fWriter.writeScalar(sx);
420 fWriter.writeScalar(sy);
421 }
reed@google.combb6992a2011-04-26 17:41:56 +0000422 }
423 return this->INHERITED::scale(sx, sy);
424}
425
426bool SkGPipeCanvas::rotate(SkScalar degrees) {
427 if (degrees) {
reed@google.comacd471f2011-05-03 21:26:46 +0000428 NOTIFY_SETUP(this);
429 if (this->needOpBytes(sizeof(SkScalar))) {
430 this->writeOp(kRotate_DrawOp);
431 fWriter.writeScalar(degrees);
432 }
reed@google.combb6992a2011-04-26 17:41:56 +0000433 }
434 return this->INHERITED::rotate(degrees);
435}
436
437bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
438 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000439 NOTIFY_SETUP(this);
440 if (this->needOpBytes(2 * sizeof(SkScalar))) {
441 this->writeOp(kSkew_DrawOp);
442 fWriter.writeScalar(sx);
443 fWriter.writeScalar(sy);
444 }
reed@google.combb6992a2011-04-26 17:41:56 +0000445 }
446 return this->INHERITED::skew(sx, sy);
447}
448
449bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
450 if (!matrix.isIdentity()) {
reed@google.comacd471f2011-05-03 21:26:46 +0000451 NOTIFY_SETUP(this);
452 if (this->needOpBytes(matrix.flatten(NULL))) {
453 this->writeOp(kConcat_DrawOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000454 fWriter.writeMatrix(matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000455 }
reed@google.combb6992a2011-04-26 17:41:56 +0000456 }
457 return this->INHERITED::concat(matrix);
458}
459
460void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
reed@google.comacd471f2011-05-03 21:26:46 +0000461 NOTIFY_SETUP(this);
462 if (this->needOpBytes(matrix.flatten(NULL))) {
463 this->writeOp(kSetMatrix_DrawOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000464 fWriter.writeMatrix(matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000465 }
reed@google.combb6992a2011-04-26 17:41:56 +0000466 this->INHERITED::setMatrix(matrix);
467}
468
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000469bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp,
470 bool doAntiAlias) {
reed@google.comacd471f2011-05-03 21:26:46 +0000471 NOTIFY_SETUP(this);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000472 if (this->needOpBytes(sizeof(SkRect)) + sizeof(bool)) {
reed@google.comacd471f2011-05-03 21:26:46 +0000473 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
474 fWriter.writeRect(rect);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000475 fWriter.writeBool(doAntiAlias);
reed@google.comacd471f2011-05-03 21:26:46 +0000476 }
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000477 return this->INHERITED::clipRect(rect, rgnOp, doAntiAlias);
reed@google.combb6992a2011-04-26 17:41:56 +0000478}
479
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000480bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp,
481 bool doAntiAlias) {
reed@google.comacd471f2011-05-03 21:26:46 +0000482 NOTIFY_SETUP(this);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000483 if (this->needOpBytes(estimateFlattenSize(path)) + sizeof(bool)) {
reed@google.comacd471f2011-05-03 21:26:46 +0000484 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
485 path.flatten(fWriter);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000486 fWriter.writeBool(doAntiAlias);
reed@google.comacd471f2011-05-03 21:26:46 +0000487 }
reed@google.combb6992a2011-04-26 17:41:56 +0000488 // we just pass on the bounds of the path
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000489 return this->INHERITED::clipRect(path.getBounds(), rgnOp, doAntiAlias);
reed@google.combb6992a2011-04-26 17:41:56 +0000490}
491
492bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000493 NOTIFY_SETUP(this);
494 if (this->needOpBytes(region.flatten(NULL))) {
495 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000496 fWriter.writeRegion(region);
reed@google.comacd471f2011-05-03 21:26:46 +0000497 }
reed@google.combb6992a2011-04-26 17:41:56 +0000498 return this->INHERITED::clipRegion(region, rgnOp);
499}
500
501///////////////////////////////////////////////////////////////////////////////
502
503void SkGPipeCanvas::clear(SkColor color) {
reed@google.comacd471f2011-05-03 21:26:46 +0000504 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000505 unsigned flags = 0;
506 if (color) {
507 flags |= kClear_HasColor_DrawOpFlag;
508 }
reed@google.comacd471f2011-05-03 21:26:46 +0000509 if (this->needOpBytes(sizeof(SkColor))) {
510 this->writeOp(kDrawClear_DrawOp, flags, 0);
511 if (color) {
512 fWriter.write32(color);
513 }
reed@google.combb6992a2011-04-26 17:41:56 +0000514 }
515}
516
517void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000518 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000519 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000520 if (this->needOpBytes()) {
reed@google.com31891582011-05-12 03:03:56 +0000521 this->writeOp(kDrawPaint_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000522 }
reed@google.combb6992a2011-04-26 17:41:56 +0000523}
524
525void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
526 const SkPoint pts[], const SkPaint& paint) {
527 if (count) {
reed@google.comacd471f2011-05-03 21:26:46 +0000528 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000529 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000530 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000531 this->writeOp(kDrawPoints_DrawOp, mode, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000532 fWriter.write32(count);
533 fWriter.write(pts, count * sizeof(SkPoint));
534 }
reed@google.combb6992a2011-04-26 17:41:56 +0000535 }
536}
537
538void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000539 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000540 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000541 if (this->needOpBytes(sizeof(SkRect))) {
reed@google.com31891582011-05-12 03:03:56 +0000542 this->writeOp(kDrawRect_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000543 fWriter.writeRect(rect);
544 }
reed@google.combb6992a2011-04-26 17:41:56 +0000545}
546
547void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000548 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000549 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000550 if (this->needOpBytes(estimateFlattenSize(path))) {
reed@google.com31891582011-05-12 03:03:56 +0000551 this->writeOp(kDrawPath_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000552 path.flatten(fWriter);
553 }
reed@google.combb6992a2011-04-26 17:41:56 +0000554}
555
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000556void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
557 const SkPaint* paint) {
558 // This is the brute-force solution
559 // TODO: add the notion of a shared, counted for large immutable resources
560 NOTIFY_SETUP(this);
561 if (paint) {
562 this->writePaint(*paint);
563 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000564
565 int bitmapIndex = this->flattenToIndex(bm);
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000566
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000567 if (this->needOpBytes(sizeof(SkScalar) * 2 + sizeof(bool))) {
568 this->writeOp(kDrawBitmap_DrawOp, 0, bitmapIndex);
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000569 fWriter.writeBool(paint != NULL);
570 fWriter.writeScalar(left);
571 fWriter.writeScalar(top);
572 }
reed@google.combb6992a2011-04-26 17:41:56 +0000573}
574
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000575void SkGPipeCanvas::drawBitmapRect(const SkBitmap& bm, const SkIRect* src,
576 const SkRect& dst, const SkPaint* paint) {
577 NOTIFY_SETUP(this);
578 if (paint) {
579 this->writePaint(*paint);
580 }
581
582 int bitmapIndex = this->flattenToIndex(bm);
583
584 size_t opBytesNeeded = sizeof(SkRect) + sizeof(bool) * 2;
585 bool hasSrc = src != NULL;
586 if (hasSrc) {
587 opBytesNeeded += sizeof(int32_t) * 4;
588 }
589 if (this->needOpBytes(opBytesNeeded)) {
590 this->writeOp(kDrawBitmapRect_DrawOp, 0, bitmapIndex);
591 fWriter.writeBool(paint != NULL);
592 fWriter.writeBool(hasSrc);
593 if (hasSrc) {
594 fWriter.write32(src->fLeft);
595 fWriter.write32(src->fTop);
596 fWriter.write32(src->fRight);
597 fWriter.write32(src->fBottom);
598 }
599 fWriter.writeRect(dst);
600 }
reed@google.combb6992a2011-04-26 17:41:56 +0000601}
602
603void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
604 const SkPaint*) {
605 UNIMPLEMENTED
606}
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000607
608void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000609 const SkRect& dst, const SkPaint* paint) {
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000610 NOTIFY_SETUP(this);
611 if (paint) {
612 this->writePaint(*paint);
613 }
614 int bitmapIndex = this->flattenToIndex(bm);
615
616 if (this->needOpBytes(sizeof(int32_t) * 4 + sizeof(bool)
617 + sizeof(SkRect))) {
618 this->writeOp(kDrawBitmapNine_DrawOp, 0, bitmapIndex);
619 fWriter.writeBool(paint != NULL);
620 fWriter.write32(center.fLeft);
621 fWriter.write32(center.fTop);
622 fWriter.write32(center.fRight);
623 fWriter.write32(center.fBottom);
624 fWriter.writeRect(dst);
625 }
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000626}
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000627
628void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
629 const SkPaint* paint) {
630 NOTIFY_SETUP(this);
631 if (paint) {
632 this->writePaint(*paint);
633 }
634 int bitmapIndex = this->flattenToIndex(bm);
635
636 if (this->needOpBytes(sizeof(int32_t) * 2 + sizeof(bool))) {
637 this->writeOp(kDrawSprite_DrawOp, 0, bitmapIndex);
638 fWriter.writeBool(paint != NULL);
639 fWriter.write32(left);
640 fWriter.write32(top);
641 }
reed@google.combb6992a2011-04-26 17:41:56 +0000642}
643
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000644void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
reed@google.combb6992a2011-04-26 17:41:56 +0000645 SkScalar y, const SkPaint& paint) {
646 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000647 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000648 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000649 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
reed@google.com31891582011-05-12 03:03:56 +0000650 this->writeOp(kDrawText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000651 fWriter.write32(byteLength);
652 fWriter.writePad(text, byteLength);
653 fWriter.writeScalar(x);
654 fWriter.writeScalar(y);
655 }
reed@google.combb6992a2011-04-26 17:41:56 +0000656 }
657}
658
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000659void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
reed@google.combb6992a2011-04-26 17:41:56 +0000660 const SkPoint pos[], const SkPaint& paint) {
661 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000662 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000663 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000664 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000665 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000666 this->writeOp(kDrawPosText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000667 fWriter.write32(byteLength);
668 fWriter.writePad(text, byteLength);
669 fWriter.write32(count);
670 fWriter.write(pos, count * sizeof(SkPoint));
671 }
reed@google.combb6992a2011-04-26 17:41:56 +0000672 }
673}
674
675void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
676 const SkScalar xpos[], SkScalar constY,
677 const SkPaint& paint) {
678 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000679 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000680 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000681 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000682 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
reed@google.com31891582011-05-12 03:03:56 +0000683 this->writeOp(kDrawPosTextH_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000684 fWriter.write32(byteLength);
685 fWriter.writePad(text, byteLength);
686 fWriter.write32(count);
687 fWriter.write(xpos, count * sizeof(SkScalar));
688 fWriter.writeScalar(constY);
689 }
reed@google.combb6992a2011-04-26 17:41:56 +0000690 }
691}
692
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000693void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
694 const SkPath& path, const SkMatrix* matrix,
reed@google.combb6992a2011-04-26 17:41:56 +0000695 const SkPaint& paint) {
696 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000697 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000698 unsigned flags = 0;
reed@google.comacd471f2011-05-03 21:26:46 +0000699 size_t size = 4 + SkAlign4(byteLength) + estimateFlattenSize(path);
reed@google.combb6992a2011-04-26 17:41:56 +0000700 if (matrix) {
701 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000702 size += matrix->flatten(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000703 }
reed@google.com31891582011-05-12 03:03:56 +0000704 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000705 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +0000706 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
reed@google.combb6992a2011-04-26 17:41:56 +0000707
reed@google.comacd471f2011-05-03 21:26:46 +0000708 fWriter.write32(byteLength);
709 fWriter.writePad(text, byteLength);
reed@google.combb6992a2011-04-26 17:41:56 +0000710
reed@google.comacd471f2011-05-03 21:26:46 +0000711 path.flatten(fWriter);
712 if (matrix) {
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000713 fWriter.writeMatrix(*matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000714 }
reed@google.combb6992a2011-04-26 17:41:56 +0000715 }
716 }
717}
718
719void SkGPipeCanvas::drawPicture(SkPicture& picture) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000720 // we want to playback the picture into individual draw calls
721 this->INHERITED::drawPicture(picture);
reed@google.combb6992a2011-04-26 17:41:56 +0000722}
723
reed@google.combb6992a2011-04-26 17:41:56 +0000724void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
725 const SkPoint vertices[], const SkPoint texs[],
726 const SkColor colors[], SkXfermode*,
727 const uint16_t indices[], int indexCount,
728 const SkPaint& paint) {
729 if (0 == vertexCount) {
730 return;
731 }
732
reed@google.comacd471f2011-05-03 21:26:46 +0000733 NOTIFY_SETUP(this);
734 size_t size = 4 + vertexCount * sizeof(SkPoint);
reed@google.com31891582011-05-12 03:03:56 +0000735 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000736 unsigned flags = 0;
737 if (texs) {
738 flags |= kDrawVertices_HasTexs_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000739 size += vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000740 }
741 if (colors) {
742 flags |= kDrawVertices_HasColors_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000743 size += vertexCount * sizeof(SkColor);
reed@google.combb6992a2011-04-26 17:41:56 +0000744 }
745 if (indices && indexCount > 0) {
746 flags |= kDrawVertices_HasIndices_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000747 size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
reed@google.combb6992a2011-04-26 17:41:56 +0000748 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000749
reed@google.comacd471f2011-05-03 21:26:46 +0000750 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +0000751 this->writeOp(kDrawVertices_DrawOp, flags, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000752 fWriter.write32(mode);
753 fWriter.write32(vertexCount);
754 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
755 if (texs) {
756 fWriter.write(texs, vertexCount * sizeof(SkPoint));
757 }
758 if (colors) {
759 fWriter.write(colors, vertexCount * sizeof(SkColor));
760 }
reed@google.combb6992a2011-04-26 17:41:56 +0000761
reed@google.comacd471f2011-05-03 21:26:46 +0000762 // TODO: flatten xfermode
reed@google.combb6992a2011-04-26 17:41:56 +0000763
reed@google.comacd471f2011-05-03 21:26:46 +0000764 if (indices && indexCount > 0) {
765 fWriter.write32(indexCount);
766 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
767 }
reed@google.combb6992a2011-04-26 17:41:56 +0000768 }
769}
770
reed@google.comacd471f2011-05-03 21:26:46 +0000771void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
772 if (size && ptr) {
773 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000774 unsigned data = 0;
775 if (size < (1 << DRAWOPS_DATA_BITS)) {
776 data = (unsigned)size;
777 }
reed@google.comacd471f2011-05-03 21:26:46 +0000778 if (this->needOpBytes(4 + SkAlign4(size))) {
779 this->writeOp(kDrawData_DrawOp, 0, data);
780 if (0 == data) {
781 fWriter.write32(size);
782 }
reed@google.combb6793b2011-05-05 15:18:15 +0000783 fWriter.writePad(ptr, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000784 }
785 }
786}
787
788///////////////////////////////////////////////////////////////////////////////
789
790template <typename T> uint32_t castToU32(T value) {
791 union {
792 T fSrc;
793 uint32_t fDst;
794 } data;
795 data.fSrc = value;
796 return data.fDst;
797}
798
reed@google.com31891582011-05-12 03:03:56 +0000799void SkGPipeCanvas::writePaint(const SkPaint& paint) {
800 SkPaint& base = fPaint;
reed@google.combb6992a2011-04-26 17:41:56 +0000801 uint32_t storage[32];
802 uint32_t* ptr = storage;
reed@google.combb6992a2011-04-26 17:41:56 +0000803
804 if (base.getFlags() != paint.getFlags()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000805 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
reed@google.comf5842f72011-05-04 18:30:04 +0000806 base.setFlags(paint.getFlags());
reed@google.combb6992a2011-04-26 17:41:56 +0000807 }
808 if (base.getColor() != paint.getColor()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000809 *ptr++ = PaintOp_packOp(kColor_PaintOp);
810 *ptr++ = paint.getColor();
reed@google.comf5842f72011-05-04 18:30:04 +0000811 base.setColor(paint.getColor());
reed@google.combb6992a2011-04-26 17:41:56 +0000812 }
813 if (base.getStyle() != paint.getStyle()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000814 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
reed@google.comf5842f72011-05-04 18:30:04 +0000815 base.setStyle(paint.getStyle());
reed@google.combb6992a2011-04-26 17:41:56 +0000816 }
817 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000818 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
reed@google.comf5842f72011-05-04 18:30:04 +0000819 base.setStrokeJoin(paint.getStrokeJoin());
reed@google.combb6992a2011-04-26 17:41:56 +0000820 }
821 if (base.getStrokeCap() != paint.getStrokeCap()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000822 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
reed@google.comf5842f72011-05-04 18:30:04 +0000823 base.setStrokeCap(paint.getStrokeCap());
reed@google.combb6992a2011-04-26 17:41:56 +0000824 }
825 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000826 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
827 *ptr++ = castToU32(paint.getStrokeWidth());
reed@google.comf5842f72011-05-04 18:30:04 +0000828 base.setStrokeWidth(paint.getStrokeWidth());
reed@google.combb6992a2011-04-26 17:41:56 +0000829 }
830 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000831 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
832 *ptr++ = castToU32(paint.getStrokeMiter());
reed@google.comf5842f72011-05-04 18:30:04 +0000833 base.setStrokeMiter(paint.getStrokeMiter());
reed@google.combb6992a2011-04-26 17:41:56 +0000834 }
835 if (base.getTextEncoding() != paint.getTextEncoding()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000836 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
reed@google.comf5842f72011-05-04 18:30:04 +0000837 base.setTextEncoding(paint.getTextEncoding());
reed@google.combb6992a2011-04-26 17:41:56 +0000838 }
839 if (base.getHinting() != paint.getHinting()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000840 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
reed@google.comf5842f72011-05-04 18:30:04 +0000841 base.setHinting(paint.getHinting());
reed@google.combb6992a2011-04-26 17:41:56 +0000842 }
843 if (base.getTextAlign() != paint.getTextAlign()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000844 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
reed@google.comf5842f72011-05-04 18:30:04 +0000845 base.setTextAlign(paint.getTextAlign());
reed@google.combb6992a2011-04-26 17:41:56 +0000846 }
847 if (base.getTextSize() != paint.getTextSize()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000848 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
849 *ptr++ = castToU32(paint.getTextSize());
reed@google.comf5842f72011-05-04 18:30:04 +0000850 base.setTextSize(paint.getTextSize());
reed@google.combb6992a2011-04-26 17:41:56 +0000851 }
852 if (base.getTextScaleX() != paint.getTextScaleX()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000853 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
854 *ptr++ = castToU32(paint.getTextScaleX());
reed@google.comf5842f72011-05-04 18:30:04 +0000855 base.setTextScaleX(paint.getTextScaleX());
reed@google.combb6992a2011-04-26 17:41:56 +0000856 }
857 if (base.getTextSkewX() != paint.getTextSkewX()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000858 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
859 *ptr++ = castToU32(paint.getTextSkewX());
reed@google.comf5842f72011-05-04 18:30:04 +0000860 base.setTextSkewX(paint.getTextSkewX());
861 }
862
863 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
864 uint32_t id = this->getTypefaceID(paint.getTypeface());
reed@google.comf5842f72011-05-04 18:30:04 +0000865 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
866 base.setTypeface(paint.getTypeface());
reed@google.combb6992a2011-04-26 17:41:56 +0000867 }
reed@google.combb6992a2011-04-26 17:41:56 +0000868
reed@google.comb55d1182011-05-11 00:42:04 +0000869 for (int i = 0; i < kCount_PaintFlats; i++) {
870 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i);
871 SkASSERT(index >= 0 && index <= fFlatArray.count());
872 if (index != fCurrFlatIndex[i]) {
reed@google.comb55d1182011-05-11 00:42:04 +0000873 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index);
874 fCurrFlatIndex[i] = index;
875 }
876 }
877
reed@google.comacd471f2011-05-03 21:26:46 +0000878 size_t size = (char*)ptr - (char*)storage;
879 if (size && this->needOpBytes(size)) {
reed@google.comb55d1182011-05-11 00:42:04 +0000880 this->writeOp(kPaintOp_DrawOp, 0, size);
reed@google.comb55d1182011-05-11 00:42:04 +0000881 fWriter.write(storage, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000882 for (size_t i = 0; i < size/4; i++) {
reed@google.comb55d1182011-05-11 00:42:04 +0000883// SkDebugf("[%d] %08X\n", i, storage[i]);
reed@google.combb6992a2011-04-26 17:41:56 +0000884 }
885 }
reed@google.combb6992a2011-04-26 17:41:56 +0000886}
887
888///////////////////////////////////////////////////////////////////////////////
889
890#include "SkGPipe.h"
891
reed@google.comacd471f2011-05-03 21:26:46 +0000892SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
reed@google.combb6992a2011-04-26 17:41:56 +0000893 fCanvas = NULL;
894}
895
896SkGPipeWriter::~SkGPipeWriter() {
reed@google.comacd471f2011-05-03 21:26:46 +0000897 this->endRecording();
reed@google.combb6992a2011-04-26 17:41:56 +0000898 SkSafeUnref(fCanvas);
899}
900
reed@google.comdde09562011-05-23 12:21:05 +0000901SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller,
902 uint32_t flags) {
reed@google.combb6992a2011-04-26 17:41:56 +0000903 if (NULL == fCanvas) {
reed@google.comacd471f2011-05-03 21:26:46 +0000904 fWriter.reset(NULL, 0);
reed@google.comdde09562011-05-23 12:21:05 +0000905 fFactorySet.reset();
906 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter,
907 (flags & kCrossProcess_Flag) ?
908 &fFactorySet : NULL));
reed@google.combb6992a2011-04-26 17:41:56 +0000909 }
910 return fCanvas;
911}
912
913void SkGPipeWriter::endRecording() {
914 if (fCanvas) {
915 fCanvas->finish();
916 fCanvas->unref();
917 fCanvas = NULL;
918 }
919}
920