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