blob: 43abf899c578e00dd8371c87bbf80097460d4ab6 [file] [log] [blame]
reed@google.combb6992a2011-04-26 17:41:56 +00001/*
2 Copyright 2011 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "SkCanvas.h"
19#include "SkPaint.h"
reed@google.comacd471f2011-05-03 21:26:46 +000020#include "SkGPipe.h"
reed@google.combb6992a2011-04-26 17:41:56 +000021#include "SkGPipePriv.h"
22#include "SkReader32.h"
reed@google.comf5842f72011-05-04 18:30:04 +000023#include "SkStream.h"
24#include "SkTypeface.h"
reed@google.combb6992a2011-04-26 17:41:56 +000025
26class SkGPipeState {
27public:
28 SkGPipeState();
29 ~SkGPipeState();
30
31 const SkPaint& getPaint(uint32_t drawOp32) const;
32
33 // Extracts index from DrawOp_unpackData().
34 // Returns the specified paint from our list, or creates a new paint if
35 // index == count. If index > count, return NULL
36 SkPaint* editPaint(uint32_t drawOp32);
reed@google.comf5842f72011-05-04 18:30:04 +000037
38 SkTypeface* findTypeface(int id) const {
39 SkASSERT(id <= fTypefaces.count());
40 return id ? fTypefaces[id - 1] : NULL;
41 }
42 void addTypeface(SkReader32* reader) {
43 size_t size = reader->readU32();
44 const void* data = reader->skip(SkAlign4(size));
45 SkMemoryStream stream(data, size, false);
46 // fTypefaces takes over ownership of the typeface reference
47 *fTypefaces.append() = SkTypeface::Deserialize(&stream);
48 }
49
reed@google.combb6992a2011-04-26 17:41:56 +000050private:
51 SkTDArray<SkPaint*> fPaints;
reed@google.comf5842f72011-05-04 18:30:04 +000052 SkTDArray<SkTypeface*> fTypefaces;
reed@google.combb6992a2011-04-26 17:41:56 +000053};
54
55///////////////////////////////////////////////////////////////////////////////
56
57template <typename T> const T* skip(SkReader32* reader, int count = 1) {
58 SkASSERT(count >= 0);
59 size_t size = sizeof(T) * count;
60 SkASSERT(SkAlign4(size) == size);
61 return reinterpret_cast<const T*>(reader->skip(size));
62}
63
64template <typename T> const T* skipAlign(SkReader32* reader, int count = 1) {
65 SkASSERT(count >= 0);
66 size_t size = SkAlign4(sizeof(T) * count);
67 return reinterpret_cast<const T*>(reader->skip(size));
68}
69
70static void readRegion(SkReader32* reader, SkRegion* rgn) {
71 size_t size = rgn->unflatten(reader->peek());
72 SkASSERT(SkAlign4(size) == size);
73 (void)reader->skip(size);
74}
75
76static void readMatrix(SkReader32* reader, SkMatrix* matrix) {
77 size_t size = matrix->unflatten(reader->peek());
78 SkASSERT(SkAlign4(size) == size);
79 (void)reader->skip(size);
80}
81
82const SkPaint& SkGPipeState::getPaint(uint32_t op32) const {
83 unsigned index = DrawOp_unpackData(op32);
84 if (index >= fPaints.count()) {
85 SkASSERT(!"paint index out of range");
86 index = 0; // we always have at least 1 paint
87 }
88 return *fPaints[index];
89}
90
91SkPaint* SkGPipeState::editPaint(uint32_t op32) {
92 unsigned index = DrawOp_unpackData(op32);
93
94 if (index > fPaints.count()) {
95 SkASSERT(!"paint index out of range");
96 return NULL;
97 }
98
99 if (index == fPaints.count()) {
100 *fPaints.append() = SkNEW(SkPaint);
101 }
102 return fPaints[index];
103}
104
105///////////////////////////////////////////////////////////////////////////////
106///////////////////////////////////////////////////////////////////////////////
107
108static void clipPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
109 SkGPipeState* state) {
110 SkPath path;
111 path.unflatten(*reader);
112 canvas->clipPath(path, (SkRegion::Op)DrawOp_unpackData(op32));
113}
114
115static void clipRegion_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
116 SkGPipeState* state) {
117 SkRegion rgn;
118 readRegion(reader, &rgn);
119 canvas->clipRegion(rgn, (SkRegion::Op)DrawOp_unpackData(op32));
120}
121
122static void clipRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
123 SkGPipeState* state) {
124 canvas->clipRect(*skip<SkRect>(reader), (SkRegion::Op)DrawOp_unpackData(op32));
125}
126
127///////////////////////////////////////////////////////////////////////////////
128
129static void setMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
130 SkGPipeState* state) {
131 SkMatrix matrix;
132 readMatrix(reader, &matrix);
133 canvas->setMatrix(matrix);
134}
135
136static void concat_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
137 SkGPipeState* state) {
138 SkMatrix matrix;
139 readMatrix(reader, &matrix);
140 canvas->concat(matrix);
141}
142
143static void scale_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
144 SkGPipeState* state) {
145 const SkScalar* param = skip<SkScalar>(reader, 2);
146 canvas->scale(param[0], param[1]);
147}
148
149static void skew_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
150 SkGPipeState* state) {
151 const SkScalar* param = skip<SkScalar>(reader, 2);
152 canvas->skew(param[0], param[1]);
153}
154
155static void rotate_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
156 SkGPipeState* state) {
157 canvas->rotate(reader->readScalar());
158}
159
160static void translate_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
161 SkGPipeState* state) {
162 const SkScalar* param = skip<SkScalar>(reader, 2);
163 canvas->translate(param[0], param[1]);
164}
165
166///////////////////////////////////////////////////////////////////////////////
167
168static void save_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
169 SkGPipeState* state) {
170 canvas->save((SkCanvas::SaveFlags)DrawOp_unpackData(op32));
171}
172
173static void saveLayer_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
174 SkGPipeState* state) {
reed@google.comacd471f2011-05-03 21:26:46 +0000175 unsigned flags = DrawOp_unpackFlags(op32);
176 SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags)DrawOp_unpackData(op32);
reed@google.combb6992a2011-04-26 17:41:56 +0000177
178 const SkRect* bounds = NULL;
179 if (flags & kSaveLayer_HasBounds_DrawOpFlag) {
180 bounds = skip<SkRect>(reader);
181 }
182 const SkPaint* paint = NULL;
183 if (flags & kSaveLayer_HasPaint_DrawOpFlag) {
184 paint = &state->getPaint(reader->readU32());
185 }
reed@google.comacd471f2011-05-03 21:26:46 +0000186 canvas->saveLayer(bounds, paint, saveFlags);
reed@google.combb6992a2011-04-26 17:41:56 +0000187}
188
189static void restore_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
190 SkGPipeState* state) {
191 canvas->restore();
192}
193
194///////////////////////////////////////////////////////////////////////////////
195
196static void drawClear_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
197 SkGPipeState* state) {
198 SkColor color = 0;
199 if (DrawOp_unpackFlags(op32) & kClear_HasColor_DrawOpFlag) {
200 color = reader->readU32();
201 }
202 canvas->clear(color);
203}
204
205static void drawPaint_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
206 SkGPipeState* state) {
207 canvas->drawPaint(state->getPaint(op32));
208}
209
210static void drawPoints_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
211 SkGPipeState* state) {
212 SkCanvas::PointMode mode = (SkCanvas::PointMode)DrawOp_unpackFlags(op32);
213 size_t count = reader->readU32();
214 const SkPoint* pts = skip<SkPoint>(reader, count);
215 canvas->drawPoints(mode, count, pts, state->getPaint(op32));
216}
217
218static void drawRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
219 SkGPipeState* state) {
220 canvas->drawRect(*skip<SkRect>(reader), state->getPaint(op32));
221}
222
223static void drawPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
224 SkGPipeState* state) {
225 SkPath path;
226 path.unflatten(*reader);
227 canvas->drawPath(path, state->getPaint(op32));
228}
229
230static void drawVertices_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
231 SkGPipeState* state) {
232 unsigned flags = DrawOp_unpackFlags(op32);
233
234 SkCanvas::VertexMode mode = (SkCanvas::VertexMode)reader->readU32();
235 int vertexCount = reader->readU32();
236 const SkPoint* verts = skip<SkPoint>(reader, vertexCount);
237
238 const SkPoint* texs = NULL;
239 if (flags & kDrawVertices_HasTexs_DrawOpFlag) {
240 texs = skip<SkPoint>(reader, vertexCount);
241 }
242
243 const SkColor* colors = NULL;
244 if (flags & kDrawVertices_HasColors_DrawOpFlag) {
245 colors = skip<SkColor>(reader, vertexCount);
246 }
247
248 // TODO: flatten/unflatten xfermodes
249 SkXfermode* xfer = NULL;
250
251 int indexCount = 0;
252 const uint16_t* indices = NULL;
253 if (flags & kDrawVertices_HasIndices_DrawOpFlag) {
254 indexCount = reader->readU32();
255 indices = skipAlign<uint16_t>(reader, indexCount);
256 }
257
258 canvas->drawVertices(mode, vertexCount, verts, texs, colors, xfer,
259 indices, indexCount, state->getPaint(op32));
260}
261
262///////////////////////////////////////////////////////////////////////////////
263
264static void drawText_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
265 SkGPipeState* state) {
266 size_t len = reader->readU32();
267 const void* text = reader->skip(SkAlign4(len));
268 const SkScalar* xy = skip<SkScalar>(reader, 2);
269 canvas->drawText(text, len, xy[0], xy[1], state->getPaint(op32));
270}
271
272static void drawPosText_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
273 SkGPipeState* state) {
274 size_t len = reader->readU32();
275 const void* text = reader->skip(SkAlign4(len));
276 size_t posCount = reader->readU32(); // compute by our writer
277 const SkPoint* pos = skip<SkPoint>(reader, posCount);
278 canvas->drawPosText(text, len, pos, state->getPaint(op32));
279}
280
281static void drawPosTextH_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
282 SkGPipeState* state) {
283 size_t len = reader->readU32();
284 const void* text = reader->skip(SkAlign4(len));
285 size_t posCount = reader->readU32(); // compute by our writer
286 const SkScalar* xpos = skip<SkScalar>(reader, posCount);
287 SkScalar constY = reader->readScalar();
288 canvas->drawPosTextH(text, len, xpos, constY, state->getPaint(op32));
289}
290
291static void drawTextOnPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
292 SkGPipeState* state) {
293 size_t len = reader->readU32();
294 const void* text = reader->skip(SkAlign4(len));
295
296 SkPath path;
297 path.unflatten(*reader);
298
299 SkMatrix matrixStorage;
300 const SkMatrix* matrix = NULL;
301 if (DrawOp_unpackFlags(op32) & kDrawTextOnPath_HasMatrix_DrawOpFlag) {
302 readMatrix(reader, &matrixStorage);
303 matrix = &matrixStorage;
304 }
305
306 canvas->drawTextOnPath(text, len, path, matrix, state->getPaint(op32));
307}
308
309///////////////////////////////////////////////////////////////////////////////
310
311static void drawBitmap_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
312 SkGPipeState* state) {
313 UNIMPLEMENTED
314}
315
316static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
317 SkGPipeState* state) {
318 UNIMPLEMENTED
319}
320
321static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
322 SkGPipeState* state) {
323 UNIMPLEMENTED
324}
325
326static void drawSprite_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
327 SkGPipeState* state) {
328 UNIMPLEMENTED
329}
330
331///////////////////////////////////////////////////////////////////////////////
332
333static void drawData_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
334 SkGPipeState* state) {
335 // since we don't have a paint, we can use data for our (small) sizes
336 size_t size = DrawOp_unpackData(op32);
337 if (0 == size) {
338 size = reader->readU32();
339 }
340 const void* data = reader->skip(SkAlign4(size));
341 canvas->drawData(data, size);
342}
343
344static void drawShape_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
345 SkGPipeState* state) {
346 UNIMPLEMENTED
347}
348
349static void drawPicture_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
350 SkGPipeState* state) {
351 UNIMPLEMENTED
352}
353
354///////////////////////////////////////////////////////////////////////////////
355
356static void inflate_patheffect(SkReader32* reader, SkPaint* paint) {
357}
358
359static void inflate_shader(SkReader32* reader, SkPaint* paint) {
360}
361
362static void inflate_xfermode(SkReader32* reader, SkPaint* paint) {
363}
364
365static void inflate_maskfilter(SkReader32* reader, SkPaint* paint) {
366}
367
368static void inflate_colorfilter(SkReader32* reader, SkPaint* paint) {
369}
370
371static void inflate_rasterizer(SkReader32* reader, SkPaint* paint) {
372}
373
374static void inflate_drawlooper(SkReader32* reader, SkPaint* paint) {
375}
376
377static void paintOp_rp(SkCanvas*, SkReader32* reader, uint32_t op32,
378 SkGPipeState* state) {
379 SkPaint* p = state->editPaint(op32);
380 int done;
381
382 do {
383 uint32_t p32 = reader->readU32();
384 unsigned op = PaintOp_unpackOp(p32);
385 unsigned data = PaintOp_unpackData(p32);
386 done = PaintOp_unpackFlags(p32) & kLastOp_PaintOpFlag;
387
388 SkDebugf(" read %08X op=%d flags=%d data=%d\n", p32, op, done, data);
389
390 switch (op) {
391 case kReset_PaintOp: p->reset(); break;
392 case kFlags_PaintOp: p->setFlags(data); break;
393 case kColor_PaintOp: p->setColor(reader->readU32()); break;
394 case kStyle_PaintOp: p->setStyle((SkPaint::Style)data); break;
395 case kJoin_PaintOp: p->setStrokeJoin((SkPaint::Join)data); break;
396 case kCap_PaintOp: p->setStrokeCap((SkPaint::Cap)data); break;
397 case kWidth_PaintOp: p->setStrokeWidth(reader->readScalar()); break;
398 case kMiter_PaintOp: p->setStrokeMiter(reader->readScalar()); break;
399 case kEncoding_PaintOp:
400 p->setTextEncoding((SkPaint::TextEncoding)data);
401 break;
402 case kHinting_PaintOp: p->setHinting((SkPaint::Hinting)data); break;
403 case kAlign_PaintOp: p->setTextAlign((SkPaint::Align)data); break;
404 case kTextSize_PaintOp: p->setTextSize(reader->readScalar()); break;
405 case kTextScaleX_PaintOp: p->setTextScaleX(reader->readScalar()); break;
406 case kTextSkewX_PaintOp: p->setTextSkewX(reader->readScalar()); break;
reed@google.comf5842f72011-05-04 18:30:04 +0000407 case kTypeface_PaintOp: p->setTypeface(state->findTypeface(data)); break;
reed@google.combb6992a2011-04-26 17:41:56 +0000408
409 // flag to reference a cached index instead of inflating?
410 case kPathEffect_PaintOp: inflate_patheffect(reader, p); break;
411 case kShader_PaintOp: inflate_shader(reader, p); break;
412 case kXfermode_PaintOp: inflate_xfermode(reader, p); break;
413 case kMaskFilter_PaintOp: inflate_maskfilter(reader, p); break;
414 case kColorFilter_PaintOp: inflate_colorfilter(reader, p); break;
415 case kRasterizer_PaintOp: inflate_rasterizer(reader, p); break;
416 case kDrawLooper_PaintOp: inflate_drawlooper(reader, p); break;
417 default: SkASSERT(!"bad paintop"); return;
418 }
419 } while (!done);
420}
421
reed@google.comf5842f72011-05-04 18:30:04 +0000422static void defTypeface_rp(SkCanvas*, SkReader32* reader, uint32_t,
423 SkGPipeState* state) {
424 state->addTypeface(reader);
425}
426
reed@google.combb6992a2011-04-26 17:41:56 +0000427///////////////////////////////////////////////////////////////////////////////
428
reed@google.comacd471f2011-05-03 21:26:46 +0000429static void skip_rp(SkCanvas*, SkReader32* reader, uint32_t op32, SkGPipeState*) {
430 size_t bytes = DrawOp_unpackData(op32);
431 (void)reader->skip(bytes);
432}
433
reed@google.combb6992a2011-04-26 17:41:56 +0000434static void done_rp(SkCanvas*, SkReader32*, uint32_t, SkGPipeState*) {}
435
436typedef void (*ReadProc)(SkCanvas*, SkReader32*, uint32_t op32, SkGPipeState*);
437
438static const ReadProc gReadTable[] = {
reed@google.comacd471f2011-05-03 21:26:46 +0000439 skip_rp,
reed@google.combb6992a2011-04-26 17:41:56 +0000440 clipPath_rp,
441 clipRegion_rp,
442 clipRect_rp,
443 concat_rp,
444 drawBitmap_rp,
445 drawBitmapMatrix_rp,
446 drawBitmapRect_rp,
447 drawClear_rp,
448 drawData_rp,
449 drawPaint_rp,
450 drawPath_rp,
451 drawPicture_rp,
452 drawPoints_rp,
453 drawPosText_rp,
454 drawPosTextH_rp,
455 drawRect_rp,
456 drawShape_rp,
457 drawSprite_rp,
458 drawText_rp,
459 drawTextOnPath_rp,
460 drawVertices_rp,
461 restore_rp,
462 rotate_rp,
463 save_rp,
464 saveLayer_rp,
465 scale_rp,
466 setMatrix_rp,
467 skew_rp,
468 translate_rp,
469 paintOp_rp,
reed@google.comf5842f72011-05-04 18:30:04 +0000470 defTypeface_rp,
reed@google.combb6992a2011-04-26 17:41:56 +0000471 done_rp
472};
473
474///////////////////////////////////////////////////////////////////////////////
475
476SkGPipeState::SkGPipeState() {
477 // start out with one paint in default state
478 *fPaints.append() = SkNEW(SkPaint);
479}
480
481SkGPipeState::~SkGPipeState() {
reed@google.comf5842f72011-05-04 18:30:04 +0000482 fTypefaces.unrefAll();
reed@google.combb6992a2011-04-26 17:41:56 +0000483 fPaints.deleteAll();
484}
485
486///////////////////////////////////////////////////////////////////////////////
487
488#include "SkGPipe.h"
489
490SkGPipeReader::SkGPipeReader(SkCanvas* target) {
491 SkSafeRef(target);
492 fCanvas = target;
493 fState = NULL;
494}
495
496SkGPipeReader::~SkGPipeReader() {
497 SkSafeUnref(fCanvas);
498 delete fState;
499}
500
501SkGPipeReader::Status SkGPipeReader::playback(const void* data, size_t length) {
502 if (NULL == fCanvas) {
503 return kError_Status;
504 }
505
506 if (NULL == fState) {
507 fState = new SkGPipeState;
508 }
509
510 const ReadProc* table = gReadTable;
511 SkReader32 reader(data, length);
512 SkCanvas* canvas = fCanvas;
513
514 while (!reader.eof()) {
515 uint32_t op32 = reader.readU32();
516 unsigned op = DrawOp_unpackOp(op32);
517
518 if (op >= SK_ARRAY_COUNT(gReadTable)) {
519 SkDebugf("---- bad op during GPipeState::playback\n");
520 return kError_Status;
521 }
522 if (kDone_DrawOp == op) {
523 return kDone_Status;
524 }
525 table[op](canvas, &reader, op32, fState);
526 }
527 return kEOF_Status;
528}
529
530