blob: 32033b52db4cc740f45cfd6a7fbaba8c1330ef22 [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"
reeda85d4d02015-05-06 12:56:48 -070010#include "SkImage_Base.h"
dandovb3c9d1c2014-08-12 08:34:29 -070011#include "SkPatchUtils.h"
dandovb3c9d1c2014-08-12 08:34:29 -070012#include "SkPixelRef.h"
13#include "SkRRect.h"
fmalitab7425172014-08-26 07:56:44 -070014#include "SkTextBlob.h"
dandovb3c9d1c2014-08-12 08:34:29 -070015#include "SkTSearch.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000016
reed@android.com8a1c16f2008-12-17 15:59:43 +000017#define HEAP_BLOCK_SIZE 4096
18
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000019enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000020 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000021 kNoInitialSave = -1,
22};
23
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000024// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
25static int const kUInt32Size = 4;
26
Florin Malita5f6102d2014-06-30 10:13:28 -040027static const uint32_t kSaveSize = kUInt32Size;
mtklein8e126562014-10-01 09:29:35 -070028#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000029static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
30static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
mtklein8e126562014-10-01 09:29:35 -070031#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000032
robertphillips0bdbea72014-06-11 11:37:55 -070033SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000034 : INHERITED(dimensions.width(), dimensions.height())
mtklein71a23632014-11-12 10:24:55 -080035 , fRecordFlags(flags)
36 , fInitialSaveCount(kNoInitialSave) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000037}
38
39SkPictureRecord::~SkPictureRecord() {
robertphillips5351aad2015-06-23 06:54:56 -070040 fImageRefs.unrefAll();
djsollen@google.com21830d92012-08-07 19:49:41 +000041 fPictureRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070042 fTextBlobRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000043}
44
45///////////////////////////////////////////////////////////////////////////////
46
mtklein8e126562014-10-01 09:29:35 -070047#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000048// Return the offset of the paint inside a given op's byte stream. A zero
49// return value means there is no paint (and you really shouldn't be calling
50// this method)
mtklein8e126562014-10-01 09:29:35 -070051static inline size_t get_paint_offset(DrawType op, size_t opSize) {
robertphillips@google.come37ad352013-03-01 19:44:30 +000052 // These offsets are where the paint would be if the op size doesn't overflow
fmalita9f49cfd2014-08-12 12:24:17 -070053 static const uint8_t gPaintOffsets[] = {
robertphillips@google.come37ad352013-03-01 19:44:30 +000054 0, // UNUSED - no paint
55 0, // CLIP_PATH - no paint
56 0, // CLIP_REGION - no paint
57 0, // CLIP_RECT - no paint
58 0, // CLIP_RRECT - no paint
59 0, // CONCAT - no paint
60 1, // DRAW_BITMAP - right after op code
Florin Malitac54d8db2014-12-10 12:02:16 -050061 1, // DRAW_BITMAP_MATRIX - right after op code, deprecated
robertphillips@google.come37ad352013-03-01 19:44:30 +000062 1, // DRAW_BITMAP_NINE - right after op code
63 1, // DRAW_BITMAP_RECT_TO_RECT - right after op code
64 0, // DRAW_CLEAR - no paint
65 0, // DRAW_DATA - no paint
66 1, // DRAW_OVAL - right after op code
67 1, // DRAW_PAINT - right after op code
68 1, // DRAW_PATH - right after op code
69 0, // DRAW_PICTURE - no paint
70 1, // DRAW_POINTS - right after op code
71 1, // DRAW_POS_TEXT - right after op code
72 1, // DRAW_POS_TEXT_TOP_BOTTOM - right after op code
73 1, // DRAW_POS_TEXT_H - right after op code
74 1, // DRAW_POS_TEXT_H_TOP_BOTTOM - right after op code
75 1, // DRAW_RECT - right after op code
76 1, // DRAW_RRECT - right after op code
77 1, // DRAW_SPRITE - right after op code
78 1, // DRAW_TEXT - right after op code
79 1, // DRAW_TEXT_ON_PATH - right after op code
80 1, // DRAW_TEXT_TOP_BOTTOM - right after op code
81 1, // DRAW_VERTICES - right after op code
82 0, // RESTORE - no paint
83 0, // ROTATE - no paint
84 0, // SAVE - no paint
skia.committer@gmail.comf140f182013-03-02 07:01:56 +000085 0, // SAVE_LAYER - see below - this paint's location varies
robertphillips@google.come37ad352013-03-01 19:44:30 +000086 0, // SCALE - no paint
87 0, // SET_MATRIX - no paint
88 0, // SKEW - no paint
89 0, // TRANSLATE - no paint
90 0, // NOOP - no paint
robertphillips@google.com0a4805e2013-05-29 13:24:23 +000091 0, // BEGIN_GROUP - no paint
92 0, // COMMENT - no paint
93 0, // END_GROUP - no paint
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +000094 1, // DRAWDRRECT - right after op code
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +000095 0, // PUSH_CULL - no paint
96 0, // POP_CULL - no paint
dandov963137b2014-08-07 07:49:53 -070097 1, // DRAW_PATCH - right after op code
fmalita9f49cfd2014-08-12 12:24:17 -070098 1, // DRAW_PICTURE_MATRIX_PAINT - right after op code
fmalitab7425172014-08-26 07:56:44 -070099 1, // DRAW_TEXT_BLOB- right after op code
reed871872f2015-06-22 12:48:26 -0700100 1, // DRAW_IMAGE - right after op code
101 1, // DRAW_IMAGE_RECT - right after op code
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000102 };
robertphillips@google.come37ad352013-03-01 19:44:30 +0000103
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000104 SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
105 need_to_be_in_sync);
robertphillips@google.come37ad352013-03-01 19:44:30 +0000106 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
107
108 int overflow = 0;
109 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
110 // This op's size overflows so an extra uint32_t will be written
111 // after the op code
112 overflow = sizeof(uint32_t);
113 }
114
115 if (SAVE_LAYER == op) {
116 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
117 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
118
119 if (kSaveLayerNoBoundsSize == opSize) {
120 return kSaveLayerNoBoundsPaintOffset + overflow;
121 } else {
122 SkASSERT(kSaveLayerWithBoundsSize == opSize);
123 return kSaveLayerWithBoundsPaintOffset + overflow;
124 }
125 }
126
127 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this method
128 return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
129}
mtklein8e126562014-10-01 09:29:35 -0700130#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +0000131
Florin Malita5f6102d2014-06-30 10:13:28 -0400132void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +0000133 // record the offset to us, making it non-positive to distinguish a save
134 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000135 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -0400136 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000137
Florin Malita5f6102d2014-06-30 10:13:28 -0400138 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000139}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000140
Florin Malita5f6102d2014-06-30 10:13:28 -0400141void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -0700142 fContentInfo.onSave();
143
Florin Malita5f6102d2014-06-30 10:13:28 -0400144 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000145 size_t size = kSaveSize;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000146 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +0000147
robertphillips@google.com8b169312013-10-15 17:47:36 +0000148 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149}
150
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000151SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
152 const SkPaint* paint, SaveFlags flags) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000153 // record the offset to us, making it non-positive to distinguish a save
154 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000155 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000156 this->recordSaveLayer(bounds, paint, flags);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000157
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000158 this->INHERITED::willSaveLayer(bounds, paint, flags);
159 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000160 at this time (and may not be able to afford since during record our
161 clip starts out the size of the picture, which is often much larger
162 than the size of the actual device we'll use during playback).
163 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000164 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000165}
166
167void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000168 SaveFlags flags) {
robertphillipsc019ec42014-08-12 05:35:58 -0700169 fContentInfo.onSaveLayer();
170
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000171 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000172 size_t size = 2 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700173 if (bounds) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000174 size += sizeof(*bounds); // + rect
175 }
176 // + paint index + flags
177 size += 2 * kUInt32Size;
178
robertphillips@google.come37ad352013-03-01 19:44:30 +0000179 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
180
robertphillips@google.com8b169312013-10-15 17:47:36 +0000181 size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000182 this->addRectPtr(bounds);
mtklein8e126562014-10-01 09:29:35 -0700183 SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000184 this->addPaintPtr(paint);
185 this->addInt(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186
robertphillips@google.com8b169312013-10-15 17:47:36 +0000187 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188}
189
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000190#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000191/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000192 * Read the op code from 'offset' in 'writer' and extract the size too.
193 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000194static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000195 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000196
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000197 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000198 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000199 if (MASK_24 == *size) {
200 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000201 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000202 }
203 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000204}
mtklein46616af2014-09-30 14:47:10 -0700205#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000206
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000207void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000208 // FIXME: SkDeferredCanvas needs to be refactored to respect
209 // save/restore balancing so that the following test can be
210 // turned on permanently.
211#if 0
212 SkASSERT(fRestoreOffsetStack.count() > 1);
213#endif
214
reed@android.comb4e22d62009-07-09 15:20:25 +0000215 // check for underflow
216 if (fRestoreOffsetStack.count() == 0) {
217 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000218 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000219
mtklein46616af2014-09-30 14:47:10 -0700220 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000221
reed@android.comb4e22d62009-07-09 15:20:25 +0000222 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000223
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000224 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000225}
226
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000227void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700228 fContentInfo.onRestore();
229
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000230 if (fillInSkips) {
231 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
232 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000233 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
234 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000235 this->validate(initialOffset, size);
236}
237
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000238void SkPictureRecord::recordTranslate(const SkMatrix& m) {
239 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
240
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000241 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000242 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000243 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000244 this->addScalar(m.getTranslateX());
245 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000246 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000247}
248
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000249void SkPictureRecord::recordScale(const SkMatrix& m) {
250 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000251
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000252 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000253 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000254 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000255 this->addScalar(m.getScaleX());
256 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000257 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000258}
259
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000260void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000261 switch (matrix.getType()) {
262 case SkMatrix::kTranslate_Mask:
263 this->recordTranslate(matrix);
264 break;
265 case SkMatrix::kScale_Mask:
266 this->recordScale(matrix);
267 break;
268 default:
269 this->recordConcat(matrix);
270 break;
271 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000272 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000273}
274
275void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000276 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000277 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000278 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000279 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000280 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000281 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000282}
283
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000284void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000285 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000286 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000287 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000288 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000289 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000290 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000291 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000292}
293
reed@google.com45482d12011-08-29 19:02:39 +0000294static bool regionOpExpands(SkRegion::Op op) {
295 switch (op) {
296 case SkRegion::kUnion_Op:
297 case SkRegion::kXOR_Op:
298 case SkRegion::kReverseDifference_Op:
299 case SkRegion::kReplace_Op:
300 return true;
301 case SkRegion::kIntersect_Op:
302 case SkRegion::kDifference_Op:
303 return false;
304 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000305 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000306 return false;
307 }
308}
309
robertphillips@google.come37ad352013-03-01 19:44:30 +0000310void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000311 int32_t offset = fRestoreOffsetStack.top();
312 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000313 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
314 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000315 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000316 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000317
reed@google.comffacd3c2012-08-30 15:31:23 +0000318#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800319 // offset of 0 has been disabled, so we skip it
320 if (offset > 0) {
321 // assert that the final offset value points to a save verb
322 uint32_t opSize;
323 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
324 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
325 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000326#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000327}
328
reed@google.comd86e7ab2012-09-27 20:31:31 +0000329void SkPictureRecord::beginRecording() {
330 // we have to call this *after* our constructor, to ensure that it gets
331 // recorded. This is balanced by restoreToCount() call from endRecording,
332 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000333 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000334}
335
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000336void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000337 SkASSERT(kNoInitialSave != fInitialSaveCount);
338 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000339}
340
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000341size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000342 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000343 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000344 }
345
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000346 // The RestoreOffset field is initially filled with a placeholder
347 // value that points to the offset of the previous RestoreOffset
348 // in the current stack level, thus forming a linked list so that
349 // the restore offsets can be filled in when the corresponding
350 // restore command is recorded.
351 int32_t prevOffset = fRestoreOffsetStack.top();
352
reed@google.com45482d12011-08-29 19:02:39 +0000353 if (regionOpExpands(op)) {
354 // Run back through any previous clip ops, and mark their offset to
355 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
356 // they could hide this clips ability to expand the clip (i.e. go from
357 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000358 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000359
360 // Reset the pointer back to the previous clip so that subsequent
361 // restores don't overwrite the offsets we just cleared.
362 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000363 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000364
reed@google.com44699382013-10-31 17:28:30 +0000365 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000366 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000367 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000368 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000369}
370
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000371void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000372 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000373 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000374}
375
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000376size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000377 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000378 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000379 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000380 if (!fRestoreOffsetStack.isEmpty()) {
381 // + restore offset
382 size += kUInt32Size;
383 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000384 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000385 this->addRect(rect);
386 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000387 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000388
robertphillips@google.com8b169312013-10-15 17:47:36 +0000389 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000390 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000391}
392
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000393void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000394 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700395 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000396}
397
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000398size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000399 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000400 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000401 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000402 if (!fRestoreOffsetStack.isEmpty()) {
403 // + restore offset
404 size += kUInt32Size;
405 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000406 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000407 this->addRRect(rrect);
408 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000409 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000410 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000411 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000412}
413
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000414void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000415 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000416 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700417 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418}
419
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000420size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000421 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000422 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000423 // recordRestoreOffsetPlaceholder doesn't always write an offset
424 if (!fRestoreOffsetStack.isEmpty()) {
425 // + restore offset
426 size += kUInt32Size;
427 }
428 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000429 this->addInt(pathID);
430 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000431 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000432 this->validate(initialOffset, size);
433 return offset;
434}
435
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000436void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000437 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000438 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000439}
440
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000441size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000442 // op + clip params + region
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000443 size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000444 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000445 if (!fRestoreOffsetStack.isEmpty()) {
446 // + restore offset
447 size += kUInt32Size;
448 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000449 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000450 this->addRegion(region);
451 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000452 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000453
robertphillips@google.com8b169312013-10-15 17:47:36 +0000454 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000455 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000456}
457
reed41af9662015-01-05 07:49:08 -0800458void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000459 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000460 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000461 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700462 SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000463 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000464 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000465}
466
reed41af9662015-01-05 07:49:08 -0800467void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
468 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700469 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000470
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000471 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000472 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000473 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
mtklein8e126562014-10-01 09:29:35 -0700474 SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000475 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700476
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000477 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000478 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000479 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000480 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000481}
482
reed41af9662015-01-05 07:49:08 -0800483void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000484 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000485 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000486 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
mtklein8e126562014-10-01 09:29:35 -0700487 SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000488 this->addPaint(paint);
489 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000490 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000491}
492
reed41af9662015-01-05 07:49:08 -0800493void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000494 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000495 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000496 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700497 SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000498 this->addPaint(paint);
499 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000500 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000501}
502
reed41af9662015-01-05 07:49:08 -0800503void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700504 // op + paint index + rrect
505 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
506 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700507 SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700508 this->addPaint(paint);
509 this->addRRect(rrect);
510 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000511}
512
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000513void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
514 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000515 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000516 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
517 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700518 SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000519 this->addPaint(paint);
520 this->addRRect(outer);
521 this->addRRect(inner);
522 this->validate(initialOffset, size);
523}
524
reed41af9662015-01-05 07:49:08 -0800525void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700526 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000527
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000528 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000529 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000530 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700531 SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000532 this->addPaint(paint);
533 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000534 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000535}
536
reed41af9662015-01-05 07:49:08 -0800537void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
538 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000539 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000540 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000541 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
mtklein8e126562014-10-01 09:29:35 -0700542 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000543 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000544 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000545 this->addScalar(left);
546 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000547 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000548}
549
reed41af9662015-01-05 07:49:08 -0800550void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
551 const SkPaint* paint, DrawBitmapRectFlags flags) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000552 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000553 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700554 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000555 size += sizeof(*src); // + rect
556 }
557 size += sizeof(dst); // + rect
558
robertphillips@google.com8b169312013-10-15 17:47:36 +0000559 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700560 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT_TO_RECT, size)
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000561 == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000562 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000563 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000564 this->addRectPtr(src); // may be null
565 this->addRect(dst);
566 this->addInt(flags);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000567 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000568}
569
reeda85d4d02015-05-06 12:56:48 -0700570void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
571 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700572 // op + paint_index + image_index + x + y
573 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
574 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
575 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE, size) == fWriter.bytesWritten());
576 this->addPaintPtr(paint);
577 this->addImage(image);
578 this->addScalar(x);
579 this->addScalar(y);
580 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700581}
582
583void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
584 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700585 // id + paint_index + bitmap_index + bool_for_src
586 size_t size = 4 * kUInt32Size;
587 if (src) {
588 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700589 }
reed871872f2015-06-22 12:48:26 -0700590 size += sizeof(dst); // + rect
591
592 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
593 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE_RECT, size)
594 == fWriter.bytesWritten());
595 this->addPaintPtr(paint);
596 this->addImage(image);
597 this->addRectPtr(src); // may be null
598 this->addRect(dst);
599 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700600}
601
reed41af9662015-01-05 07:49:08 -0800602void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
603 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000604 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000605 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000606 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
mtklein8e126562014-10-01 09:29:35 -0700607 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000608 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000609 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000610 this->addIRect(center);
611 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000612 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000613}
614
reed41af9662015-01-05 07:49:08 -0800615void SkPictureRecord::onDrawSprite(const SkBitmap& bitmap, int left, int top,
616 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000617 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000618 size_t size = 5 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000619 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
mtklein8e126562014-10-01 09:29:35 -0700620 SkASSERT(initialOffset+get_paint_offset(DRAW_SPRITE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000621 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000622 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000623 this->addInt(left);
624 this->addInt(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000625 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000626}
627
reed@google.come0d9ce82014-04-23 04:00:17 +0000628void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
629 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000630 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000631 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000632
mtklein46616af2014-09-30 14:47:10 -0700633 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000634 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700635 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700636 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000637 this->addText(text, byteLength);
638 this->addScalar(x);
639 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000640 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000641}
642
reed@google.come0d9ce82014-04-23 04:00:17 +0000643void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
644 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000645 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000646
mtklein46616af2014-09-30 14:47:10 -0700647 // op + paint index + length + 'length' worth of data + num points + x&y point data
648 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000649
mtklein46616af2014-09-30 14:47:10 -0700650 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000651
robertphillips@google.com8b169312013-10-15 17:47:36 +0000652 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700653 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700654 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000655 this->addText(text, byteLength);
656 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700657 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000658 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000659}
660
reed@google.come0d9ce82014-04-23 04:00:17 +0000661void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
662 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000663 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000664
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000665 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000666 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000667 // + y + the actual points
668 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000669
mtklein46616af2014-09-30 14:47:10 -0700670 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
671 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000672 this->addText(text, byteLength);
673 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000674 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000675 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000676 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000677}
678
reed@google.come0d9ce82014-04-23 04:00:17 +0000679void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
680 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000681 // op + paint index + length + 'length' worth of data + path index + matrix
682 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000683 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000684 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700685 SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000686 this->addPaint(paint);
687 this->addText(text, byteLength);
688 this->addPath(path);
689 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000690 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000691}
692
fmalitab7425172014-08-26 07:56:44 -0700693void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
694 const SkPaint& paint) {
695
696 // op + paint index + blob index + x/y
697 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
698 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
mtklein8e126562014-10-01 09:29:35 -0700699 SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
fmalitab7425172014-08-26 07:56:44 -0700700
701 this->addPaint(paint);
702 this->addTextBlob(blob);
703 this->addScalar(x);
704 this->addScalar(y);
705
706 this->validate(initialOffset, size);
707}
708
reedd5fa1a42014-08-09 11:08:05 -0700709void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
710 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000711 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000712 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700713 size_t initialOffset;
714
715 if (NULL == matrix && NULL == paint) {
716 initialOffset = this->addDraw(DRAW_PICTURE, &size);
717 this->addPicture(picture);
718 } else {
719 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
720 size += m.writeToMemory(NULL) + kUInt32Size; // matrix + paint
721 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700722 SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
fmalita9f49cfd2014-08-12 12:24:17 -0700723 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700724 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700725 this->addMatrix(m);
726 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700727 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000728 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000729}
730
reed41af9662015-01-05 07:49:08 -0800731void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
732 const SkPoint vertices[], const SkPoint texs[],
733 const SkColor colors[], SkXfermode* xfer,
734 const uint16_t indices[], int indexCount,
735 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000736 uint32_t flags = 0;
737 if (texs) {
738 flags |= DRAW_VERTICES_HAS_TEXS;
739 }
740 if (colors) {
741 flags |= DRAW_VERTICES_HAS_COLORS;
742 }
743 if (indexCount > 0) {
744 flags |= DRAW_VERTICES_HAS_INDICES;
745 }
bsalomon49f085d2014-09-05 13:34:00 -0700746 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000747 SkXfermode::Mode mode;
748 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
749 flags |= DRAW_VERTICES_HAS_XFER;
750 }
751 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000752
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000753 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000754 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000755 if (flags & DRAW_VERTICES_HAS_TEXS) {
756 size += vertexCount * sizeof(SkPoint); // + uvs
757 }
758 if (flags & DRAW_VERTICES_HAS_COLORS) {
759 size += vertexCount * sizeof(SkColor); // + vert colors
760 }
761 if (flags & DRAW_VERTICES_HAS_INDICES) {
762 // + num indices + indices
763 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
764 }
reed@google.com85e143c2013-12-30 15:51:25 +0000765 if (flags & DRAW_VERTICES_HAS_XFER) {
766 size += kUInt32Size; // mode enum
767 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000768
robertphillips@google.com8b169312013-10-15 17:47:36 +0000769 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
mtklein8e126562014-10-01 09:29:35 -0700770 SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000771 this->addPaint(paint);
772 this->addInt(flags);
773 this->addInt(vmode);
774 this->addInt(vertexCount);
775 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000776 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000777 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000778 }
779 if (flags & DRAW_VERTICES_HAS_COLORS) {
780 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
781 }
782 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000783 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000784 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
785 }
reed@google.com85e143c2013-12-30 15:51:25 +0000786 if (flags & DRAW_VERTICES_HAS_XFER) {
787 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
788 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000789 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000790 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000791 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000792}
793
dandovb3c9d1c2014-08-12 08:34:29 -0700794void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
795 const SkPoint texCoords[4], SkXfermode* xmode,
796 const SkPaint& paint) {
797 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
798 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
799 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700800 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700801 flag |= DRAW_VERTICES_HAS_COLORS;
802 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
803 }
bsalomon49f085d2014-09-05 13:34:00 -0700804 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700805 flag |= DRAW_VERTICES_HAS_TEXS;
806 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
807 }
bsalomon49f085d2014-09-05 13:34:00 -0700808 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700809 SkXfermode::Mode mode;
810 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
811 flag |= DRAW_VERTICES_HAS_XFER;
812 size += kUInt32Size;
813 }
814 }
mtklein46616af2014-09-30 14:47:10 -0700815
dandov963137b2014-08-07 07:49:53 -0700816 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
mtklein8e126562014-10-01 09:29:35 -0700817 SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
dandov963137b2014-08-07 07:49:53 -0700818 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700819 this->addPatch(cubics);
820 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700821
dandovb3c9d1c2014-08-12 08:34:29 -0700822 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700823 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700824 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
825 }
bsalomon49f085d2014-09-05 13:34:00 -0700826 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700827 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
828 }
829 if (flag & DRAW_VERTICES_HAS_XFER) {
830 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
831 xmode->asMode(&mode);
832 this->addInt(mode);
833 }
dandov963137b2014-08-07 07:49:53 -0700834 this->validate(initialOffset, size);
835}
836
reed@android.com8a1c16f2008-12-17 15:59:43 +0000837///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000838
reed4a8126e2014-09-22 07:29:03 -0700839SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000840 return NULL;
reed@google.com76f10a32014-02-05 15:32:21 +0000841}
842
mtkleine0694002014-11-12 12:49:47 -0800843// If we already have a stored, can we reuse it instead of also storing b?
844static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
845 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
846 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
847 // but it sure makes things easier to reason about below.
848 return false;
849 }
850 if (a.pixelRef() == b.pixelRef()) {
851 return true; // Same shape and same pixels -> same bitmap.
852 }
853
854 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
855 if (!a.pixelRef() || !b.pixelRef()) {
856 return false;
857 }
858
859 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
860 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
861 encB(b.pixelRef()->refEncodedData());
862 if (encA && encB) {
863 return encA->equals(encB);
864 } else if (encA || encB) {
865 return false; // One has encoded data but the other does not.
866 }
867
868 // As a last resort, we have to look at the pixels. This will read back textures.
869 SkAutoLockPixels al(a), bl(b);
870 const char* ap = (const char*)a.getPixels();
871 const char* bp = (const char*)b.getPixels();
872 if (ap && bp) {
873 // We check row by row; row bytes might differ.
874 SkASSERT(a.info() == b.info()); // We checked this above.
875 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
876 const SkImageInfo info = a.info();
877 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
878 for (int row = 0; row < info.height(); row++) {
879 if (0 != memcmp(ap, bp, bytesToCompare)) {
880 return false;
881 }
882 ap += a.rowBytes();
883 bp += b.rowBytes();
884 }
885 return true;
886 }
887 return false; // Couldn't get pixels for both bitmaps.
888}
889
890void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
891 // First see if we already have this bitmap. This deduplication should really
892 // only be important for our tests, where bitmaps tend not to be tagged immutable.
893 // In Chrome (and hopefully Android?) they're typically immutable.
894 for (int i = 0; i < fBitmaps.count(); i++) {
895 if (equivalent(fBitmaps[i], bitmap)) {
896 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
897 return;
898 }
899 }
900 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800901 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800902 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800903 fBitmaps.push_back(bitmap);
904 } else {
mtkleine0694002014-11-12 12:49:47 -0800905 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800906 SkBitmap copy;
907 bitmap.copyTo(&copy);
908 copy.setImmutable();
909 fBitmaps.push_back(copy);
910 }
mtkleine0694002014-11-12 12:49:47 -0800911 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000912}
913
reed871872f2015-06-22 12:48:26 -0700914void SkPictureRecord::addImage(const SkImage* image) {
915 int index = fImageRefs.find(image);
916 if (index >= 0) {
917 this->addInt(index);
918 } else {
919 *fImageRefs.append() = SkRef(image);
920 this->addInt(fImageRefs.count()-1);
921 }
922}
923
reed@android.com8a1c16f2008-12-17 15:59:43 +0000924void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000925 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000926}
927
mtklein46616af2014-09-30 14:47:10 -0700928void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700929 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000930
mtklein46616af2014-09-30 14:47:10 -0700931 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800932 fPaints.push_back(*paint);
933 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700934 } else {
935 this->addInt(0);
936 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000937}
938
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000939int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtklein71a23632014-11-12 10:24:55 -0800940 fPaths.push_back(path);
941 return fPaths.count();
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