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