blob: 41650b17fdc447e4300afa40d78375d569f23fe2 [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"
12#include "SkPaint.h"
reed@google.comacd471f2011-05-03 21:26:46 +000013#include "SkGPipe.h"
reed@google.combb6992a2011-04-26 17:41:56 +000014#include "SkGPipePriv.h"
15#include "SkReader32.h"
reed@google.comf5842f72011-05-04 18:30:04 +000016#include "SkStream.h"
reed@google.combb6793b2011-05-05 15:18:15 +000017
18#include "SkColorFilter.h"
19#include "SkDrawLooper.h"
20#include "SkMaskFilter.h"
djsollen@google.com2b2ede32012-04-12 13:24:04 +000021#include "SkOrderedReadBuffer.h"
reed@google.combb6793b2011-05-05 15:18:15 +000022#include "SkPathEffect.h"
23#include "SkRasterizer.h"
24#include "SkShader.h"
reed@google.comf5842f72011-05-04 18:30:04 +000025#include "SkTypeface.h"
reed@google.combb6793b2011-05-05 15:18:15 +000026#include "SkXfermode.h"
27
reed@google.comb55d1182011-05-11 00:42:04 +000028static void set_paintflat(SkPaint* paint, SkFlattenable* obj, unsigned paintFlat) {
29 SkASSERT(paintFlat < kCount_PaintFlats);
30 switch (paintFlat) {
31 case kColorFilter_PaintFlat:
32 paint->setColorFilter((SkColorFilter*)obj);
33 break;
reed@google.com0faac1e2011-05-11 05:58:58 +000034 case kDrawLooper_PaintFlat:
35 paint->setLooper((SkDrawLooper*)obj);
36 break;
reed@google.comb55d1182011-05-11 00:42:04 +000037 case kMaskFilter_PaintFlat:
38 paint->setMaskFilter((SkMaskFilter*)obj);
39 break;
40 case kPathEffect_PaintFlat:
41 paint->setPathEffect((SkPathEffect*)obj);
42 break;
43 case kRasterizer_PaintFlat:
44 paint->setRasterizer((SkRasterizer*)obj);
45 break;
46 case kShader_PaintFlat:
47 paint->setShader((SkShader*)obj);
48 break;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +000049 case kImageFilter_PaintFlat:
50 paint->setImageFilter((SkImageFilter*)obj);
51 break;
reed@google.comb55d1182011-05-11 00:42:04 +000052 case kXfermode_PaintFlat:
53 paint->setXfermode((SkXfermode*)obj);
54 break;
55 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +000056 SkDEBUGFAIL("never gets here");
reed@google.comb55d1182011-05-11 00:42:04 +000057 }
58}
59
reed@google.combb6793b2011-05-05 15:18:15 +000060template <typename T> class SkRefCntTDArray : public SkTDArray<T> {
61public:
62 ~SkRefCntTDArray() { this->unrefAll(); }
63};
reed@google.combb6992a2011-04-26 17:41:56 +000064
65class SkGPipeState {
66public:
67 SkGPipeState();
68 ~SkGPipeState();
reed@google.combb6793b2011-05-05 15:18:15 +000069
scroggo@google.com565254b2012-06-28 15:41:32 +000070 void setFlags(unsigned flags) {
71 if (fFlags != flags) {
72 fFlags = flags;
73 this->updateReader();
74 }
75 }
76
77 unsigned getFlags() const {
78 return fFlags;
79 }
80
reed@google.comdde09562011-05-23 12:21:05 +000081 void setReader(SkFlattenableReadBuffer* reader) {
82 fReader = reader;
scroggo@google.com565254b2012-06-28 15:41:32 +000083 this->updateReader();
reed@google.comdde09562011-05-23 12:21:05 +000084 }
reed@google.combb6793b2011-05-05 15:18:15 +000085
reed@google.com31891582011-05-12 03:03:56 +000086 const SkPaint& paint() const { return fPaint; }
87 SkPaint* editPaint() { return &fPaint; }
reed@google.combb6992a2011-04-26 17:41:56 +000088
reed@google.comb55d1182011-05-11 00:42:04 +000089 SkFlattenable* getFlat(unsigned index) const {
90 if (0 == index) {
91 return NULL;
92 }
93 return fFlatArray[index - 1];
94 }
95
reed@google.com67908f22011-06-27 14:47:50 +000096 void defFlattenable(PaintFlats pf, int index) {
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +000097 index--;
reed@google.comb55d1182011-05-11 00:42:04 +000098 SkFlattenable* obj = fReader->readFlattenable();
scroggo@google.comd3ba5cc2012-07-09 16:05:53 +000099 if (fFlatArray.count() == index) {
100 *fFlatArray.append() = obj;
101 } else {
102 SkSafeUnref(fFlatArray[index]);
103 fFlatArray[index] = obj;
104 }
reed@google.comb55d1182011-05-11 00:42:04 +0000105 }
106
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000107 void addBitmap(int index) {
scroggo@google.com4dffc592012-07-17 16:49:40 +0000108 index--;
109 SkBitmap* bm;
110 if(fBitmaps.count() == index) {
111 bm = SkNEW(SkBitmap);
112 *fBitmaps.append() = bm;
113 } else {
114 bm = fBitmaps[index];
115 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000116 bm->unflatten(*fReader);
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000117 }
118
119 SkBitmap* getBitmap(unsigned index) {
scroggo@google.com4dffc592012-07-17 16:49:40 +0000120 return fBitmaps[index - 1];
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000121 }
122
reed@google.combb6793b2011-05-05 15:18:15 +0000123 void addTypeface() {
124 size_t size = fReader->readU32();
125 const void* data = fReader->skip(SkAlign4(size));
reed@google.comf5842f72011-05-04 18:30:04 +0000126 SkMemoryStream stream(data, size, false);
reed@google.comf5842f72011-05-04 18:30:04 +0000127 *fTypefaces.append() = SkTypeface::Deserialize(&stream);
reed@google.com0faac1e2011-05-11 05:58:58 +0000128 }
reed@google.combb6793b2011-05-05 15:18:15 +0000129 void setTypeface(SkPaint* paint, unsigned id) {
130 paint->setTypeface(id ? fTypefaces[id - 1] : NULL);
131 }
reed@google.combb6793b2011-05-05 15:18:15 +0000132
reed@google.comb55d1182011-05-11 00:42:04 +0000133private:
scroggo@google.com565254b2012-06-28 15:41:32 +0000134 void updateReader() {
135 if (NULL == fReader) {
136 return;
137 }
138 bool crossProcess = SkToBool(fFlags & SkGPipeWriter::kCrossProcess_Flag);
139 fReader->setFlags(SkSetClearMask(fReader->getFlags(), crossProcess,
140 SkFlattenableReadBuffer::kCrossProcess_Flag));
141 if (crossProcess) {
142 fReader->setFactoryArray(&fFactoryArray);
143 } else {
144 fReader->setFactoryArray(NULL);
145 }
146 }
147 SkFlattenableReadBuffer* fReader;
reed@google.com31891582011-05-12 03:03:56 +0000148 SkPaint fPaint;
149 SkTDArray<SkFlattenable*> fFlatArray;
150 SkTDArray<SkTypeface*> fTypefaces;
reed@google.comdde09562011-05-23 12:21:05 +0000151 SkTDArray<SkFlattenable::Factory> fFactoryArray;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000152 SkTDArray<SkBitmap*> fBitmaps;
scroggo@google.com565254b2012-06-28 15:41:32 +0000153 unsigned fFlags;
reed@google.combb6992a2011-04-26 17:41:56 +0000154};
155
156///////////////////////////////////////////////////////////////////////////////
157
158template <typename T> const T* skip(SkReader32* reader, int count = 1) {
159 SkASSERT(count >= 0);
160 size_t size = sizeof(T) * count;
161 SkASSERT(SkAlign4(size) == size);
162 return reinterpret_cast<const T*>(reader->skip(size));
163}
164
165template <typename T> const T* skipAlign(SkReader32* reader, int count = 1) {
166 SkASSERT(count >= 0);
167 size_t size = SkAlign4(sizeof(T) * count);
168 return reinterpret_cast<const T*>(reader->skip(size));
169}
170
reed@google.combb6992a2011-04-26 17:41:56 +0000171///////////////////////////////////////////////////////////////////////////////
172///////////////////////////////////////////////////////////////////////////////
173
174static void clipPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
175 SkGPipeState* state) {
176 SkPath path;
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000177 reader->readPath(&path);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000178 canvas->clipPath(path, (SkRegion::Op)DrawOp_unpackData(op32),
179 reader->readBool());
reed@google.combb6992a2011-04-26 17:41:56 +0000180}
181
182static void clipRegion_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
183 SkGPipeState* state) {
184 SkRegion rgn;
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000185 reader->readRegion(&rgn);
reed@google.combb6992a2011-04-26 17:41:56 +0000186 canvas->clipRegion(rgn, (SkRegion::Op)DrawOp_unpackData(op32));
187}
188
189static void clipRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
190 SkGPipeState* state) {
scroggo@google.com691703c2012-06-05 14:58:40 +0000191 const SkRect* rect = skip<SkRect>(reader);
192 bool doAA = reader->readBool();
193 canvas->clipRect(*rect, (SkRegion::Op)DrawOp_unpackData(op32), doAA);
reed@google.combb6992a2011-04-26 17:41:56 +0000194}
195
196///////////////////////////////////////////////////////////////////////////////
197
198static void setMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
199 SkGPipeState* state) {
200 SkMatrix matrix;
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000201 reader->readMatrix(&matrix);
reed@google.combb6992a2011-04-26 17:41:56 +0000202 canvas->setMatrix(matrix);
203}
204
205static void concat_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
206 SkGPipeState* state) {
207 SkMatrix matrix;
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000208 reader->readMatrix(&matrix);
reed@google.combb6992a2011-04-26 17:41:56 +0000209 canvas->concat(matrix);
210}
211
212static void scale_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
213 SkGPipeState* state) {
214 const SkScalar* param = skip<SkScalar>(reader, 2);
215 canvas->scale(param[0], param[1]);
216}
217
218static void skew_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
219 SkGPipeState* state) {
220 const SkScalar* param = skip<SkScalar>(reader, 2);
221 canvas->skew(param[0], param[1]);
222}
223
224static void rotate_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
225 SkGPipeState* state) {
226 canvas->rotate(reader->readScalar());
227}
228
229static void translate_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
230 SkGPipeState* state) {
231 const SkScalar* param = skip<SkScalar>(reader, 2);
232 canvas->translate(param[0], param[1]);
233}
234
235///////////////////////////////////////////////////////////////////////////////
236
237static void save_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
238 SkGPipeState* state) {
239 canvas->save((SkCanvas::SaveFlags)DrawOp_unpackData(op32));
240}
241
242static void saveLayer_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
243 SkGPipeState* state) {
reed@google.comacd471f2011-05-03 21:26:46 +0000244 unsigned flags = DrawOp_unpackFlags(op32);
245 SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags)DrawOp_unpackData(op32);
reed@google.combb6992a2011-04-26 17:41:56 +0000246
247 const SkRect* bounds = NULL;
248 if (flags & kSaveLayer_HasBounds_DrawOpFlag) {
249 bounds = skip<SkRect>(reader);
250 }
251 const SkPaint* paint = NULL;
252 if (flags & kSaveLayer_HasPaint_DrawOpFlag) {
reed@google.com31891582011-05-12 03:03:56 +0000253 paint = &state->paint();
reed@google.combb6992a2011-04-26 17:41:56 +0000254 }
reed@google.comacd471f2011-05-03 21:26:46 +0000255 canvas->saveLayer(bounds, paint, saveFlags);
reed@google.combb6992a2011-04-26 17:41:56 +0000256}
257
258static void restore_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
259 SkGPipeState* state) {
260 canvas->restore();
261}
262
263///////////////////////////////////////////////////////////////////////////////
264
265static void drawClear_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
266 SkGPipeState* state) {
267 SkColor color = 0;
268 if (DrawOp_unpackFlags(op32) & kClear_HasColor_DrawOpFlag) {
269 color = reader->readU32();
270 }
271 canvas->clear(color);
272}
273
274static void drawPaint_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
275 SkGPipeState* state) {
reed@google.com31891582011-05-12 03:03:56 +0000276 canvas->drawPaint(state->paint());
reed@google.combb6992a2011-04-26 17:41:56 +0000277}
278
279static void drawPoints_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
280 SkGPipeState* state) {
281 SkCanvas::PointMode mode = (SkCanvas::PointMode)DrawOp_unpackFlags(op32);
282 size_t count = reader->readU32();
283 const SkPoint* pts = skip<SkPoint>(reader, count);
reed@google.com31891582011-05-12 03:03:56 +0000284 canvas->drawPoints(mode, count, pts, state->paint());
reed@google.combb6992a2011-04-26 17:41:56 +0000285}
286
287static void drawRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
288 SkGPipeState* state) {
reed@google.com31891582011-05-12 03:03:56 +0000289 canvas->drawRect(*skip<SkRect>(reader), state->paint());
reed@google.combb6992a2011-04-26 17:41:56 +0000290}
291
292static void drawPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
293 SkGPipeState* state) {
294 SkPath path;
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000295 reader->readPath(&path);
reed@google.com31891582011-05-12 03:03:56 +0000296 canvas->drawPath(path, state->paint());
reed@google.combb6992a2011-04-26 17:41:56 +0000297}
298
299static void drawVertices_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
300 SkGPipeState* state) {
301 unsigned flags = DrawOp_unpackFlags(op32);
302
303 SkCanvas::VertexMode mode = (SkCanvas::VertexMode)reader->readU32();
304 int vertexCount = reader->readU32();
305 const SkPoint* verts = skip<SkPoint>(reader, vertexCount);
306
307 const SkPoint* texs = NULL;
308 if (flags & kDrawVertices_HasTexs_DrawOpFlag) {
309 texs = skip<SkPoint>(reader, vertexCount);
310 }
311
312 const SkColor* colors = NULL;
313 if (flags & kDrawVertices_HasColors_DrawOpFlag) {
314 colors = skip<SkColor>(reader, vertexCount);
315 }
316
317 // TODO: flatten/unflatten xfermodes
318 SkXfermode* xfer = NULL;
319
320 int indexCount = 0;
321 const uint16_t* indices = NULL;
322 if (flags & kDrawVertices_HasIndices_DrawOpFlag) {
323 indexCount = reader->readU32();
324 indices = skipAlign<uint16_t>(reader, indexCount);
325 }
326
327 canvas->drawVertices(mode, vertexCount, verts, texs, colors, xfer,
reed@google.com31891582011-05-12 03:03:56 +0000328 indices, indexCount, state->paint());
reed@google.combb6992a2011-04-26 17:41:56 +0000329}
330
331///////////////////////////////////////////////////////////////////////////////
332
333static void drawText_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
334 SkGPipeState* state) {
335 size_t len = reader->readU32();
336 const void* text = reader->skip(SkAlign4(len));
337 const SkScalar* xy = skip<SkScalar>(reader, 2);
reed@google.com31891582011-05-12 03:03:56 +0000338 canvas->drawText(text, len, xy[0], xy[1], state->paint());
reed@google.combb6992a2011-04-26 17:41:56 +0000339}
340
341static void drawPosText_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
342 SkGPipeState* state) {
343 size_t len = reader->readU32();
344 const void* text = reader->skip(SkAlign4(len));
345 size_t posCount = reader->readU32(); // compute by our writer
346 const SkPoint* pos = skip<SkPoint>(reader, posCount);
reed@google.com31891582011-05-12 03:03:56 +0000347 canvas->drawPosText(text, len, pos, state->paint());
reed@google.combb6992a2011-04-26 17:41:56 +0000348}
349
350static void drawPosTextH_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
351 SkGPipeState* state) {
352 size_t len = reader->readU32();
353 const void* text = reader->skip(SkAlign4(len));
354 size_t posCount = reader->readU32(); // compute by our writer
355 const SkScalar* xpos = skip<SkScalar>(reader, posCount);
356 SkScalar constY = reader->readScalar();
reed@google.com31891582011-05-12 03:03:56 +0000357 canvas->drawPosTextH(text, len, xpos, constY, state->paint());
reed@google.combb6992a2011-04-26 17:41:56 +0000358}
359
360static void drawTextOnPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
361 SkGPipeState* state) {
362 size_t len = reader->readU32();
363 const void* text = reader->skip(SkAlign4(len));
364
365 SkPath path;
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000366 reader->readPath(&path);
reed@google.combb6992a2011-04-26 17:41:56 +0000367
368 SkMatrix matrixStorage;
369 const SkMatrix* matrix = NULL;
370 if (DrawOp_unpackFlags(op32) & kDrawTextOnPath_HasMatrix_DrawOpFlag) {
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000371 reader->readMatrix(&matrixStorage);
reed@google.combb6992a2011-04-26 17:41:56 +0000372 matrix = &matrixStorage;
373 }
374
reed@google.com31891582011-05-12 03:03:56 +0000375 canvas->drawTextOnPath(text, len, path, matrix, state->paint());
reed@google.combb6992a2011-04-26 17:41:56 +0000376}
377
378///////////////////////////////////////////////////////////////////////////////
379
scroggo@google.com284bf502012-07-17 16:10:34 +0000380class BitmapHolder : SkNoncopyable {
381public:
382 BitmapHolder(SkReader32* reader, uint32_t op32, SkGPipeState* state);
383 ~BitmapHolder() {
384 if (fInfo != NULL) {
385 fInfo->decDraws();
386 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000387 }
scroggo@google.com284bf502012-07-17 16:10:34 +0000388 const SkBitmap* getBitmap() {
389 return fBitmap;
390 }
391private:
392 BitmapInfo* fInfo;
393 const SkBitmap* fBitmap;
394};
395
396BitmapHolder::BitmapHolder(SkReader32* reader, uint32_t op32,
397 SkGPipeState* state) {
398 if (shouldFlattenBitmaps(state->getFlags())) {
399 fInfo = NULL;
400 fBitmap = state->getBitmap(DrawOp_unpackData(op32));
401 } else {
402 fInfo = static_cast<BitmapInfo*>(reader->readPtr());
403 fBitmap = fInfo->fBitmap;
404 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000405}
406
reed@google.combb6992a2011-04-26 17:41:56 +0000407static void drawBitmap_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
408 SkGPipeState* state) {
scroggo@google.com284bf502012-07-17 16:10:34 +0000409 BitmapHolder holder(reader, op32, state);
scroggo@google.com58be6822012-07-30 14:40:01 +0000410 bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpsFlag);
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000411 SkScalar left = reader->readScalar();
412 SkScalar top = reader->readScalar();
scroggo@google.com284bf502012-07-17 16:10:34 +0000413 canvas->drawBitmap(*holder.getBitmap(), left, top, hasPaint ? &state->paint() : NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000414}
415
416static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
417 SkGPipeState* state) {
scroggo@google.com58be6822012-07-30 14:40:01 +0000418 BitmapHolder holder(reader, op32, state);
419 bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpsFlag);
420 SkMatrix matrix;
421 reader->readMatrix(&matrix);
422 canvas->drawBitmapMatrix(*holder.getBitmap(), matrix,
423 hasPaint ? &state->paint() : NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000424}
425
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000426static void drawBitmapNine_rp(SkCanvas* canvas, SkReader32* reader,
427 uint32_t op32, SkGPipeState* state) {
scroggo@google.com284bf502012-07-17 16:10:34 +0000428 BitmapHolder holder(reader, op32, state);
scroggo@google.com58be6822012-07-30 14:40:01 +0000429 bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpsFlag);
scroggo@google.com691703c2012-06-05 14:58:40 +0000430 const SkIRect* center = skip<SkIRect>(reader);
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000431 const SkRect* dst = skip<SkRect>(reader);
scroggo@google.com284bf502012-07-17 16:10:34 +0000432 canvas->drawBitmapNine(*holder.getBitmap(), *center, *dst,
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000433 hasPaint ? &state->paint() : NULL);
434}
435
436static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader,
437 uint32_t op32, SkGPipeState* state) {
scroggo@google.com284bf502012-07-17 16:10:34 +0000438 BitmapHolder holder(reader, op32, state);
scroggo@google.com58be6822012-07-30 14:40:01 +0000439 unsigned flags = DrawOp_unpackFlags(op32);
440 bool hasPaint = SkToBool(flags & kDrawBitmap_HasPaint_DrawOpsFlag);
441 bool hasSrc = SkToBool(flags & kDrawBitmap_HasSrcRect_DrawOpsFlag);
scroggo@google.com691703c2012-06-05 14:58:40 +0000442 const SkIRect* src;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000443 if (hasSrc) {
scroggo@google.com691703c2012-06-05 14:58:40 +0000444 src = skip<SkIRect>(reader);
445 } else {
446 src = NULL;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000447 }
448 const SkRect* dst = skip<SkRect>(reader);
scroggo@google.com284bf502012-07-17 16:10:34 +0000449 canvas->drawBitmapRect(*holder.getBitmap(), src, *dst, hasPaint ? &state->paint() : NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000450}
451
452static void drawSprite_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
453 SkGPipeState* state) {
scroggo@google.com284bf502012-07-17 16:10:34 +0000454 BitmapHolder holder(reader, op32, state);
scroggo@google.com58be6822012-07-30 14:40:01 +0000455 bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpsFlag);
scroggo@google.com691703c2012-06-05 14:58:40 +0000456 const SkIPoint* point = skip<SkIPoint>(reader);
scroggo@google.com284bf502012-07-17 16:10:34 +0000457 canvas->drawSprite(*holder.getBitmap(), point->fX, point->fY, hasPaint ? &state->paint() : NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000458}
459
460///////////////////////////////////////////////////////////////////////////////
461
462static void drawData_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
463 SkGPipeState* state) {
464 // since we don't have a paint, we can use data for our (small) sizes
465 size_t size = DrawOp_unpackData(op32);
466 if (0 == size) {
467 size = reader->readU32();
468 }
469 const void* data = reader->skip(SkAlign4(size));
470 canvas->drawData(data, size);
471}
472
reed@google.combb6992a2011-04-26 17:41:56 +0000473static void drawPicture_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
474 SkGPipeState* state) {
475 UNIMPLEMENTED
476}
477
478///////////////////////////////////////////////////////////////////////////////
479
reed@google.combb6992a2011-04-26 17:41:56 +0000480static void paintOp_rp(SkCanvas*, SkReader32* reader, uint32_t op32,
481 SkGPipeState* state) {
reed@google.comb55d1182011-05-11 00:42:04 +0000482 size_t offset = reader->offset();
483 size_t stop = offset + PaintOp_unpackData(op32);
reed@google.com31891582011-05-12 03:03:56 +0000484 SkPaint* p = state->editPaint();
reed@google.combb6992a2011-04-26 17:41:56 +0000485
486 do {
487 uint32_t p32 = reader->readU32();
488 unsigned op = PaintOp_unpackOp(p32);
489 unsigned data = PaintOp_unpackData(p32);
reed@google.combb6992a2011-04-26 17:41:56 +0000490
reed@google.comb55d1182011-05-11 00:42:04 +0000491// SkDebugf(" read %08X op=%d flags=%d data=%d\n", p32, op, done, data);
reed@google.combb6992a2011-04-26 17:41:56 +0000492
493 switch (op) {
494 case kReset_PaintOp: p->reset(); break;
495 case kFlags_PaintOp: p->setFlags(data); break;
496 case kColor_PaintOp: p->setColor(reader->readU32()); break;
497 case kStyle_PaintOp: p->setStyle((SkPaint::Style)data); break;
498 case kJoin_PaintOp: p->setStrokeJoin((SkPaint::Join)data); break;
499 case kCap_PaintOp: p->setStrokeCap((SkPaint::Cap)data); break;
500 case kWidth_PaintOp: p->setStrokeWidth(reader->readScalar()); break;
501 case kMiter_PaintOp: p->setStrokeMiter(reader->readScalar()); break;
502 case kEncoding_PaintOp:
503 p->setTextEncoding((SkPaint::TextEncoding)data);
504 break;
505 case kHinting_PaintOp: p->setHinting((SkPaint::Hinting)data); break;
506 case kAlign_PaintOp: p->setTextAlign((SkPaint::Align)data); break;
507 case kTextSize_PaintOp: p->setTextSize(reader->readScalar()); break;
508 case kTextScaleX_PaintOp: p->setTextScaleX(reader->readScalar()); break;
509 case kTextSkewX_PaintOp: p->setTextSkewX(reader->readScalar()); break;
reed@google.combb6793b2011-05-05 15:18:15 +0000510
reed@google.comb55d1182011-05-11 00:42:04 +0000511 case kFlatIndex_PaintOp: {
512 PaintFlats pf = (PaintFlats)PaintOp_unpackFlags(p32);
513 unsigned index = data;
514 set_paintflat(p, state->getFlat(index), pf);
515 break;
516 }
517
scroggo@google.com3cb969f2012-07-27 20:39:19 +0000518 case kTypeface_PaintOp:
519 SkASSERT(SkToBool(state->getFlags() &
520 SkGPipeWriter::kCrossProcess_Flag));
521 state->setTypeface(p, data); break;
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000522 default: SkDEBUGFAIL("bad paintop"); return;
reed@google.combb6992a2011-04-26 17:41:56 +0000523 }
reed@google.comb55d1182011-05-11 00:42:04 +0000524 SkASSERT(reader->offset() <= stop);
reed@google.com31891582011-05-12 03:03:56 +0000525 } while (reader->offset() < stop);
reed@google.combb6992a2011-04-26 17:41:56 +0000526}
527
scroggo@google.com3cb969f2012-07-27 20:39:19 +0000528static void typeface_rp(SkCanvas*, SkReader32* reader, uint32_t,
529 SkGPipeState* state) {
530 SkASSERT(!SkToBool(state->getFlags() & SkGPipeWriter::kCrossProcess_Flag));
531 SkPaint* p = state->editPaint();
532 p->setTypeface(static_cast<SkTypeface*>(reader->readPtr()));
533}
534
reed@google.combb6793b2011-05-05 15:18:15 +0000535///////////////////////////////////////////////////////////////////////////////
536
reed@google.com0faac1e2011-05-11 05:58:58 +0000537static void def_Typeface_rp(SkCanvas*, SkReader32*, uint32_t, SkGPipeState* state) {
538 state->addTypeface();
539}
540
reed@google.comb55d1182011-05-11 00:42:04 +0000541static void def_PaintFlat_rp(SkCanvas*, SkReader32*, uint32_t op32,
542 SkGPipeState* state) {
543 PaintFlats pf = (PaintFlats)DrawOp_unpackFlags(op32);
544 unsigned index = DrawOp_unpackData(op32);
545 state->defFlattenable(pf, index);
546}
547
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000548static void def_Bitmap_rp(SkCanvas*, SkReader32*, uint32_t op32,
549 SkGPipeState* state) {
550 unsigned index = DrawOp_unpackData(op32);
551 state->addBitmap(index);
552}
553
reed@google.combb6992a2011-04-26 17:41:56 +0000554///////////////////////////////////////////////////////////////////////////////
555
reed@google.comacd471f2011-05-03 21:26:46 +0000556static void skip_rp(SkCanvas*, SkReader32* reader, uint32_t op32, SkGPipeState*) {
557 size_t bytes = DrawOp_unpackData(op32);
558 (void)reader->skip(bytes);
559}
560
scroggo@google.com565254b2012-06-28 15:41:32 +0000561static void reportflags_rp(SkCanvas*, SkReader32*, uint32_t op32,
562 SkGPipeState* state) {
563 unsigned flags = DrawOp_unpackFlags(op32);
564 state->setFlags(flags);
565}
566
reed@google.combb6992a2011-04-26 17:41:56 +0000567static void done_rp(SkCanvas*, SkReader32*, uint32_t, SkGPipeState*) {}
568
569typedef void (*ReadProc)(SkCanvas*, SkReader32*, uint32_t op32, SkGPipeState*);
570
571static const ReadProc gReadTable[] = {
reed@google.comacd471f2011-05-03 21:26:46 +0000572 skip_rp,
reed@google.combb6992a2011-04-26 17:41:56 +0000573 clipPath_rp,
574 clipRegion_rp,
575 clipRect_rp,
576 concat_rp,
577 drawBitmap_rp,
578 drawBitmapMatrix_rp,
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000579 drawBitmapNine_rp,
reed@google.combb6992a2011-04-26 17:41:56 +0000580 drawBitmapRect_rp,
581 drawClear_rp,
582 drawData_rp,
583 drawPaint_rp,
584 drawPath_rp,
585 drawPicture_rp,
586 drawPoints_rp,
587 drawPosText_rp,
588 drawPosTextH_rp,
589 drawRect_rp,
reed@google.combb6992a2011-04-26 17:41:56 +0000590 drawSprite_rp,
591 drawText_rp,
592 drawTextOnPath_rp,
593 drawVertices_rp,
594 restore_rp,
595 rotate_rp,
596 save_rp,
597 saveLayer_rp,
598 scale_rp,
599 setMatrix_rp,
600 skew_rp,
601 translate_rp,
reed@google.com0faac1e2011-05-11 05:58:58 +0000602
reed@google.combb6992a2011-04-26 17:41:56 +0000603 paintOp_rp,
scroggo@google.com3cb969f2012-07-27 20:39:19 +0000604 typeface_rp,
reed@google.combb6793b2011-05-05 15:18:15 +0000605 def_Typeface_rp,
reed@google.com0faac1e2011-05-11 05:58:58 +0000606 def_PaintFlat_rp,
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000607 def_Bitmap_rp,
reed@google.com0faac1e2011-05-11 05:58:58 +0000608
scroggo@google.com565254b2012-06-28 15:41:32 +0000609 reportflags_rp,
reed@google.combb6992a2011-04-26 17:41:56 +0000610 done_rp
611};
612
613///////////////////////////////////////////////////////////////////////////////
614
scroggo@google.com565254b2012-06-28 15:41:32 +0000615SkGPipeState::SkGPipeState(): fReader(0), fFlags(0) {}
reed@google.combb6992a2011-04-26 17:41:56 +0000616
reed@google.comb55d1182011-05-11 00:42:04 +0000617SkGPipeState::~SkGPipeState() {
reed@google.com6bac9472011-06-21 19:24:00 +0000618 fTypefaces.safeUnrefAll();
619 fFlatArray.safeUnrefAll();
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000620 fBitmaps.deleteAll();
reed@google.combb6992a2011-04-26 17:41:56 +0000621}
622
623///////////////////////////////////////////////////////////////////////////////
624
625#include "SkGPipe.h"
626
scroggo@google.com72c96722012-06-06 21:07:10 +0000627SkGPipeReader::SkGPipeReader() {
628 fCanvas = NULL;
reed@google.combb6992a2011-04-26 17:41:56 +0000629 fState = NULL;
630}
631
scroggo@google.com72c96722012-06-06 21:07:10 +0000632SkGPipeReader::SkGPipeReader(SkCanvas* target) {
633 fCanvas = NULL;
634 this->setCanvas(target);
635 fState = NULL;
636}
637
638void SkGPipeReader::setCanvas(SkCanvas *target) {
639 SkRefCnt_SafeAssign(fCanvas, target);
640}
641
reed@google.combb6992a2011-04-26 17:41:56 +0000642SkGPipeReader::~SkGPipeReader() {
643 SkSafeUnref(fCanvas);
644 delete fState;
645}
646
reed@google.com80b09de2011-05-23 13:54:24 +0000647SkGPipeReader::Status SkGPipeReader::playback(const void* data, size_t length,
yangsu@google.com1bce0a52011-06-16 21:08:19 +0000648 size_t* bytesRead, bool readAtom) {
reed@google.combb6992a2011-04-26 17:41:56 +0000649 if (NULL == fCanvas) {
650 return kError_Status;
651 }
652
653 if (NULL == fState) {
654 fState = new SkGPipeState;
655 }
656
reed@google.com0faac1e2011-05-11 05:58:58 +0000657 SkASSERT(SK_ARRAY_COUNT(gReadTable) == (kDone_DrawOp + 1));
658
reed@google.combb6992a2011-04-26 17:41:56 +0000659 const ReadProc* table = gReadTable;
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000660 SkOrderedReadBuffer reader(data, length);
reed@google.combb6992a2011-04-26 17:41:56 +0000661 SkCanvas* canvas = fCanvas;
reed@google.com80b09de2011-05-23 13:54:24 +0000662 Status status = kEOF_Status;
reed@google.combb6793b2011-05-05 15:18:15 +0000663
664 fState->setReader(&reader);
reed@google.combb6992a2011-04-26 17:41:56 +0000665 while (!reader.eof()) {
666 uint32_t op32 = reader.readU32();
667 unsigned op = DrawOp_unpackOp(op32);
caryclark@google.com920901d2012-06-06 12:04:11 +0000668 // SkDEBUGCODE(DrawOps drawOp = (DrawOps)op;)
reed@google.combb6992a2011-04-26 17:41:56 +0000669
670 if (op >= SK_ARRAY_COUNT(gReadTable)) {
671 SkDebugf("---- bad op during GPipeState::playback\n");
reed@google.com80b09de2011-05-23 13:54:24 +0000672 status = kError_Status;
673 break;
reed@google.combb6992a2011-04-26 17:41:56 +0000674 }
675 if (kDone_DrawOp == op) {
reed@google.com80b09de2011-05-23 13:54:24 +0000676 status = kDone_Status;
677 break;
reed@google.combb6992a2011-04-26 17:41:56 +0000678 }
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000679 table[op](canvas, reader.getReader32(), op32, fState);
yangsu@google.com1bce0a52011-06-16 21:08:19 +0000680 if (readAtom &&
681 (table[op] != paintOp_rp &&
682 table[op] != def_Typeface_rp &&
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000683 table[op] != def_PaintFlat_rp &&
684 table[op] != def_Bitmap_rp
yangsu@google.com1bce0a52011-06-16 21:08:19 +0000685 )) {
686 status = kReadAtom_Status;
687 break;
688 }
reed@google.combb6992a2011-04-26 17:41:56 +0000689 }
reed@google.com80b09de2011-05-23 13:54:24 +0000690
691 if (bytesRead) {
reed@google.comac45f002011-05-24 13:50:21 +0000692 *bytesRead = reader.offset();
reed@google.com80b09de2011-05-23 13:54:24 +0000693 }
694 return status;
reed@google.combb6992a2011-04-26 17:41:56 +0000695}
696
697