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