blob: 16cb3b5a1bd0ba755ca7e4c52a4e9cc6382d3f27 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 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 */
reed@google.com76f10a32014-02-05 15:32:21 +00007
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkPictureRecord.h"
junov@chromium.orgd575eed2013-05-08 15:39:13 +00009#include "SkDevice.h"
dandovb3c9d1c2014-08-12 08:34:29 -070010#include "SkPatchUtils.h"
dandovb3c9d1c2014-08-12 08:34:29 -070011#include "SkPixelRef.h"
12#include "SkRRect.h"
fmalitab7425172014-08-26 07:56:44 -070013#include "SkTextBlob.h"
dandovb3c9d1c2014-08-12 08:34:29 -070014#include "SkTSearch.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015
reed@android.com8a1c16f2008-12-17 15:59:43 +000016#define HEAP_BLOCK_SIZE 4096
17
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000018enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000019 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000020 kNoInitialSave = -1,
21};
22
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000023// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
24static int const kUInt32Size = 4;
25
Florin Malita5f6102d2014-06-30 10:13:28 -040026static const uint32_t kSaveSize = kUInt32Size;
robertphillips@google.come37ad352013-03-01 19:44:30 +000027static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
28static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
29
robertphillips0bdbea72014-06-11 11:37:55 -070030SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000031 : INHERITED(dimensions.width(), dimensions.height())
robertphillips@google.com5a63f242014-02-04 20:07:50 +000032 , fFlattenableHeap(HEAP_BLOCK_SIZE)
33 , fPaints(&fFlattenableHeap)
mtklein46616af2014-09-30 14:47:10 -070034 , fRecordFlags(flags) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000035
djsollen@google.comc9ab9872012-08-29 18:52:07 +000036 fBitmapHeap = SkNEW(SkBitmapHeap);
37 fFlattenableHeap.setBitmapStorage(fBitmapHeap);
commit-bot@chromium.org8016f792014-03-07 15:53:01 +000038
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +000039 fFirstSavedLayerIndex = kNoSavedLayerIndex;
reed@google.comd86e7ab2012-09-27 20:31:31 +000040 fInitialSaveCount = kNoInitialSave;
reed@android.com8a1c16f2008-12-17 15:59:43 +000041}
42
43SkPictureRecord::~SkPictureRecord() {
djsollen@google.comc9ab9872012-08-29 18:52:07 +000044 SkSafeUnref(fBitmapHeap);
djsollen@google.com21830d92012-08-07 19:49:41 +000045 fFlattenableHeap.setBitmapStorage(NULL);
46 fPictureRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070047 fTextBlobRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000048}
49
50///////////////////////////////////////////////////////////////////////////////
51
robertphillips@google.come37ad352013-03-01 19:44:30 +000052// Return the offset of the paint inside a given op's byte stream. A zero
53// return value means there is no paint (and you really shouldn't be calling
54// this method)
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +000055static inline size_t getPaintOffset(DrawType op, size_t opSize) {
robertphillips@google.come37ad352013-03-01 19:44:30 +000056 // These offsets are where the paint would be if the op size doesn't overflow
fmalita9f49cfd2014-08-12 12:24:17 -070057 static const uint8_t gPaintOffsets[] = {
robertphillips@google.come37ad352013-03-01 19:44:30 +000058 0, // UNUSED - no paint
59 0, // CLIP_PATH - no paint
60 0, // CLIP_REGION - no paint
61 0, // CLIP_RECT - no paint
62 0, // CLIP_RRECT - no paint
63 0, // CONCAT - no paint
64 1, // DRAW_BITMAP - right after op code
65 1, // DRAW_BITMAP_MATRIX - right after op code
66 1, // DRAW_BITMAP_NINE - right after op code
67 1, // DRAW_BITMAP_RECT_TO_RECT - right after op code
68 0, // DRAW_CLEAR - no paint
69 0, // DRAW_DATA - no paint
70 1, // DRAW_OVAL - right after op code
71 1, // DRAW_PAINT - right after op code
72 1, // DRAW_PATH - right after op code
73 0, // DRAW_PICTURE - no paint
74 1, // DRAW_POINTS - right after op code
75 1, // DRAW_POS_TEXT - right after op code
76 1, // DRAW_POS_TEXT_TOP_BOTTOM - right after op code
77 1, // DRAW_POS_TEXT_H - right after op code
78 1, // DRAW_POS_TEXT_H_TOP_BOTTOM - right after op code
79 1, // DRAW_RECT - right after op code
80 1, // DRAW_RRECT - right after op code
81 1, // DRAW_SPRITE - right after op code
82 1, // DRAW_TEXT - right after op code
83 1, // DRAW_TEXT_ON_PATH - right after op code
84 1, // DRAW_TEXT_TOP_BOTTOM - right after op code
85 1, // DRAW_VERTICES - right after op code
86 0, // RESTORE - no paint
87 0, // ROTATE - no paint
88 0, // SAVE - no paint
skia.committer@gmail.comf140f182013-03-02 07:01:56 +000089 0, // SAVE_LAYER - see below - this paint's location varies
robertphillips@google.come37ad352013-03-01 19:44:30 +000090 0, // SCALE - no paint
91 0, // SET_MATRIX - no paint
92 0, // SKEW - no paint
93 0, // TRANSLATE - no paint
94 0, // NOOP - no paint
robertphillips@google.com0a4805e2013-05-29 13:24:23 +000095 0, // BEGIN_GROUP - no paint
96 0, // COMMENT - no paint
97 0, // END_GROUP - no paint
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +000098 1, // DRAWDRRECT - right after op code
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +000099 0, // PUSH_CULL - no paint
100 0, // POP_CULL - no paint
dandov963137b2014-08-07 07:49:53 -0700101 1, // DRAW_PATCH - right after op code
fmalita9f49cfd2014-08-12 12:24:17 -0700102 1, // DRAW_PICTURE_MATRIX_PAINT - right after op code
fmalitab7425172014-08-26 07:56:44 -0700103 1, // DRAW_TEXT_BLOB- right after op code
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000104 };
robertphillips@google.come37ad352013-03-01 19:44:30 +0000105
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000106 SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
107 need_to_be_in_sync);
robertphillips@google.come37ad352013-03-01 19:44:30 +0000108 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
109
110 int overflow = 0;
111 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
112 // This op's size overflows so an extra uint32_t will be written
113 // after the op code
114 overflow = sizeof(uint32_t);
115 }
116
117 if (SAVE_LAYER == op) {
118 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
119 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
120
121 if (kSaveLayerNoBoundsSize == opSize) {
122 return kSaveLayerNoBoundsPaintOffset + overflow;
123 } else {
124 SkASSERT(kSaveLayerWithBoundsSize == opSize);
125 return kSaveLayerWithBoundsPaintOffset + overflow;
126 }
127 }
128
129 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this method
130 return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
131}
132
Florin Malita5f6102d2014-06-30 10:13:28 -0400133void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +0000134 // record the offset to us, making it non-positive to distinguish a save
135 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000136 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -0400137 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000138
Florin Malita5f6102d2014-06-30 10:13:28 -0400139 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000140}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000141
Florin Malita5f6102d2014-06-30 10:13:28 -0400142void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -0700143 fContentInfo.onSave();
144
Florin Malita5f6102d2014-06-30 10:13:28 -0400145 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000146 size_t size = kSaveSize;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000147 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +0000148
robertphillips@google.com8b169312013-10-15 17:47:36 +0000149 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150}
151
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000152SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
153 const SkPaint* paint, SaveFlags flags) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000154 // record the offset to us, making it non-positive to distinguish a save
155 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000156 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000157 this->recordSaveLayer(bounds, paint, flags);
158 if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
159 fFirstSavedLayerIndex = fRestoreOffsetStack.count();
160 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000161
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000162 this->INHERITED::willSaveLayer(bounds, paint, flags);
163 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000164 at this time (and may not be able to afford since during record our
165 clip starts out the size of the picture, which is often much larger
166 than the size of the actual device we'll use during playback).
167 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000168 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000169}
170
171void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000172 SaveFlags flags) {
robertphillipsc019ec42014-08-12 05:35:58 -0700173 fContentInfo.onSaveLayer();
174
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000175 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000176 size_t size = 2 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700177 if (bounds) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000178 size += sizeof(*bounds); // + rect
179 }
180 // + paint index + flags
181 size += 2 * kUInt32Size;
182
robertphillips@google.come37ad352013-03-01 19:44:30 +0000183 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
184
robertphillips@google.com8b169312013-10-15 17:47:36 +0000185 size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000186 this->addRectPtr(bounds);
reed@google.com44699382013-10-31 17:28:30 +0000187 SkASSERT(initialOffset+getPaintOffset(SAVE_LAYER, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000188 this->addPaintPtr(paint);
189 this->addInt(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000190
robertphillips@google.com8b169312013-10-15 17:47:36 +0000191 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192}
193
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000194bool SkPictureRecord::isDrawingToLayer() const {
195 return fFirstSavedLayerIndex != kNoSavedLayerIndex;
196}
197
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000198#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000199/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000200 * Read the op code from 'offset' in 'writer' and extract the size too.
201 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000202static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000203 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000204
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000205 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000206 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000207 if (MASK_24 == *size) {
208 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000209 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000210 }
211 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000212}
mtklein46616af2014-09-30 14:47:10 -0700213#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000214
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000215void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000216 // FIXME: SkDeferredCanvas needs to be refactored to respect
217 // save/restore balancing so that the following test can be
218 // turned on permanently.
219#if 0
220 SkASSERT(fRestoreOffsetStack.count() > 1);
221#endif
222
reed@android.comb4e22d62009-07-09 15:20:25 +0000223 // check for underflow
224 if (fRestoreOffsetStack.count() == 0) {
225 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000227
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000228 if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) {
229 fFirstSavedLayerIndex = kNoSavedLayerIndex;
230 }
231
mtklein46616af2014-09-30 14:47:10 -0700232 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000233
reed@android.comb4e22d62009-07-09 15:20:25 +0000234 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000235
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000236 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000237}
238
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000239void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700240 fContentInfo.onRestore();
241
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000242 if (fillInSkips) {
243 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
244 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000245 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
246 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000247 this->validate(initialOffset, size);
248}
249
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000250void SkPictureRecord::recordTranslate(const SkMatrix& m) {
251 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
252
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000253 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000254 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000255 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000256 this->addScalar(m.getTranslateX());
257 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000258 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259}
260
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000261void SkPictureRecord::recordScale(const SkMatrix& m) {
262 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000263
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000264 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000265 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000266 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000267 this->addScalar(m.getScaleX());
268 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000269 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270}
271
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000272void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000273 switch (matrix.getType()) {
274 case SkMatrix::kTranslate_Mask:
275 this->recordTranslate(matrix);
276 break;
277 case SkMatrix::kScale_Mask:
278 this->recordScale(matrix);
279 break;
280 default:
281 this->recordConcat(matrix);
282 break;
283 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000284 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000285}
286
287void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000288 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000289 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000290 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000291 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000292 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000293 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294}
295
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000296void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000297 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000298 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000299 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000300 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000301 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000302 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000303 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000304}
305
reed@google.com45482d12011-08-29 19:02:39 +0000306static bool regionOpExpands(SkRegion::Op op) {
307 switch (op) {
308 case SkRegion::kUnion_Op:
309 case SkRegion::kXOR_Op:
310 case SkRegion::kReverseDifference_Op:
311 case SkRegion::kReplace_Op:
312 return true;
313 case SkRegion::kIntersect_Op:
314 case SkRegion::kDifference_Op:
315 return false;
316 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000317 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000318 return false;
319 }
320}
321
robertphillips@google.come37ad352013-03-01 19:44:30 +0000322void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000323 int32_t offset = fRestoreOffsetStack.top();
324 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000325 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
326 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000327 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000328 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000329
reed@google.comffacd3c2012-08-30 15:31:23 +0000330#ifdef SK_DEBUG
331 // assert that the final offset value points to a save verb
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000332 uint32_t opSize;
333 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
reed@google.comffacd3c2012-08-30 15:31:23 +0000334 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
335#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000336}
337
reed@google.comd86e7ab2012-09-27 20:31:31 +0000338void SkPictureRecord::beginRecording() {
339 // we have to call this *after* our constructor, to ensure that it gets
340 // recorded. This is balanced by restoreToCount() call from endRecording,
341 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000342 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000343}
344
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000345void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000346 SkASSERT(kNoInitialSave != fInitialSaveCount);
347 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000348}
349
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000350size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000351 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000352 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000353 }
354
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000355 // The RestoreOffset field is initially filled with a placeholder
356 // value that points to the offset of the previous RestoreOffset
357 // in the current stack level, thus forming a linked list so that
358 // the restore offsets can be filled in when the corresponding
359 // restore command is recorded.
360 int32_t prevOffset = fRestoreOffsetStack.top();
361
reed@google.com45482d12011-08-29 19:02:39 +0000362 if (regionOpExpands(op)) {
363 // Run back through any previous clip ops, and mark their offset to
364 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
365 // they could hide this clips ability to expand the clip (i.e. go from
366 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000367 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000368
369 // Reset the pointer back to the previous clip so that subsequent
370 // restores don't overwrite the offsets we just cleared.
371 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000372 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000373
reed@google.com44699382013-10-31 17:28:30 +0000374 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000375 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000376 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000377 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000378}
379
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000380void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000381 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000382 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000383}
384
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000385size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000386 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000387 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000388 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000389 if (!fRestoreOffsetStack.isEmpty()) {
390 // + restore offset
391 size += kUInt32Size;
392 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000393 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000394 this->addRect(rect);
395 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000396 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000397
robertphillips@google.com8b169312013-10-15 17:47:36 +0000398 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000399 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000400}
401
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000402void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000403 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700404 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000405}
406
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000407size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000408 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000409 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000410 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000411 if (!fRestoreOffsetStack.isEmpty()) {
412 // + restore offset
413 size += kUInt32Size;
414 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000415 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000416 this->addRRect(rrect);
417 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000418 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000419 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000420 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000421}
422
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000423void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000424 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000425 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700426 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000427}
428
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000429size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000430 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000431 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000432 // recordRestoreOffsetPlaceholder doesn't always write an offset
433 if (!fRestoreOffsetStack.isEmpty()) {
434 // + restore offset
435 size += kUInt32Size;
436 }
437 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000438 this->addInt(pathID);
439 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000440 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000441 this->validate(initialOffset, size);
442 return offset;
443}
444
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000445void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000446 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000447 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000448}
449
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000450size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000451 // op + clip params + region
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000452 size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000453 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000454 if (!fRestoreOffsetStack.isEmpty()) {
455 // + restore offset
456 size += kUInt32Size;
457 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000458 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000459 this->addRegion(region);
460 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000461 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000462
robertphillips@google.com8b169312013-10-15 17:47:36 +0000463 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000464 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000465}
466
reed@google.com2a981812011-04-14 18:59:28 +0000467void SkPictureRecord::clear(SkColor color) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000468 // op + color
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000469 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000470 size_t initialOffset = this->addDraw(DRAW_CLEAR, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000471 this->addInt(color);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000472 this->validate(initialOffset, size);
reed@google.com2a981812011-04-14 18:59:28 +0000473}
474
reed@android.com8a1c16f2008-12-17 15:59:43 +0000475void SkPictureRecord::drawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000476 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000477 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000478 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
reed@google.com44699382013-10-31 17:28:30 +0000479 SkASSERT(initialOffset+getPaintOffset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000480 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000481 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000482}
483
484void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000485 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700486 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000487
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000488 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000489 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000490 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
reed@google.com44699382013-10-31 17:28:30 +0000491 SkASSERT(initialOffset+getPaintOffset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000492 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700493
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000494 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000495 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000496 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000497 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000498}
499
reed@google.com4ed0fb72012-12-12 20:48:18 +0000500void SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000501 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000502 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000503 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
reed@google.com44699382013-10-31 17:28:30 +0000504 SkASSERT(initialOffset+getPaintOffset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000505 this->addPaint(paint);
506 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000507 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000508}
509
bsalomon@google.com7ce564c2013-10-22 16:54:15 +0000510void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000511 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000512 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000513 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
reed@google.com44699382013-10-31 17:28:30 +0000514 SkASSERT(initialOffset+getPaintOffset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000515 this->addPaint(paint);
516 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000517 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000518}
519
reed@google.com4ed0fb72012-12-12 20:48:18 +0000520void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700521 // op + paint index + rrect
522 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
523 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
524 SkASSERT(initialOffset+getPaintOffset(DRAW_RRECT, size) == fWriter.bytesWritten());
525 this->addPaint(paint);
526 this->addRRect(rrect);
527 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000528}
529
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000530void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
531 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000532 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000533 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
534 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000535 SkASSERT(initialOffset+getPaintOffset(DRAW_DRRECT, size) == fWriter.bytesWritten());
536 this->addPaint(paint);
537 this->addRRect(outer);
538 this->addRRect(inner);
539 this->validate(initialOffset, size);
540}
541
bsalomon@google.com7ce564c2013-10-22 16:54:15 +0000542void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700543 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000544
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000545 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000546 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000547 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
reed@google.com44699382013-10-31 17:28:30 +0000548 SkASSERT(initialOffset+getPaintOffset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000549 this->addPaint(paint);
550 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000551 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000552}
553
554void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000555 const SkPaint* paint = NULL) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000556 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000557 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000558 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
reed@google.com44699382013-10-31 17:28:30 +0000559 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000560 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000561 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000562 this->addScalar(left);
563 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000564 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000565}
566
reed@google.com71121732012-09-18 15:14:33 +0000567void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000568 const SkRect& dst, const SkPaint* paint,
569 DrawBitmapRectFlags flags) {
570 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000571 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700572 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000573 size += sizeof(*src); // + rect
574 }
575 size += sizeof(dst); // + rect
576
robertphillips@google.com8b169312013-10-15 17:47:36 +0000577 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000578 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size)
579 == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000580 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000581 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000582 this->addRectPtr(src); // may be null
583 this->addRect(dst);
584 this->addInt(flags);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000585 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000586}
587
588void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
reed@google.comf0b5e112011-09-07 11:57:34 +0000589 const SkPaint* paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000590 // id + paint index + bitmap index + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000591 size_t size = 3 * kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000592 size_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
reed@google.com44699382013-10-31 17:28:30 +0000593 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_MATRIX, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000594 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000595 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000596 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000597 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000598}
599
reed@google.comf0b5e112011-09-07 11:57:34 +0000600void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
601 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000602 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000603 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000604 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
reed@google.com44699382013-10-31 17:28:30 +0000605 SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000606 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000607 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000608 this->addIRect(center);
609 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000610 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000611}
612
reed@android.com8a1c16f2008-12-17 15:59:43 +0000613void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000614 const SkPaint* paint = NULL) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000615 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000616 size_t size = 5 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000617 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
reed@google.com44699382013-10-31 17:28:30 +0000618 SkASSERT(initialOffset+getPaintOffset(DRAW_SPRITE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000619 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000620 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000621 this->addInt(left);
622 this->addInt(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000623 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000624}
625
reed@google.come0d9ce82014-04-23 04:00:17 +0000626void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
627 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000628 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000629 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000630
mtklein46616af2014-09-30 14:47:10 -0700631 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000632 size_t initialOffset = this->addDraw(op, &size);
reed@google.com44699382013-10-31 17:28:30 +0000633 SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700634 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000635 this->addText(text, byteLength);
636 this->addScalar(x);
637 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000638 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000639}
640
reed@google.come0d9ce82014-04-23 04:00:17 +0000641void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
642 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000643 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000644
mtklein46616af2014-09-30 14:47:10 -0700645 // op + paint index + length + 'length' worth of data + num points + x&y point data
646 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000647
mtklein46616af2014-09-30 14:47:10 -0700648 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000649
robertphillips@google.com8b169312013-10-15 17:47:36 +0000650 size_t initialOffset = this->addDraw(op, &size);
reed@google.com44699382013-10-31 17:28:30 +0000651 SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700652 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000653 this->addText(text, byteLength);
654 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700655 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000656 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000657}
658
reed@google.come0d9ce82014-04-23 04:00:17 +0000659void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
660 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000661 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000662
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000663 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000664 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000665 // + y + the actual points
666 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000667
mtklein46616af2014-09-30 14:47:10 -0700668 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
669 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000670 this->addText(text, byteLength);
671 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000672 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000673 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000674 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000675}
676
reed@google.come0d9ce82014-04-23 04:00:17 +0000677void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
678 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000679 // op + paint index + length + 'length' worth of data + path index + matrix
680 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000681 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000682 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
reed@google.com44699382013-10-31 17:28:30 +0000683 SkASSERT(initialOffset+getPaintOffset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000684 this->addPaint(paint);
685 this->addText(text, byteLength);
686 this->addPath(path);
687 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000688 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000689}
690
fmalitab7425172014-08-26 07:56:44 -0700691void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
692 const SkPaint& paint) {
693
694 // op + paint index + blob index + x/y
695 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
696 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
697 SkASSERT(initialOffset + getPaintOffset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
698
699 this->addPaint(paint);
700 this->addTextBlob(blob);
701 this->addScalar(x);
702 this->addScalar(y);
703
704 this->validate(initialOffset, size);
705}
706
reedd5fa1a42014-08-09 11:08:05 -0700707void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
708 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000709 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000710 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700711 size_t initialOffset;
712
713 if (NULL == matrix && NULL == paint) {
714 initialOffset = this->addDraw(DRAW_PICTURE, &size);
715 this->addPicture(picture);
716 } else {
717 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
718 size += m.writeToMemory(NULL) + kUInt32Size; // matrix + paint
719 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
fmalita9f49cfd2014-08-12 12:24:17 -0700720 SkASSERT(initialOffset + getPaintOffset(DRAW_PICTURE_MATRIX_PAINT, size)
721 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700722 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700723 this->addMatrix(m);
724 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700725 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000726 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000727}
728
729void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
730 const SkPoint vertices[], const SkPoint texs[],
reed@google.com85e143c2013-12-30 15:51:25 +0000731 const SkColor colors[], SkXfermode* xfer,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000732 const uint16_t indices[], int indexCount,
733 const SkPaint& paint) {
734 uint32_t flags = 0;
735 if (texs) {
736 flags |= DRAW_VERTICES_HAS_TEXS;
737 }
738 if (colors) {
739 flags |= DRAW_VERTICES_HAS_COLORS;
740 }
741 if (indexCount > 0) {
742 flags |= DRAW_VERTICES_HAS_INDICES;
743 }
bsalomon49f085d2014-09-05 13:34:00 -0700744 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000745 SkXfermode::Mode mode;
746 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
747 flags |= DRAW_VERTICES_HAS_XFER;
748 }
749 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000750
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000751 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000752 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000753 if (flags & DRAW_VERTICES_HAS_TEXS) {
754 size += vertexCount * sizeof(SkPoint); // + uvs
755 }
756 if (flags & DRAW_VERTICES_HAS_COLORS) {
757 size += vertexCount * sizeof(SkColor); // + vert colors
758 }
759 if (flags & DRAW_VERTICES_HAS_INDICES) {
760 // + num indices + indices
761 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
762 }
reed@google.com85e143c2013-12-30 15:51:25 +0000763 if (flags & DRAW_VERTICES_HAS_XFER) {
764 size += kUInt32Size; // mode enum
765 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000766
robertphillips@google.com8b169312013-10-15 17:47:36 +0000767 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
reed@google.com44699382013-10-31 17:28:30 +0000768 SkASSERT(initialOffset+getPaintOffset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000769 this->addPaint(paint);
770 this->addInt(flags);
771 this->addInt(vmode);
772 this->addInt(vertexCount);
773 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000774 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000775 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000776 }
777 if (flags & DRAW_VERTICES_HAS_COLORS) {
778 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
779 }
780 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000781 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000782 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
783 }
reed@google.com85e143c2013-12-30 15:51:25 +0000784 if (flags & DRAW_VERTICES_HAS_XFER) {
785 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
786 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000787 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000788 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000789 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000790}
791
dandovb3c9d1c2014-08-12 08:34:29 -0700792void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
793 const SkPoint texCoords[4], SkXfermode* xmode,
794 const SkPaint& paint) {
795 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
796 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
797 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700798 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700799 flag |= DRAW_VERTICES_HAS_COLORS;
800 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
801 }
bsalomon49f085d2014-09-05 13:34:00 -0700802 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700803 flag |= DRAW_VERTICES_HAS_TEXS;
804 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
805 }
bsalomon49f085d2014-09-05 13:34:00 -0700806 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700807 SkXfermode::Mode mode;
808 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
809 flag |= DRAW_VERTICES_HAS_XFER;
810 size += kUInt32Size;
811 }
812 }
mtklein46616af2014-09-30 14:47:10 -0700813
dandov963137b2014-08-07 07:49:53 -0700814 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
815 SkASSERT(initialOffset+getPaintOffset(DRAW_PATCH, size) == fWriter.bytesWritten());
816 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700817 this->addPatch(cubics);
818 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700819
dandovb3c9d1c2014-08-12 08:34:29 -0700820 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700821 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700822 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
823 }
bsalomon49f085d2014-09-05 13:34:00 -0700824 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700825 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
826 }
827 if (flag & DRAW_VERTICES_HAS_XFER) {
828 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
829 xmode->asMode(&mode);
830 this->addInt(mode);
831 }
dandov963137b2014-08-07 07:49:53 -0700832 this->validate(initialOffset, size);
833}
834
reed@android.comcb608442009-12-04 21:32:27 +0000835void SkPictureRecord::drawData(const void* data, size_t length) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000836 // op + length + 'length' worth of data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000837 size_t size = 2 * kUInt32Size + SkAlign4(length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000838 size_t initialOffset = this->addDraw(DRAW_DATA, &size);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000839 this->addInt(SkToInt(length));
reed@android.comcb608442009-12-04 21:32:27 +0000840 fWriter.writePad(data, length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000841 this->validate(initialOffset, size);
reed@android.comcb608442009-12-04 21:32:27 +0000842}
843
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000844void SkPictureRecord::beginCommentGroup(const char* description) {
845 // op/size + length of string + \0 terminated chars
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000846 size_t length = strlen(description);
847 size_t size = 2 * kUInt32Size + SkAlign4(length + 1);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000848 size_t initialOffset = this->addDraw(BEGIN_COMMENT_GROUP, &size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000849 fWriter.writeString(description, length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000850 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000851}
852
853void SkPictureRecord::addComment(const char* kywd, const char* value) {
854 // op/size + 2x length of string + 2x \0 terminated chars
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000855 size_t kywdLen = strlen(kywd);
856 size_t valueLen = strlen(value);
857 size_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000858 size_t initialOffset = this->addDraw(COMMENT, &size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000859 fWriter.writeString(kywd, kywdLen);
860 fWriter.writeString(value, valueLen);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000861 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000862}
863
864void SkPictureRecord::endCommentGroup() {
865 // op/size
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000866 size_t size = 1 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000867 size_t initialOffset = this->addDraw(END_COMMENT_GROUP, &size);
868 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000869}
870
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000871// [op/size] [rect] [skip offset]
872static const uint32_t kPushCullOpSize = 2 * kUInt32Size + sizeof(SkRect);
873void SkPictureRecord::onPushCull(const SkRect& cullRect) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000874 size_t size = kPushCullOpSize;
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000875 size_t initialOffset = this->addDraw(PUSH_CULL, &size);
876 // PUSH_CULL's size should stay constant (used to rewind).
877 SkASSERT(size == kPushCullOpSize);
878
879 this->addRect(cullRect);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000880 fCullOffsetStack.push(SkToU32(fWriter.bytesWritten()));
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000881 this->addInt(0);
882 this->validate(initialOffset, size);
883}
884
885void SkPictureRecord::onPopCull() {
886 SkASSERT(!fCullOffsetStack.isEmpty());
887
888 uint32_t cullSkipOffset = fCullOffsetStack.top();
889 fCullOffsetStack.pop();
890
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000891 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000892 size_t size = kUInt32Size;
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000893 size_t initialOffset = this->addDraw(POP_CULL, &size);
894
895 // update the cull skip offset to point past this op.
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000896 fWriter.overwriteTAt<uint32_t>(cullSkipOffset, SkToU32(fWriter.bytesWritten()));
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000897
898 this->validate(initialOffset, size);
899}
900
reed@android.com8a1c16f2008-12-17 15:59:43 +0000901///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000902
reed4a8126e2014-09-22 07:29:03 -0700903SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000904 return NULL;
reed@google.com76f10a32014-02-05 15:32:21 +0000905}
906
commit-bot@chromium.org8016f792014-03-07 15:53:01 +0000907int SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
scroggo@google.com4b90b112012-12-04 15:08:56 +0000908 const int index = fBitmapHeap->insert(bitmap);
909 // In debug builds, a bad return value from insert() will crash, allowing for debugging. In
910 // release builds, the invalid value will be recorded so that the reader will know that there
911 // was a problem.
912 SkASSERT(index != SkBitmapHeap::INVALID_SLOT);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000913 this->addInt(index);
commit-bot@chromium.org8016f792014-03-07 15:53:01 +0000914 return index;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000915}
916
917void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000918 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000919}
920
mtklein46616af2014-09-30 14:47:10 -0700921void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700922 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000923
mtklein46616af2014-09-30 14:47:10 -0700924 if (paint) {
925 const SkFlatData* flat = fPaints.findAndReturnFlat(*paint);
926 SkASSERT(flat && flat->index() != 0);
927 this->addInt(flat->index());
928 } else {
929 this->addInt(0);
930 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000931}
932
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000933int SkPictureRecord::addPathToHeap(const SkPath& path) {
robertphillips0bdbea72014-06-11 11:37:55 -0700934 if (NULL == fPathHeap) {
935 fPathHeap.reset(SkNEW(SkPathHeap));
936 }
937#ifdef SK_DEDUP_PICTURE_PATHS
938 return fPathHeap->insert(path);
939#else
940 return fPathHeap->append(path);
941#endif
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000942}
943
944void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000945 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000946}
947
dandovb3c9d1c2014-08-12 08:34:29 -0700948void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
949 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700950}
951
robertphillips9b14f262014-06-04 05:40:44 -0700952void SkPictureRecord::addPicture(const SkPicture* picture) {
953 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000954 if (index < 0) { // not found
955 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700956 *fPictureRefs.append() = picture;
957 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000958 }
959 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000960 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000961}
962
963void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000964 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000965}
reed@google.com82065d62011-02-07 15:30:46 +0000966
reed@android.com8a1c16f2008-12-17 15:59:43 +0000967void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
968 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000969}
970
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000971void SkPictureRecord::addNoOp() {
972 size_t size = kUInt32Size; // op
973 this->addDraw(NOOP, &size);
974}
975
reed@android.com8a1c16f2008-12-17 15:59:43 +0000976void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000977 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000978}
979
980void SkPictureRecord::addRectPtr(const SkRect* rect) {
981 if (fWriter.writeBool(rect != NULL)) {
982 fWriter.writeRect(*rect);
983 }
984}
985
reed@google.comf0b5e112011-09-07 11:57:34 +0000986void SkPictureRecord::addIRect(const SkIRect& rect) {
987 fWriter.write(&rect, sizeof(rect));
988}
989
reed@android.com8a1c16f2008-12-17 15:59:43 +0000990void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
991 if (fWriter.writeBool(rect != NULL)) {
992 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
993 }
994}
995
reed@google.com4ed0fb72012-12-12 20:48:18 +0000996void SkPictureRecord::addRRect(const SkRRect& rrect) {
997 fWriter.writeRRect(rrect);
998}
999
reed@android.com8a1c16f2008-12-17 15:59:43 +00001000void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001001 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001002}
1003
1004void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001005 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001006 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001007 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001008}
1009
fmalitab7425172014-08-26 07:56:44 -07001010void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001011 int index = fTextBlobRefs.count();
1012 *fTextBlobRefs.append() = blob;
1013 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001014 // follow the convention of recording a 1-based index
1015 this->addInt(index + 1);
1016}
1017
reed@android.com8a1c16f2008-12-17 15:59:43 +00001018///////////////////////////////////////////////////////////////////////////////
1019