blob: 36b8d379f536b637feea9d825ad5ddfd0a08c28d [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"
reed71c3c762015-06-24 10:29:17 -070014#include "SkRSXform.h"
fmalitab7425172014-08-26 07:56:44 -070015#include "SkTextBlob.h"
dandovb3c9d1c2014-08-12 08:34:29 -070016#include "SkTSearch.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017
reed@android.com8a1c16f2008-12-17 15:59:43 +000018#define HEAP_BLOCK_SIZE 4096
19
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000020enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000021 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000022 kNoInitialSave = -1,
23};
24
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000025// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
26static int const kUInt32Size = 4;
27
Florin Malita5f6102d2014-06-30 10:13:28 -040028static const uint32_t kSaveSize = kUInt32Size;
mtklein8e126562014-10-01 09:29:35 -070029#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000030static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
31static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
mtklein8e126562014-10-01 09:29:35 -070032#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000033
robertphillips0bdbea72014-06-11 11:37:55 -070034SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000035 : INHERITED(dimensions.width(), dimensions.height())
mtklein71a23632014-11-12 10:24:55 -080036 , fRecordFlags(flags)
37 , fInitialSaveCount(kNoInitialSave) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000038}
39
40SkPictureRecord::~SkPictureRecord() {
robertphillips5351aad2015-06-23 06:54:56 -070041 fImageRefs.unrefAll();
djsollen@google.com21830d92012-08-07 19:49:41 +000042 fPictureRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070043 fTextBlobRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000044}
45
46///////////////////////////////////////////////////////////////////////////////
47
mtklein8e126562014-10-01 09:29:35 -070048#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000049// Return the offset of the paint inside a given op's byte stream. A zero
50// return value means there is no paint (and you really shouldn't be calling
51// this method)
mtklein8e126562014-10-01 09:29:35 -070052static inline size_t get_paint_offset(DrawType op, size_t opSize) {
robertphillips@google.come37ad352013-03-01 19:44:30 +000053 // These offsets are where the paint would be if the op size doesn't overflow
fmalita9f49cfd2014-08-12 12:24:17 -070054 static const uint8_t gPaintOffsets[] = {
robertphillips@google.come37ad352013-03-01 19:44:30 +000055 0, // UNUSED - no paint
56 0, // CLIP_PATH - no paint
57 0, // CLIP_REGION - no paint
58 0, // CLIP_RECT - no paint
59 0, // CLIP_RRECT - no paint
60 0, // CONCAT - no paint
61 1, // DRAW_BITMAP - right after op code
Florin Malitac54d8db2014-12-10 12:02:16 -050062 1, // DRAW_BITMAP_MATRIX - right after op code, deprecated
robertphillips@google.come37ad352013-03-01 19:44:30 +000063 1, // DRAW_BITMAP_NINE - right after op code
reeda5517e22015-07-14 10:54:12 -070064 1, // DRAW_BITMAP_RECT - right after op code
robertphillips@google.come37ad352013-03-01 19:44:30 +000065 0, // DRAW_CLEAR - no paint
66 0, // DRAW_DATA - no paint
67 1, // DRAW_OVAL - right after op code
68 1, // DRAW_PAINT - right after op code
69 1, // DRAW_PATH - right after op code
70 0, // DRAW_PICTURE - no paint
71 1, // DRAW_POINTS - right after op code
72 1, // DRAW_POS_TEXT - right after op code
73 1, // DRAW_POS_TEXT_TOP_BOTTOM - right after op code
74 1, // DRAW_POS_TEXT_H - right after op code
75 1, // DRAW_POS_TEXT_H_TOP_BOTTOM - right after op code
76 1, // DRAW_RECT - right after op code
77 1, // DRAW_RRECT - right after op code
78 1, // DRAW_SPRITE - right after op code
79 1, // DRAW_TEXT - right after op code
80 1, // DRAW_TEXT_ON_PATH - right after op code
81 1, // DRAW_TEXT_TOP_BOTTOM - right after op code
82 1, // DRAW_VERTICES - right after op code
83 0, // RESTORE - no paint
84 0, // ROTATE - no paint
85 0, // SAVE - no paint
reed4960eee2015-12-18 07:09:18 -080086 0, // SAVE_LAYER_SAVEFLAGS_DEPRECATED - see below - this paint's location varies
robertphillips@google.come37ad352013-03-01 19:44:30 +000087 0, // SCALE - no paint
88 0, // SET_MATRIX - no paint
89 0, // SKEW - no paint
90 0, // TRANSLATE - no paint
91 0, // NOOP - no paint
robertphillips@google.com0a4805e2013-05-29 13:24:23 +000092 0, // BEGIN_GROUP - no paint
93 0, // COMMENT - no paint
94 0, // END_GROUP - no paint
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +000095 1, // DRAWDRRECT - right after op code
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +000096 0, // PUSH_CULL - no paint
97 0, // POP_CULL - no paint
dandov963137b2014-08-07 07:49:53 -070098 1, // DRAW_PATCH - right after op code
fmalita9f49cfd2014-08-12 12:24:17 -070099 1, // DRAW_PICTURE_MATRIX_PAINT - right after op code
fmalitab7425172014-08-26 07:56:44 -0700100 1, // DRAW_TEXT_BLOB- right after op code
reed871872f2015-06-22 12:48:26 -0700101 1, // DRAW_IMAGE - right after op code
reeda5517e22015-07-14 10:54:12 -0700102 1, // DRAW_IMAGE_RECT_STRICT - right after op code
reed71c3c762015-06-24 10:29:17 -0700103 1, // DRAW_ATLAS - right after op code
reed4c21dc52015-06-25 12:32:03 -0700104 1, // DRAW_IMAGE_NINE - right after op code
reeda5517e22015-07-14 10:54:12 -0700105 1, // DRAW_IMAGE_RECT - right after op code
reed4960eee2015-12-18 07:09:18 -0800106 0, // SAVE_LAYER_SAVELAYERFLAGS - see below - this paint's location varies
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000107 };
robertphillips@google.come37ad352013-03-01 19:44:30 +0000108
bungeman99fe8222015-08-20 07:57:51 -0700109 static_assert(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1, "need_to_be_in_sync");
robertphillips@google.come37ad352013-03-01 19:44:30 +0000110 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
111
112 int overflow = 0;
113 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
114 // This op's size overflows so an extra uint32_t will be written
115 // after the op code
116 overflow = sizeof(uint32_t);
117 }
118
reed4960eee2015-12-18 07:09:18 -0800119 SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != op);
120 if (SAVE_LAYER_SAVELAYERFLAGS == op) {
robertphillips@google.come37ad352013-03-01 19:44:30 +0000121 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
122 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
123
124 if (kSaveLayerNoBoundsSize == opSize) {
125 return kSaveLayerNoBoundsPaintOffset + overflow;
126 } else {
127 SkASSERT(kSaveLayerWithBoundsSize == opSize);
128 return kSaveLayerWithBoundsPaintOffset + overflow;
129 }
130 }
131
132 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this method
133 return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
134}
mtklein8e126562014-10-01 09:29:35 -0700135#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +0000136
Florin Malita5f6102d2014-06-30 10:13:28 -0400137void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +0000138 // record the offset to us, making it non-positive to distinguish a save
139 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000140 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -0400141 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000142
Florin Malita5f6102d2014-06-30 10:13:28 -0400143 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000144}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000145
Florin Malita5f6102d2014-06-30 10:13:28 -0400146void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -0700147 fContentInfo.onSave();
148
Florin Malita5f6102d2014-06-30 10:13:28 -0400149 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000150 size_t size = kSaveSize;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000151 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +0000152
robertphillips@google.com8b169312013-10-15 17:47:36 +0000153 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154}
155
reed4960eee2015-12-18 07:09:18 -0800156SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000157 // record the offset to us, making it non-positive to distinguish a save
158 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000159 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
reed4960eee2015-12-18 07:09:18 -0800160 this->recordSaveLayer(rec);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000161
reed4960eee2015-12-18 07:09:18 -0800162 (void)this->INHERITED::getSaveLayerStrategy(rec);
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000163 /* 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
reed4960eee2015-12-18 07:09:18 -0800171void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
robertphillipsc019ec42014-08-12 05:35:58 -0700172 fContentInfo.onSaveLayer();
173
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000174 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000175 size_t size = 2 * kUInt32Size;
reed4960eee2015-12-18 07:09:18 -0800176 if (rec.fBounds) {
177 size += sizeof(*rec.fBounds); // + rect
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000178 }
179 // + paint index + flags
180 size += 2 * kUInt32Size;
181
robertphillips@google.come37ad352013-03-01 19:44:30 +0000182 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
183
reed4960eee2015-12-18 07:09:18 -0800184 size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERFLAGS, &size);
185 this->addRectPtr(rec.fBounds);
186 SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER_SAVELAYERFLAGS, size) == fWriter.bytesWritten());
187 this->addPaintPtr(rec.fPaint);
188 this->addInt(rec.fSaveLayerFlags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189
robertphillips@google.com8b169312013-10-15 17:47:36 +0000190 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000191}
192
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000193#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000194/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000195 * Read the op code from 'offset' in 'writer' and extract the size too.
196 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000197static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000198 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000199
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000200 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000201 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000202 if (MASK_24 == *size) {
203 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000204 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000205 }
206 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000207}
mtklein46616af2014-09-30 14:47:10 -0700208#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000209
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000210void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000211#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
halcanary96fcdcc2015-08-27 07:41:13 -0700278 size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
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
halcanary96fcdcc2015-08-27 07:41:13 -0700287 size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
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);
reed4960eee2015-12-18 07:09:18 -0800324 SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
325 SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERFLAGS == drawOp);
reed2ff1fce2014-12-11 07:07:37 -0800326 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000327#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000328}
329
reed@google.comd86e7ab2012-09-27 20:31:31 +0000330void SkPictureRecord::beginRecording() {
331 // we have to call this *after* our constructor, to ensure that it gets
332 // recorded. This is balanced by restoreToCount() call from endRecording,
333 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000334 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000335}
336
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000337void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000338 SkASSERT(kNoInitialSave != fInitialSaveCount);
339 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000340}
341
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000342size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000343 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000344 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000345 }
346
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000347 // The RestoreOffset field is initially filled with a placeholder
348 // value that points to the offset of the previous RestoreOffset
349 // in the current stack level, thus forming a linked list so that
350 // the restore offsets can be filled in when the corresponding
351 // restore command is recorded.
352 int32_t prevOffset = fRestoreOffsetStack.top();
353
reed@google.com45482d12011-08-29 19:02:39 +0000354 if (regionOpExpands(op)) {
355 // Run back through any previous clip ops, and mark their offset to
356 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
357 // they could hide this clips ability to expand the clip (i.e. go from
358 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000359 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000360
361 // Reset the pointer back to the previous clip so that subsequent
362 // restores don't overwrite the offsets we just cleared.
363 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000364 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000365
reed@google.com44699382013-10-31 17:28:30 +0000366 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000367 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000368 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000369 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000370}
371
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000372void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000373 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000374 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000375}
376
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000377size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000378 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000379 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000380 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000381 if (!fRestoreOffsetStack.isEmpty()) {
382 // + restore offset
383 size += kUInt32Size;
384 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000385 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000386 this->addRect(rect);
387 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000388 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000389
robertphillips@google.com8b169312013-10-15 17:47:36 +0000390 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000391 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000392}
393
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000394void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000395 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700396 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000397}
398
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000399size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000400 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000401 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000402 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000403 if (!fRestoreOffsetStack.isEmpty()) {
404 // + restore offset
405 size += kUInt32Size;
406 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000407 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000408 this->addRRect(rrect);
409 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000410 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000411 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000412 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000413}
414
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000415void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000416 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000417 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700418 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000419}
420
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000421size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000422 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000423 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000424 // recordRestoreOffsetPlaceholder doesn't always write an offset
425 if (!fRestoreOffsetStack.isEmpty()) {
426 // + restore offset
427 size += kUInt32Size;
428 }
429 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000430 this->addInt(pathID);
431 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000432 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000433 this->validate(initialOffset, size);
434 return offset;
435}
436
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000437void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000438 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000439 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000440}
441
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000442size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000443 // op + clip params + region
halcanary96fcdcc2015-08-27 07:41:13 -0700444 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000445 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000446 if (!fRestoreOffsetStack.isEmpty()) {
447 // + restore offset
448 size += kUInt32Size;
449 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000450 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000451 this->addRegion(region);
452 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000453 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000454
robertphillips@google.com8b169312013-10-15 17:47:36 +0000455 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000456 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000457}
458
reed41af9662015-01-05 07:49:08 -0800459void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000460 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000461 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000462 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700463 SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000464 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000465 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000466}
467
reed41af9662015-01-05 07:49:08 -0800468void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
469 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700470 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000471
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000472 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000473 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000474 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
mtklein8e126562014-10-01 09:29:35 -0700475 SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000476 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700477
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000478 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000479 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000480 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000481 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000482}
483
reed41af9662015-01-05 07:49:08 -0800484void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000485 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000486 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000487 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
mtklein8e126562014-10-01 09:29:35 -0700488 SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000489 this->addPaint(paint);
490 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000491 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000492}
493
reed41af9662015-01-05 07:49:08 -0800494void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000495 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000496 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000497 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700498 SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000499 this->addPaint(paint);
500 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000501 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000502}
503
reed41af9662015-01-05 07:49:08 -0800504void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700505 // op + paint index + rrect
506 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
507 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700508 SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700509 this->addPaint(paint);
510 this->addRRect(rrect);
511 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000512}
513
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000514void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
515 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000516 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000517 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
518 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700519 SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000520 this->addPaint(paint);
521 this->addRRect(outer);
522 this->addRRect(inner);
523 this->validate(initialOffset, size);
524}
525
reed41af9662015-01-05 07:49:08 -0800526void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700527 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000528
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000529 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000530 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000531 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700532 SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000533 this->addPaint(paint);
534 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000535 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000536}
537
reed41af9662015-01-05 07:49:08 -0800538void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
539 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000540 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000541 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000542 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
mtklein8e126562014-10-01 09:29:35 -0700543 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000544 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000545 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000546 this->addScalar(left);
547 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000548 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000549}
550
reed41af9662015-01-05 07:49:08 -0800551void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700552 const SkPaint* paint, SrcRectConstraint constraint) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000553 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000554 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700555 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000556 size += sizeof(*src); // + rect
557 }
558 size += sizeof(dst); // + rect
559
reeda5517e22015-07-14 10:54:12 -0700560 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT, &size);
561 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT, size) == 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);
reeda5517e22015-07-14 10:54:12 -0700566 this->addInt(constraint);
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,
reed562fe472015-07-28 07:35:14 -0700584 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700585 // id + paint_index + image_index + bool_for_src + constraint
586 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700587 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
mtkleinc2e29772015-10-30 05:24:58 -0700591
reed871872f2015-06-22 12:48:26 -0700592 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);
reeda5517e22015-07-14 10:54:12 -0700599 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700600 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700601}
602
reed4c21dc52015-06-25 12:32:03 -0700603void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
604 const SkPaint* paint) {
605 // id + paint_index + image_index + center + dst
606 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
mtkleinc2e29772015-10-30 05:24:58 -0700607
reed4c21dc52015-06-25 12:32:03 -0700608 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
609 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE_NINE, size) == fWriter.bytesWritten());
610 this->addPaintPtr(paint);
611 this->addImage(img);
612 this->addIRect(center);
613 this->addRect(dst);
614 this->validate(initialOffset, size);
615}
616
reed41af9662015-01-05 07:49:08 -0800617void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
618 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000619 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000620 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000621 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
mtklein8e126562014-10-01 09:29:35 -0700622 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000623 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000624 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000625 this->addIRect(center);
626 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000627 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000628}
629
reed@google.come0d9ce82014-04-23 04:00:17 +0000630void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
631 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000632 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000633 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000634
mtklein46616af2014-09-30 14:47:10 -0700635 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000636 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700637 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700638 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000639 this->addText(text, byteLength);
640 this->addScalar(x);
641 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000642 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000643}
644
reed@google.come0d9ce82014-04-23 04:00:17 +0000645void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
646 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000647 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000648
mtklein46616af2014-09-30 14:47:10 -0700649 // op + paint index + length + 'length' worth of data + num points + x&y point data
650 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000651
mtklein46616af2014-09-30 14:47:10 -0700652 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000653
robertphillips@google.com8b169312013-10-15 17:47:36 +0000654 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700655 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700656 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000657 this->addText(text, byteLength);
658 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700659 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000660 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000661}
662
reed@google.come0d9ce82014-04-23 04:00:17 +0000663void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
664 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000665 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000666
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000667 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000668 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000669 // + y + the actual points
670 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000671
mtklein46616af2014-09-30 14:47:10 -0700672 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
673 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000674 this->addText(text, byteLength);
675 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000676 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000677 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000678 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000679}
680
reed@google.come0d9ce82014-04-23 04:00:17 +0000681void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
682 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000683 // op + paint index + length + 'length' worth of data + path index + matrix
684 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700685 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000686 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700687 SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000688 this->addPaint(paint);
689 this->addText(text, byteLength);
690 this->addPath(path);
691 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000692 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000693}
694
fmalitab7425172014-08-26 07:56:44 -0700695void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
696 const SkPaint& paint) {
697
698 // op + paint index + blob index + x/y
699 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
700 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
mtklein8e126562014-10-01 09:29:35 -0700701 SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
fmalitab7425172014-08-26 07:56:44 -0700702
703 this->addPaint(paint);
704 this->addTextBlob(blob);
705 this->addScalar(x);
706 this->addScalar(y);
707
708 this->validate(initialOffset, size);
709}
710
reedd5fa1a42014-08-09 11:08:05 -0700711void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
712 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000713 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000714 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700715 size_t initialOffset;
716
halcanary96fcdcc2015-08-27 07:41:13 -0700717 if (nullptr == matrix && nullptr == paint) {
reedd5fa1a42014-08-09 11:08:05 -0700718 initialOffset = this->addDraw(DRAW_PICTURE, &size);
719 this->addPicture(picture);
720 } else {
721 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700722 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
reedd5fa1a42014-08-09 11:08:05 -0700723 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700724 SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
fmalita9f49cfd2014-08-12 12:24:17 -0700725 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700726 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700727 this->addMatrix(m);
728 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700729 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000730 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000731}
732
reed41af9662015-01-05 07:49:08 -0800733void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
734 const SkPoint vertices[], const SkPoint texs[],
735 const SkColor colors[], SkXfermode* xfer,
736 const uint16_t indices[], int indexCount,
737 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000738 uint32_t flags = 0;
739 if (texs) {
740 flags |= DRAW_VERTICES_HAS_TEXS;
741 }
742 if (colors) {
743 flags |= DRAW_VERTICES_HAS_COLORS;
744 }
745 if (indexCount > 0) {
746 flags |= DRAW_VERTICES_HAS_INDICES;
747 }
bsalomon49f085d2014-09-05 13:34:00 -0700748 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000749 SkXfermode::Mode mode;
750 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
751 flags |= DRAW_VERTICES_HAS_XFER;
752 }
753 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000754
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000755 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000756 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000757 if (flags & DRAW_VERTICES_HAS_TEXS) {
758 size += vertexCount * sizeof(SkPoint); // + uvs
759 }
760 if (flags & DRAW_VERTICES_HAS_COLORS) {
761 size += vertexCount * sizeof(SkColor); // + vert colors
762 }
763 if (flags & DRAW_VERTICES_HAS_INDICES) {
764 // + num indices + indices
765 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
766 }
reed@google.com85e143c2013-12-30 15:51:25 +0000767 if (flags & DRAW_VERTICES_HAS_XFER) {
768 size += kUInt32Size; // mode enum
769 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000770
robertphillips@google.com8b169312013-10-15 17:47:36 +0000771 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
mtklein8e126562014-10-01 09:29:35 -0700772 SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000773 this->addPaint(paint);
774 this->addInt(flags);
775 this->addInt(vmode);
776 this->addInt(vertexCount);
777 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000778 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000779 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000780 }
781 if (flags & DRAW_VERTICES_HAS_COLORS) {
782 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
783 }
784 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000785 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000786 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
787 }
reed@google.com85e143c2013-12-30 15:51:25 +0000788 if (flags & DRAW_VERTICES_HAS_XFER) {
789 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
790 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000791 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000792 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000793 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000794}
795
dandovb3c9d1c2014-08-12 08:34:29 -0700796void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
797 const SkPoint texCoords[4], SkXfermode* xmode,
798 const SkPaint& paint) {
799 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
800 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
801 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700802 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700803 flag |= DRAW_VERTICES_HAS_COLORS;
804 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
805 }
bsalomon49f085d2014-09-05 13:34:00 -0700806 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700807 flag |= DRAW_VERTICES_HAS_TEXS;
808 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
809 }
bsalomon49f085d2014-09-05 13:34:00 -0700810 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700811 SkXfermode::Mode mode;
812 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
813 flag |= DRAW_VERTICES_HAS_XFER;
814 size += kUInt32Size;
815 }
816 }
mtklein46616af2014-09-30 14:47:10 -0700817
dandov963137b2014-08-07 07:49:53 -0700818 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
mtklein8e126562014-10-01 09:29:35 -0700819 SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
dandov963137b2014-08-07 07:49:53 -0700820 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700821 this->addPatch(cubics);
822 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700823
dandovb3c9d1c2014-08-12 08:34:29 -0700824 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700825 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700826 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
827 }
bsalomon49f085d2014-09-05 13:34:00 -0700828 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700829 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
830 }
831 if (flag & DRAW_VERTICES_HAS_XFER) {
832 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
833 xmode->asMode(&mode);
834 this->addInt(mode);
835 }
dandov963137b2014-08-07 07:49:53 -0700836 this->validate(initialOffset, size);
837}
838
reed71c3c762015-06-24 10:29:17 -0700839void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
840 const SkColor colors[], int count, SkXfermode::Mode mode,
841 const SkRect* cull, const SkPaint* paint) {
842 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
843 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
844 uint32_t flags = 0;
845 if (colors) {
846 flags |= DRAW_ATLAS_HAS_COLORS;
847 size += count * sizeof(SkColor);
848 size += sizeof(uint32_t); // xfermode::mode
849 }
850 if (cull) {
851 flags |= DRAW_ATLAS_HAS_CULL;
852 size += sizeof(SkRect);
853 }
mtkleinc2e29772015-10-30 05:24:58 -0700854
reed71c3c762015-06-24 10:29:17 -0700855 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
856 SkASSERT(initialOffset+get_paint_offset(DRAW_ATLAS, size) == fWriter.bytesWritten());
857 this->addPaintPtr(paint);
858 this->addImage(atlas);
859 this->addInt(flags);
860 this->addInt(count);
861 fWriter.write(xform, count * sizeof(SkRSXform));
862 fWriter.write(tex, count * sizeof(SkRect));
863
864 // write optional parameters
865 if (colors) {
866 fWriter.write(colors, count * sizeof(SkColor));
867 this->addInt(mode);
868 }
869 if (cull) {
870 fWriter.write(cull, sizeof(SkRect));
871 }
872 this->validate(initialOffset, size);
873}
874
reed@android.com8a1c16f2008-12-17 15:59:43 +0000875///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000876
reed4a8126e2014-09-22 07:29:03 -0700877SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700878 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000879}
880
mtkleine0694002014-11-12 12:49:47 -0800881// If we already have a stored, can we reuse it instead of also storing b?
882static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
883 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
884 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
885 // but it sure makes things easier to reason about below.
886 return false;
887 }
888 if (a.pixelRef() == b.pixelRef()) {
889 return true; // Same shape and same pixels -> same bitmap.
890 }
891
892 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
893 if (!a.pixelRef() || !b.pixelRef()) {
894 return false;
895 }
896
897 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
898 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
899 encB(b.pixelRef()->refEncodedData());
900 if (encA && encB) {
901 return encA->equals(encB);
902 } else if (encA || encB) {
903 return false; // One has encoded data but the other does not.
904 }
905
906 // As a last resort, we have to look at the pixels. This will read back textures.
907 SkAutoLockPixels al(a), bl(b);
908 const char* ap = (const char*)a.getPixels();
909 const char* bp = (const char*)b.getPixels();
910 if (ap && bp) {
911 // We check row by row; row bytes might differ.
912 SkASSERT(a.info() == b.info()); // We checked this above.
913 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
914 const SkImageInfo info = a.info();
915 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
916 for (int row = 0; row < info.height(); row++) {
917 if (0 != memcmp(ap, bp, bytesToCompare)) {
918 return false;
919 }
920 ap += a.rowBytes();
921 bp += b.rowBytes();
922 }
923 return true;
924 }
925 return false; // Couldn't get pixels for both bitmaps.
926}
927
928void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
929 // First see if we already have this bitmap. This deduplication should really
930 // only be important for our tests, where bitmaps tend not to be tagged immutable.
931 // In Chrome (and hopefully Android?) they're typically immutable.
932 for (int i = 0; i < fBitmaps.count(); i++) {
933 if (equivalent(fBitmaps[i], bitmap)) {
934 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
935 return;
936 }
937 }
938 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800939 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800940 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800941 fBitmaps.push_back(bitmap);
942 } else {
mtkleine0694002014-11-12 12:49:47 -0800943 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800944 SkBitmap copy;
945 bitmap.copyTo(&copy);
946 copy.setImmutable();
947 fBitmaps.push_back(copy);
948 }
mtkleine0694002014-11-12 12:49:47 -0800949 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000950}
951
reed871872f2015-06-22 12:48:26 -0700952void SkPictureRecord::addImage(const SkImage* image) {
953 int index = fImageRefs.find(image);
954 if (index >= 0) {
955 this->addInt(index);
956 } else {
957 *fImageRefs.append() = SkRef(image);
958 this->addInt(fImageRefs.count()-1);
959 }
960}
961
reed@android.com8a1c16f2008-12-17 15:59:43 +0000962void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000963 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000964}
965
mtklein46616af2014-09-30 14:47:10 -0700966void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700967 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000968
mtklein46616af2014-09-30 14:47:10 -0700969 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800970 fPaints.push_back(*paint);
971 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700972 } else {
973 this->addInt(0);
974 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000975}
976
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000977int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700978 if (int* n = fPaths.find(path)) {
979 return *n;
980 }
981 int n = fPaths.count() + 1; // 0 is reserved for null / error.
982 fPaths.set(path, n);
983 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000984}
985
986void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000987 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000988}
989
dandovb3c9d1c2014-08-12 08:34:29 -0700990void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
991 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700992}
993
robertphillips9b14f262014-06-04 05:40:44 -0700994void SkPictureRecord::addPicture(const SkPicture* picture) {
995 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000996 if (index < 0) { // not found
997 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700998 *fPictureRefs.append() = picture;
999 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001000 }
1001 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +00001002 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001003}
1004
1005void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001006 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001007}
reed@google.com82065d62011-02-07 15:30:46 +00001008
reed@android.com8a1c16f2008-12-17 15:59:43 +00001009void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
1010 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001011}
1012
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001013void SkPictureRecord::addNoOp() {
1014 size_t size = kUInt32Size; // op
1015 this->addDraw(NOOP, &size);
1016}
1017
reed@android.com8a1c16f2008-12-17 15:59:43 +00001018void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001019 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001020}
1021
1022void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -07001023 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001024 fWriter.writeRect(*rect);
1025 }
1026}
1027
reed@google.comf0b5e112011-09-07 11:57:34 +00001028void SkPictureRecord::addIRect(const SkIRect& rect) {
1029 fWriter.write(&rect, sizeof(rect));
1030}
1031
reed@android.com8a1c16f2008-12-17 15:59:43 +00001032void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -07001033 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001034 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
1035 }
1036}
1037
reed@google.com4ed0fb72012-12-12 20:48:18 +00001038void SkPictureRecord::addRRect(const SkRRect& rrect) {
1039 fWriter.writeRRect(rrect);
1040}
1041
reed@android.com8a1c16f2008-12-17 15:59:43 +00001042void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001043 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001044}
1045
1046void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001047 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001048 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001049 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001050}
1051
fmalitab7425172014-08-26 07:56:44 -07001052void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001053 int index = fTextBlobRefs.count();
1054 *fTextBlobRefs.append() = blob;
1055 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001056 // follow the convention of recording a 1-based index
1057 this->addInt(index + 1);
1058}
1059
reed@android.com8a1c16f2008-12-17 15:59:43 +00001060///////////////////////////////////////////////////////////////////////////////
1061