Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkPicturePlayback.cpp
1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkCanvas.h"
9 #include "SkPatchUtils.h"
10 #include "SkPictureData.h"
11 #include "SkPicturePlayback.h"
12 #include "SkPictureRecord.h"
13 #include "SkReader32.h"
14 #include "SkTextBlob.h"
15 #include "SkTDArray.h"
16 #include "SkTypes.h"
17
18 /*
19  * Read the next op code and chunk size from 'reader'. The returned size
20  * is the entire size of the chunk (including the opcode). Thus, the
21  * offset just prior to calling ReadOpAndSize + 'size' is the offset
22  * to the next chunk's op code. This also means that the size of a chunk
23  * with no arguments (just an opcode) will be 4.
24  */
25 DrawType SkPicturePlayback::ReadOpAndSize(SkReader32* reader, uint32_t* size) {
26     uint32_t temp = reader->readInt();
27     uint32_t op;
28     if (((uint8_t)temp) == temp) {
29         // old skp file - no size information
30         op = temp;
31         *size = 0;
32     } else {
33         UNPACK_8_24(temp, op, *size);
34         if (MASK_24 == *size) {
35             *size = reader->readInt();
36         }
37     }
38     return (DrawType)op;
39 }
40
41
42 static const SkRect* get_rect_ptr(SkReader32* reader) {
43     if (reader->readBool()) {
44         return &reader->skipT<SkRect>();
45     } else {
46         return NULL;
47     }
48 }
49
50 class TextContainer {
51 public:
52     size_t length() { return fByteLength; }
53     const void* text() { return (const void*)fText; }
54     size_t fByteLength;
55     const char* fText;
56 };
57
58 void get_text(SkReader32* reader, TextContainer* text) {
59     size_t length = text->fByteLength = reader->readInt();
60     text->fText = (const char*)reader->skip(length);
61 }
62
63 // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
64 static SkBitmap shallow_copy(const SkBitmap& bitmap) {
65     return bitmap;
66 }
67
68 void SkPicturePlayback::draw(SkCanvas* canvas, SkDrawPictureCallback* callback) {
69     AutoResetOpID aroi(this);
70     SkASSERT(0 == fCurOffset);
71
72     SkReader32 reader(fPictureData->opData()->bytes(), fPictureData->opData()->size());
73
74     // Record this, so we can concat w/ it if we encounter a setMatrix()
75     SkMatrix initialMatrix = canvas->getTotalMatrix();
76
77     SkAutoCanvasRestore acr(canvas, false);
78
79     while (!reader.eof()) {
80         if (callback && callback->abortDrawing()) {
81             return;
82         }
83
84         fCurOffset = reader.offset();
85         uint32_t size;
86         DrawType op = ReadOpAndSize(&reader, &size);
87
88         this->handleOp(&reader, op, size, canvas, initialMatrix);
89     }
90 }
91
92 void SkPicturePlayback::handleOp(SkReader32* reader,
93                                  DrawType op,
94                                  uint32_t size,
95                                  SkCanvas* canvas,
96                                  const SkMatrix& initialMatrix) {
97     switch (op) {
98         case NOOP: {
99             SkASSERT(size >= 4);
100             reader->skip(size - 4);
101         } break;
102         case CLIP_PATH: {
103             const SkPath& path = fPictureData->getPath(reader);
104             uint32_t packed = reader->readInt();
105             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
106             bool doAA = ClipParams_unpackDoAA(packed);
107             size_t offsetToRestore = reader->readInt();
108             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
109             canvas->clipPath(path, regionOp, doAA);
110             if (canvas->isClipEmpty() && offsetToRestore) {
111                 reader->setOffset(offsetToRestore);
112             }
113         } break;
114         case CLIP_REGION: {
115             SkRegion region;
116             reader->readRegion(&region);
117             uint32_t packed = reader->readInt();
118             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
119             size_t offsetToRestore = reader->readInt();
120             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
121             canvas->clipRegion(region, regionOp);
122             if (canvas->isClipEmpty() && offsetToRestore) {
123                 reader->setOffset(offsetToRestore);
124             }
125         } break;
126         case CLIP_RECT: {
127             const SkRect& rect = reader->skipT<SkRect>();
128             uint32_t packed = reader->readInt();
129             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
130             bool doAA = ClipParams_unpackDoAA(packed);
131             size_t offsetToRestore = reader->readInt();
132             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
133             canvas->clipRect(rect, regionOp, doAA);
134             if (canvas->isClipEmpty() && offsetToRestore) {
135                 reader->setOffset(offsetToRestore);
136             }
137         } break;
138         case CLIP_RRECT: {
139             SkRRect rrect;
140             reader->readRRect(&rrect);
141             uint32_t packed = reader->readInt();
142             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
143             bool doAA = ClipParams_unpackDoAA(packed);
144             size_t offsetToRestore = reader->readInt();
145             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
146             canvas->clipRRect(rrect, regionOp, doAA);
147             if (canvas->isClipEmpty() && offsetToRestore) {
148                 reader->setOffset(offsetToRestore);
149             }
150         } break;
151         case PUSH_CULL: {
152             const SkRect& cullRect = reader->skipT<SkRect>();
153             size_t offsetToRestore = reader->readInt();
154             if (offsetToRestore && canvas->quickReject(cullRect)) {
155                 reader->setOffset(offsetToRestore);
156             } else {
157                 canvas->pushCull(cullRect);
158             }
159         } break;
160         case POP_CULL:
161             canvas->popCull();
162             break;
163         case CONCAT: {
164             SkMatrix matrix;
165             reader->readMatrix(&matrix);
166             canvas->concat(matrix);
167             break;
168         }
169         case DRAW_BITMAP: {
170             const SkPaint* paint = fPictureData->getPaint(reader);
171             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
172             const SkPoint& loc = reader->skipT<SkPoint>();
173             canvas->drawBitmap(bitmap, loc.fX, loc.fY, paint);
174         } break;
175         case DRAW_BITMAP_RECT_TO_RECT: {
176             const SkPaint* paint = fPictureData->getPaint(reader);
177             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
178             const SkRect* src = get_rect_ptr(reader);   // may be null
179             const SkRect& dst = reader->skipT<SkRect>();     // required
180             SkCanvas::DrawBitmapRectFlags flags;
181             flags = (SkCanvas::DrawBitmapRectFlags) reader->readInt();
182             canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags);
183         } break;
184         case DRAW_BITMAP_MATRIX: {
185             const SkPaint* paint = fPictureData->getPaint(reader);
186             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
187             SkMatrix matrix;
188             reader->readMatrix(&matrix);
189             canvas->drawBitmapMatrix(bitmap, matrix, paint);
190         } break;
191         case DRAW_BITMAP_NINE: {
192             const SkPaint* paint = fPictureData->getPaint(reader);
193             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
194             const SkIRect& src = reader->skipT<SkIRect>();
195             const SkRect& dst = reader->skipT<SkRect>();
196             canvas->drawBitmapNine(bitmap, src, dst, paint);
197         } break;
198         case DRAW_CLEAR:
199             canvas->clear(reader->readInt());
200             break;
201         case DRAW_DATA: {
202             size_t length = reader->readInt();
203             canvas->drawData(reader->skip(length), length);
204             // skip handles padding the read out to a multiple of 4
205         } break;
206         case DRAW_DRRECT: {
207             const SkPaint& paint = *fPictureData->getPaint(reader);
208             SkRRect outer, inner;
209             reader->readRRect(&outer);
210             reader->readRRect(&inner);
211             canvas->drawDRRect(outer, inner, paint);
212         } break;
213         case BEGIN_COMMENT_GROUP: {
214             const char* desc = reader->readString();
215             canvas->beginCommentGroup(desc);
216         } break;
217         case COMMENT: {
218             const char* kywd = reader->readString();
219             const char* value = reader->readString();
220             canvas->addComment(kywd, value);
221         } break;
222         case END_COMMENT_GROUP: {
223             canvas->endCommentGroup();
224         } break;
225         case DRAW_OVAL: {
226             const SkPaint& paint = *fPictureData->getPaint(reader);
227             canvas->drawOval(reader->skipT<SkRect>(), paint);
228         } break;
229         case DRAW_PAINT:
230             canvas->drawPaint(*fPictureData->getPaint(reader));
231             break;
232         case DRAW_PATCH: {
233             const SkPaint& paint = *fPictureData->getPaint(reader);
234
235             const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts *
236                                                                  sizeof(SkPoint));
237             uint32_t flag = reader->readInt();
238             const SkColor* colors = NULL;
239             if (flag & DRAW_VERTICES_HAS_COLORS) {
240                 colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor));
241             }
242             const SkPoint* texCoords = NULL;
243             if (flag & DRAW_VERTICES_HAS_TEXS) {
244                 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
245                                                          sizeof(SkPoint));
246             }
247             SkAutoTUnref<SkXfermode> xfer;
248             if (flag & DRAW_VERTICES_HAS_XFER) {
249                 int mode = reader->readInt();
250                 if (mode < 0 || mode > SkXfermode::kLastMode) {
251                     mode = SkXfermode::kModulate_Mode;
252                 }
253                 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
254             }
255             canvas->drawPatch(cubics, colors, texCoords, xfer, paint);
256         } break;
257         case DRAW_PATH: {
258             const SkPaint& paint = *fPictureData->getPaint(reader);
259             canvas->drawPath(fPictureData->getPath(reader), paint);
260         } break;
261         case DRAW_PICTURE:
262             canvas->drawPicture(fPictureData->getPicture(reader));
263             break;
264         case DRAW_PICTURE_MATRIX_PAINT: {
265             const SkPaint* paint = fPictureData->getPaint(reader);
266             SkMatrix matrix;
267             reader->readMatrix(&matrix);
268             const SkPicture* pic = fPictureData->getPicture(reader);
269             canvas->drawPicture(pic, &matrix, paint);
270         } break;
271         case DRAW_POINTS: {
272             const SkPaint& paint = *fPictureData->getPaint(reader);
273             SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
274             size_t count = reader->readInt();
275             const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count);
276             canvas->drawPoints(mode, count, pts, paint);
277         } break;
278         case DRAW_POS_TEXT: {
279             const SkPaint& paint = *fPictureData->getPaint(reader);
280             TextContainer text;
281             get_text(reader, &text);
282             size_t points = reader->readInt();
283             const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
284             canvas->drawPosText(text.text(), text.length(), pos, paint);
285         } break;
286         case DRAW_POS_TEXT_TOP_BOTTOM: {
287             const SkPaint& paint = *fPictureData->getPaint(reader);
288             TextContainer text;
289             get_text(reader, &text);
290             size_t points = reader->readInt();
291             const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
292             const SkScalar top = reader->readScalar();
293             const SkScalar bottom = reader->readScalar();
294             if (!canvas->quickRejectY(top, bottom)) {
295                 canvas->drawPosText(text.text(), text.length(), pos, paint);
296             }
297         } break;
298         case DRAW_POS_TEXT_H: {
299             const SkPaint& paint = *fPictureData->getPaint(reader);
300             TextContainer text;
301             get_text(reader, &text);
302             size_t xCount = reader->readInt();
303             const SkScalar constY = reader->readScalar();
304             const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar));
305             canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
306         } break;
307         case DRAW_POS_TEXT_H_TOP_BOTTOM: {
308             const SkPaint& paint = *fPictureData->getPaint(reader);
309             TextContainer text;
310             get_text(reader, &text);
311             size_t xCount = reader->readInt();
312             const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar));
313             const SkScalar top = *xpos++;
314             const SkScalar bottom = *xpos++;
315             const SkScalar constY = *xpos++;
316             if (!canvas->quickRejectY(top, bottom)) {
317                 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
318             }
319         } break;
320         case DRAW_RECT: {
321             const SkPaint& paint = *fPictureData->getPaint(reader);
322             canvas->drawRect(reader->skipT<SkRect>(), paint);
323         } break;
324         case DRAW_RRECT: {
325             const SkPaint& paint = *fPictureData->getPaint(reader);
326             SkRRect rrect;
327             reader->readRRect(&rrect);
328             canvas->drawRRect(rrect, paint);
329         } break;
330         case DRAW_SPRITE: {
331             const SkPaint* paint = fPictureData->getPaint(reader);
332             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
333             int left = reader->readInt();
334             int top = reader->readInt();
335             canvas->drawSprite(bitmap, left, top, paint);
336         } break;
337         case DRAW_TEXT: {
338             const SkPaint& paint = *fPictureData->getPaint(reader);
339             TextContainer text;
340             get_text(reader, &text);
341             SkScalar x = reader->readScalar();
342             SkScalar y = reader->readScalar();
343             canvas->drawText(text.text(), text.length(), x, y, paint);
344         } break;
345         case DRAW_TEXT_BLOB: {
346             const SkPaint& paint = *fPictureData->getPaint(reader);
347             const SkTextBlob* blob = fPictureData->getTextBlob(reader);
348             SkScalar x = reader->readScalar();
349             SkScalar y = reader->readScalar();
350             canvas->drawTextBlob(blob, x, y, paint);
351         } break;
352         case DRAW_TEXT_TOP_BOTTOM: {
353             const SkPaint& paint = *fPictureData->getPaint(reader);
354             TextContainer text;
355             get_text(reader, &text);
356             const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
357             // ptr[0] == x
358             // ptr[1] == y
359             // ptr[2] == top
360             // ptr[3] == bottom
361             if (!canvas->quickRejectY(ptr[2], ptr[3])) {
362                 canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], paint);
363             }
364         } break;
365         case DRAW_TEXT_ON_PATH: {
366             const SkPaint& paint = *fPictureData->getPaint(reader);
367             TextContainer text;
368             get_text(reader, &text);
369             const SkPath& path = fPictureData->getPath(reader);
370             SkMatrix matrix;
371             reader->readMatrix(&matrix);
372             canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
373         } break;
374         case DRAW_VERTICES: {
375             SkAutoTUnref<SkXfermode> xfer;
376             const SkPaint& paint = *fPictureData->getPaint(reader);
377             DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
378             SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt();
379             int vCount = reader->readInt();
380             const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
381             const SkPoint* texs = NULL;
382             const SkColor* colors = NULL;
383             const uint16_t* indices = NULL;
384             int iCount = 0;
385             if (flags & DRAW_VERTICES_HAS_TEXS) {
386                 texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
387             }
388             if (flags & DRAW_VERTICES_HAS_COLORS) {
389                 colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor));
390             }
391             if (flags & DRAW_VERTICES_HAS_INDICES) {
392                 iCount = reader->readInt();
393                 indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
394             }
395             if (flags & DRAW_VERTICES_HAS_XFER) {
396                 int mode = reader->readInt();
397                 if (mode < 0 || mode > SkXfermode::kLastMode) {
398                     mode = SkXfermode::kModulate_Mode;
399                 }
400                 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
401             }
402             canvas->drawVertices(vmode, vCount, verts, texs, colors, xfer, indices, iCount, paint);
403         } break;
404         case RESTORE:
405             canvas->restore();
406             break;
407         case ROTATE:
408             canvas->rotate(reader->readScalar());
409             break;
410         case SAVE:
411             // SKPs with version < 29 also store a SaveFlags param.
412             if (size > 4) {
413                 SkASSERT(8 == size);
414                 reader->readInt();
415             }
416             canvas->save();
417             break;
418         case SAVE_LAYER: {
419             const SkRect* boundsPtr = get_rect_ptr(reader);
420             const SkPaint* paint = fPictureData->getPaint(reader);
421             canvas->saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader->readInt());
422         } break;
423         case SCALE: {
424             SkScalar sx = reader->readScalar();
425             SkScalar sy = reader->readScalar();
426             canvas->scale(sx, sy);
427         } break;
428         case SET_MATRIX: {
429             SkMatrix matrix;
430             reader->readMatrix(&matrix);
431             matrix.postConcat(initialMatrix);
432             canvas->setMatrix(matrix);
433         } break;
434         case SKEW: {
435             SkScalar sx = reader->readScalar();
436             SkScalar sy = reader->readScalar();
437             canvas->skew(sx, sy);
438         } break;
439         case TRANSLATE: {
440             SkScalar dx = reader->readScalar();
441             SkScalar dy = reader->readScalar();
442             canvas->translate(dx, dy);
443         } break;
444         default:
445             SkASSERTF(false, "Unknown draw type: %d", op);
446     }
447 }
448