blob: 562f056c501d6df226f4c3821b4a24926e4ceee2 [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"
reeda85d4d02015-05-06 12:56:48 -07009#include "SkImage_Base.h"
dandovb3c9d1c2014-08-12 08:34:29 -070010#include "SkPatchUtils.h"
dandovb3c9d1c2014-08-12 08:34:29 -070011#include "SkPixelRef.h"
12#include "SkRRect.h"
reed71c3c762015-06-24 10:29:17 -070013#include "SkRSXform.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
robertphillips0bdbea72014-06-11 11:37:55 -070027SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000028 : INHERITED(dimensions.width(), dimensions.height())
mtklein71a23632014-11-12 10:24:55 -080029 , fRecordFlags(flags)
30 , fInitialSaveCount(kNoInitialSave) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000031}
32
33SkPictureRecord::~SkPictureRecord() {
robertphillips5351aad2015-06-23 06:54:56 -070034 fImageRefs.unrefAll();
djsollen@google.com21830d92012-08-07 19:49:41 +000035 fPictureRefs.unrefAll();
msarett95416f42016-04-27 13:51:20 -070036 fDrawableRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070037 fTextBlobRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000038}
39
40///////////////////////////////////////////////////////////////////////////////
41
Florin Malita5f6102d2014-06-30 10:13:28 -040042void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +000043 // record the offset to us, making it non-positive to distinguish a save
44 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +000045 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -040046 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000047
Florin Malita5f6102d2014-06-30 10:13:28 -040048 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +000049}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +000050
Florin Malita5f6102d2014-06-30 10:13:28 -040051void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -070052 fContentInfo.onSave();
53
Florin Malita5f6102d2014-06-30 10:13:28 -040054 // op only
reed512f3e32016-01-04 14:11:31 -080055 size_t size = sizeof(kUInt32Size);
robertphillips@google.com8b169312013-10-15 17:47:36 +000056 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +000057
robertphillips@google.com8b169312013-10-15 17:47:36 +000058 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +000059}
60
reed4960eee2015-12-18 07:09:18 -080061SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
reed@google.comffacd3c2012-08-30 15:31:23 +000062 // record the offset to us, making it non-positive to distinguish a save
63 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +000064 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
reed4960eee2015-12-18 07:09:18 -080065 this->recordSaveLayer(rec);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +000066
reed4960eee2015-12-18 07:09:18 -080067 (void)this->INHERITED::getSaveLayerStrategy(rec);
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000068 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +000069 at this time (and may not be able to afford since during record our
70 clip starts out the size of the picture, which is often much larger
71 than the size of the actual device we'll use during playback).
72 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000073 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +000074}
75
reed4960eee2015-12-18 07:09:18 -080076void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
robertphillipsc019ec42014-08-12 05:35:58 -070077 fContentInfo.onSaveLayer();
78
reedbfd5f172016-01-07 11:28:08 -080079 // op + flatflags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +000080 size_t size = 2 * kUInt32Size;
reedbfd5f172016-01-07 11:28:08 -080081 uint32_t flatFlags = 0;
82
reed4960eee2015-12-18 07:09:18 -080083 if (rec.fBounds) {
reedbfd5f172016-01-07 11:28:08 -080084 flatFlags |= SAVELAYERREC_HAS_BOUNDS;
85 size += sizeof(*rec.fBounds);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000086 }
reedbfd5f172016-01-07 11:28:08 -080087 if (rec.fPaint) {
88 flatFlags |= SAVELAYERREC_HAS_PAINT;
89 size += sizeof(uint32_t); // index
90 }
91 if (rec.fBackdrop) {
92 flatFlags |= SAVELAYERREC_HAS_BACKDROP;
93 size += sizeof(uint32_t); // (paint) index
94 }
95 if (rec.fSaveLayerFlags) {
96 flatFlags |= SAVELAYERREC_HAS_FLAGS;
97 size += sizeof(uint32_t);
98 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000099
reedbfd5f172016-01-07 11:28:08 -0800100 const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
101 this->addInt(flatFlags);
102 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
103 this->addRect(*rec.fBounds);
104 }
105 if (flatFlags & SAVELAYERREC_HAS_PAINT) {
106 this->addPaintPtr(rec.fPaint);
107 }
108 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
109 // overkill, but we didn't already track single flattenables, so using a paint for that
110 SkPaint paint;
111 paint.setImageFilter(const_cast<SkImageFilter*>(rec.fBackdrop));
112 this->addPaint(paint);
113 }
114 if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
115 this->addInt(rec.fSaveLayerFlags);
116 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000117 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000118}
119
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000120#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000121/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000122 * Read the op code from 'offset' in 'writer' and extract the size too.
123 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000124static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000125 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000126
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000127 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000128 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000129 if (MASK_24 == *size) {
130 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000131 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000132 }
133 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000134}
mtklein46616af2014-09-30 14:47:10 -0700135#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000136
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000137void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000138#if 0
139 SkASSERT(fRestoreOffsetStack.count() > 1);
140#endif
141
reed@android.comb4e22d62009-07-09 15:20:25 +0000142 // check for underflow
143 if (fRestoreOffsetStack.count() == 0) {
144 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000146
mtklein46616af2014-09-30 14:47:10 -0700147 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000148
reed@android.comb4e22d62009-07-09 15:20:25 +0000149 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000150
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000151 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152}
153
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000154void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700155 fContentInfo.onRestore();
156
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000157 if (fillInSkips) {
158 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
159 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000160 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
161 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000162 this->validate(initialOffset, size);
163}
164
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000165void SkPictureRecord::recordTranslate(const SkMatrix& m) {
166 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
167
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000168 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000169 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000170 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000171 this->addScalar(m.getTranslateX());
172 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000173 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174}
175
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000176void SkPictureRecord::recordScale(const SkMatrix& m) {
177 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000178
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000179 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000180 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000181 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000182 this->addScalar(m.getScaleX());
183 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000184 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185}
186
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000187void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000188 switch (matrix.getType()) {
189 case SkMatrix::kTranslate_Mask:
190 this->recordTranslate(matrix);
191 break;
192 case SkMatrix::kScale_Mask:
193 this->recordScale(matrix);
194 break;
195 default:
196 this->recordConcat(matrix);
197 break;
198 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000199 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000200}
201
202void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000203 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000204 // op + matrix
halcanary96fcdcc2015-08-27 07:41:13 -0700205 size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000206 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000207 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000208 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209}
210
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000211void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000212 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000213 // op + matrix
halcanary96fcdcc2015-08-27 07:41:13 -0700214 size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000215 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000216 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000217 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000218 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000219}
220
vjiaoblacke5de1302016-07-13 14:05:28 -0700221void SkPictureRecord::didTranslateZ(SkScalar z) {
vjiaoblack95302da2016-07-21 10:25:54 -0700222#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke5de1302016-07-13 14:05:28 -0700223 this->validate(fWriter.bytesWritten(), 0);
224 // op + scalar
225 size_t size = 1 * kUInt32Size + 1 * sizeof(SkScalar);
226 size_t initialOffset = this->addDraw(TRANSLATE_Z, &size);
227 this->addScalar(z);
228 this->validate(initialOffset, size);
229 this->INHERITED::didTranslateZ(z);
vjiaoblack95302da2016-07-21 10:25:54 -0700230#endif
vjiaoblacke5de1302016-07-13 14:05:28 -0700231}
232
reed@google.com45482d12011-08-29 19:02:39 +0000233static bool regionOpExpands(SkRegion::Op op) {
234 switch (op) {
235 case SkRegion::kUnion_Op:
236 case SkRegion::kXOR_Op:
237 case SkRegion::kReverseDifference_Op:
238 case SkRegion::kReplace_Op:
239 return true;
240 case SkRegion::kIntersect_Op:
241 case SkRegion::kDifference_Op:
242 return false;
243 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000244 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000245 return false;
246 }
247}
248
robertphillips@google.come37ad352013-03-01 19:44:30 +0000249void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000250 int32_t offset = fRestoreOffsetStack.top();
251 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000252 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
253 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000254 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000255 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000256
reed@google.comffacd3c2012-08-30 15:31:23 +0000257#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800258 // offset of 0 has been disabled, so we skip it
259 if (offset > 0) {
260 // assert that the final offset value points to a save verb
261 uint32_t opSize;
262 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
reed4960eee2015-12-18 07:09:18 -0800263 SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
reedbfd5f172016-01-07 11:28:08 -0800264 SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
265 SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
reed2ff1fce2014-12-11 07:07:37 -0800266 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000267#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000268}
269
reed@google.comd86e7ab2012-09-27 20:31:31 +0000270void SkPictureRecord::beginRecording() {
271 // we have to call this *after* our constructor, to ensure that it gets
272 // recorded. This is balanced by restoreToCount() call from endRecording,
273 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000274 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000275}
276
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000277void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000278 SkASSERT(kNoInitialSave != fInitialSaveCount);
279 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000280}
281
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000282size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000283 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000284 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000285 }
286
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000287 // The RestoreOffset field is initially filled with a placeholder
288 // value that points to the offset of the previous RestoreOffset
289 // in the current stack level, thus forming a linked list so that
290 // the restore offsets can be filled in when the corresponding
291 // restore command is recorded.
292 int32_t prevOffset = fRestoreOffsetStack.top();
293
reed@google.com45482d12011-08-29 19:02:39 +0000294 if (regionOpExpands(op)) {
295 // Run back through any previous clip ops, and mark their offset to
296 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
297 // they could hide this clips ability to expand the clip (i.e. go from
298 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000299 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000300
301 // Reset the pointer back to the previous clip so that subsequent
302 // restores don't overwrite the offsets we just cleared.
303 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000304 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000305
reed@google.com44699382013-10-31 17:28:30 +0000306 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000307 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000308 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000309 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000310}
311
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000312void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000313 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000314 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000315}
316
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000317size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000318 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000319 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000320 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000321 if (!fRestoreOffsetStack.isEmpty()) {
322 // + restore offset
323 size += kUInt32Size;
324 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000325 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000326 this->addRect(rect);
327 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000328 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000329
robertphillips@google.com8b169312013-10-15 17:47:36 +0000330 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000331 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000332}
333
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000334void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000335 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700336 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000337}
338
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000339size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000340 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000341 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000342 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000343 if (!fRestoreOffsetStack.isEmpty()) {
344 // + restore offset
345 size += kUInt32Size;
346 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000347 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000348 this->addRRect(rrect);
349 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000350 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000351 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000352 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000353}
354
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000355void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000356 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000357 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700358 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000359}
360
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000361size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000362 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000363 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000364 // recordRestoreOffsetPlaceholder doesn't always write an offset
365 if (!fRestoreOffsetStack.isEmpty()) {
366 // + restore offset
367 size += kUInt32Size;
368 }
369 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000370 this->addInt(pathID);
371 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000372 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000373 this->validate(initialOffset, size);
374 return offset;
375}
376
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000377void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000378 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000379 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000380}
381
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000382size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000383 // op + clip params + region
halcanary96fcdcc2015-08-27 07:41:13 -0700384 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000385 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000386 if (!fRestoreOffsetStack.isEmpty()) {
387 // + restore offset
388 size += kUInt32Size;
389 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000390 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000391 this->addRegion(region);
392 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000393 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000394
robertphillips@google.com8b169312013-10-15 17:47:36 +0000395 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000396 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000397}
398
reed41af9662015-01-05 07:49:08 -0800399void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000400 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000401 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000402 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000403 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000404 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000405}
406
reed41af9662015-01-05 07:49:08 -0800407void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
408 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700409 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000410
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000411 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000412 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000413 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000414 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700415
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000416 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000417 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000419 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000420}
421
reed41af9662015-01-05 07:49:08 -0800422void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000423 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000424 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000425 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000426 this->addPaint(paint);
427 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000428 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000429}
430
reed41af9662015-01-05 07:49:08 -0800431void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000432 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000433 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000434 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000435 this->addPaint(paint);
436 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000437 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000438}
439
reed41af9662015-01-05 07:49:08 -0800440void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700441 // op + paint index + rrect
442 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
443 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein46616af2014-09-30 14:47:10 -0700444 this->addPaint(paint);
445 this->addRRect(rrect);
446 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000447}
448
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000449void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
450 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000451 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000452 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
453 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000454 this->addPaint(paint);
455 this->addRRect(outer);
456 this->addRRect(inner);
457 this->validate(initialOffset, size);
458}
459
reed41af9662015-01-05 07:49:08 -0800460void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700461 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000462
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000463 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000464 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000465 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000466 this->addPaint(paint);
467 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000468 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000469}
470
reed41af9662015-01-05 07:49:08 -0800471void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
472 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000473 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000474 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000475 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000476 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000477 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000478 this->addScalar(left);
479 this->addScalar(top);
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::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700484 const SkPaint* paint, SrcRectConstraint constraint) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000485 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000486 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700487 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000488 size += sizeof(*src); // + rect
489 }
490 size += sizeof(dst); // + rect
491
reeda5517e22015-07-14 10:54:12 -0700492 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000493 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000494 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000495 this->addRectPtr(src); // may be null
496 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700497 this->addInt(constraint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000498 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000499}
500
reeda85d4d02015-05-06 12:56:48 -0700501void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
502 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700503 // op + paint_index + image_index + x + y
504 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
505 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
reed871872f2015-06-22 12:48:26 -0700506 this->addPaintPtr(paint);
507 this->addImage(image);
508 this->addScalar(x);
509 this->addScalar(y);
510 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700511}
512
513void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700514 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700515 // id + paint_index + image_index + bool_for_src + constraint
516 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700517 if (src) {
518 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700519 }
reed871872f2015-06-22 12:48:26 -0700520 size += sizeof(dst); // + rect
mtkleinc2e29772015-10-30 05:24:58 -0700521
reed871872f2015-06-22 12:48:26 -0700522 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
reed871872f2015-06-22 12:48:26 -0700523 this->addPaintPtr(paint);
524 this->addImage(image);
525 this->addRectPtr(src); // may be null
526 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700527 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700528 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700529}
530
reed4c21dc52015-06-25 12:32:03 -0700531void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
532 const SkPaint* paint) {
533 // id + paint_index + image_index + center + dst
534 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
mtkleinc2e29772015-10-30 05:24:58 -0700535
reed4c21dc52015-06-25 12:32:03 -0700536 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
reed4c21dc52015-06-25 12:32:03 -0700537 this->addPaintPtr(paint);
538 this->addImage(img);
539 this->addIRect(center);
540 this->addRect(dst);
541 this->validate(initialOffset, size);
542}
543
reed41af9662015-01-05 07:49:08 -0800544void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
545 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000546 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000547 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000548 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000549 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000550 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000551 this->addIRect(center);
552 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000553 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000554}
555
reed@google.come0d9ce82014-04-23 04:00:17 +0000556void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
557 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000558 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000559 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000560
mtklein46616af2014-09-30 14:47:10 -0700561 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000562 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700563 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000564 this->addText(text, byteLength);
565 this->addScalar(x);
566 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000567 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000568}
569
reed@google.come0d9ce82014-04-23 04:00:17 +0000570void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
571 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000572 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000573
mtklein46616af2014-09-30 14:47:10 -0700574 // op + paint index + length + 'length' worth of data + num points + x&y point data
575 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000576
mtklein46616af2014-09-30 14:47:10 -0700577 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000578
robertphillips@google.com8b169312013-10-15 17:47:36 +0000579 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700580 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000581 this->addText(text, byteLength);
582 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700583 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000584 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000585}
586
reed@google.come0d9ce82014-04-23 04:00:17 +0000587void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
588 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000589 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000591 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000592 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000593 // + y + the actual points
594 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000595
mtklein46616af2014-09-30 14:47:10 -0700596 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
597 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000598 this->addText(text, byteLength);
599 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000600 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000601 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000602 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000603}
604
reed@google.come0d9ce82014-04-23 04:00:17 +0000605void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
606 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000607 // op + paint index + length + 'length' worth of data + path index + matrix
608 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700609 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000610 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000611 this->addPaint(paint);
612 this->addText(text, byteLength);
613 this->addPath(path);
614 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000615 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616}
617
reed45561a02016-07-07 12:47:17 -0700618void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
619 const SkRSXform xform[], const SkRect* cull,
620 const SkPaint& paint) {
621 const int count = paint.countText(text, byteLength);
622 // [op + paint-index + count + flags + length] + [text] + [xform] + cull
623 size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
624 uint32_t flags = 0;
625 if (cull) {
626 flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
627 size += sizeof(SkRect);
628 }
629
630 size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
631 this->addPaint(paint);
632 this->addInt(count);
633 this->addInt(flags);
634 this->addText(text, byteLength);
635 fWriter.write(xform, count * sizeof(SkRSXform));
636 if (cull) {
637 fWriter.write(cull, sizeof(SkRect));
638 }
639 this->validate(initialOffset, size);
640}
641
fmalitab7425172014-08-26 07:56:44 -0700642void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
643 const SkPaint& paint) {
644
645 // op + paint index + blob index + x/y
646 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
647 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
fmalitab7425172014-08-26 07:56:44 -0700648
649 this->addPaint(paint);
650 this->addTextBlob(blob);
651 this->addScalar(x);
652 this->addScalar(y);
653
654 this->validate(initialOffset, size);
655}
656
reedd5fa1a42014-08-09 11:08:05 -0700657void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
658 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000659 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000660 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700661 size_t initialOffset;
662
halcanary96fcdcc2015-08-27 07:41:13 -0700663 if (nullptr == matrix && nullptr == paint) {
reedd5fa1a42014-08-09 11:08:05 -0700664 initialOffset = this->addDraw(DRAW_PICTURE, &size);
665 this->addPicture(picture);
666 } else {
667 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700668 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
reedd5fa1a42014-08-09 11:08:05 -0700669 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
reedd5fa1a42014-08-09 11:08:05 -0700670 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700671 this->addMatrix(m);
672 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700673 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000674 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000675}
676
vjiaoblack95302da2016-07-21 10:25:54 -0700677void SkPictureRecord::onDrawShadowedPicture(const SkPicture* picture,
678 const SkMatrix* matrix,
679 const SkPaint* paint) {
680 // op + picture index
681 size_t size = 2 * kUInt32Size;
682 size_t initialOffset;
683
684 if (nullptr == matrix && nullptr == paint) {
685 initialOffset = this->addDraw(DRAW_PICTURE, &size);
686 this->addPicture(picture);
687 } else {
688 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
689 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
690 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
691 this->addPaintPtr(paint);
692 this->addMatrix(m);
693 this->addPicture(picture);
694 }
695 this->validate(initialOffset, size);
696}
697
msarett95416f42016-04-27 13:51:20 -0700698void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
699 // op + drawable index
700 size_t size = 2 * kUInt32Size;
701 size_t initialOffset;
702
703 if (nullptr == matrix) {
704 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
705 this->addDrawable(drawable);
706 } else {
707 size += matrix->writeToMemory(nullptr); // matrix
708 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
709 this->addMatrix(*matrix);
710 this->addDrawable(drawable);
711 }
712 this->validate(initialOffset, size);
713}
714
reed41af9662015-01-05 07:49:08 -0800715void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
716 const SkPoint vertices[], const SkPoint texs[],
717 const SkColor colors[], SkXfermode* xfer,
718 const uint16_t indices[], int indexCount,
719 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000720 uint32_t flags = 0;
721 if (texs) {
722 flags |= DRAW_VERTICES_HAS_TEXS;
723 }
724 if (colors) {
725 flags |= DRAW_VERTICES_HAS_COLORS;
726 }
727 if (indexCount > 0) {
728 flags |= DRAW_VERTICES_HAS_INDICES;
729 }
bsalomon49f085d2014-09-05 13:34:00 -0700730 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000731 SkXfermode::Mode mode;
732 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
733 flags |= DRAW_VERTICES_HAS_XFER;
734 }
735 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000736
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000737 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000738 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000739 if (flags & DRAW_VERTICES_HAS_TEXS) {
740 size += vertexCount * sizeof(SkPoint); // + uvs
741 }
742 if (flags & DRAW_VERTICES_HAS_COLORS) {
743 size += vertexCount * sizeof(SkColor); // + vert colors
744 }
745 if (flags & DRAW_VERTICES_HAS_INDICES) {
746 // + num indices + indices
747 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
748 }
reed@google.com85e143c2013-12-30 15:51:25 +0000749 if (flags & DRAW_VERTICES_HAS_XFER) {
750 size += kUInt32Size; // mode enum
751 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000752
robertphillips@google.com8b169312013-10-15 17:47:36 +0000753 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000754 this->addPaint(paint);
755 this->addInt(flags);
756 this->addInt(vmode);
757 this->addInt(vertexCount);
758 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000759 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000760 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000761 }
762 if (flags & DRAW_VERTICES_HAS_COLORS) {
763 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
764 }
765 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000766 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000767 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
768 }
reed@google.com85e143c2013-12-30 15:51:25 +0000769 if (flags & DRAW_VERTICES_HAS_XFER) {
770 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
771 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000772 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000773 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000774 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000775}
776
dandovb3c9d1c2014-08-12 08:34:29 -0700777void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
778 const SkPoint texCoords[4], SkXfermode* xmode,
779 const SkPaint& paint) {
780 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
781 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
782 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700783 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700784 flag |= DRAW_VERTICES_HAS_COLORS;
785 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
786 }
bsalomon49f085d2014-09-05 13:34:00 -0700787 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700788 flag |= DRAW_VERTICES_HAS_TEXS;
789 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
790 }
bsalomon49f085d2014-09-05 13:34:00 -0700791 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700792 SkXfermode::Mode mode;
793 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
794 flag |= DRAW_VERTICES_HAS_XFER;
795 size += kUInt32Size;
796 }
797 }
mtklein46616af2014-09-30 14:47:10 -0700798
dandov963137b2014-08-07 07:49:53 -0700799 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
dandov963137b2014-08-07 07:49:53 -0700800 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700801 this->addPatch(cubics);
802 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700803
dandovb3c9d1c2014-08-12 08:34:29 -0700804 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700805 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700806 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
807 }
bsalomon49f085d2014-09-05 13:34:00 -0700808 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700809 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
810 }
811 if (flag & DRAW_VERTICES_HAS_XFER) {
812 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
813 xmode->asMode(&mode);
814 this->addInt(mode);
815 }
dandov963137b2014-08-07 07:49:53 -0700816 this->validate(initialOffset, size);
817}
818
reed71c3c762015-06-24 10:29:17 -0700819void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
820 const SkColor colors[], int count, SkXfermode::Mode mode,
821 const SkRect* cull, const SkPaint* paint) {
822 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
823 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
824 uint32_t flags = 0;
825 if (colors) {
826 flags |= DRAW_ATLAS_HAS_COLORS;
827 size += count * sizeof(SkColor);
828 size += sizeof(uint32_t); // xfermode::mode
829 }
830 if (cull) {
831 flags |= DRAW_ATLAS_HAS_CULL;
832 size += sizeof(SkRect);
833 }
mtkleinc2e29772015-10-30 05:24:58 -0700834
reed71c3c762015-06-24 10:29:17 -0700835 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
reed71c3c762015-06-24 10:29:17 -0700836 this->addPaintPtr(paint);
837 this->addImage(atlas);
838 this->addInt(flags);
839 this->addInt(count);
840 fWriter.write(xform, count * sizeof(SkRSXform));
841 fWriter.write(tex, count * sizeof(SkRect));
842
843 // write optional parameters
844 if (colors) {
845 fWriter.write(colors, count * sizeof(SkColor));
846 this->addInt(mode);
847 }
848 if (cull) {
849 fWriter.write(cull, sizeof(SkRect));
850 }
851 this->validate(initialOffset, size);
852}
853
reedf70b5312016-03-04 16:36:20 -0800854void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
855 size_t keyLen = fWriter.WriteStringSize(key);
856 size_t valueLen = fWriter.WriteDataSize(value);
857 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
858
859 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
860 this->addRect(rect);
861 fWriter.writeString(key);
862 fWriter.writeData(value);
863 this->validate(initialOffset, size);
864}
865
reed@android.com8a1c16f2008-12-17 15:59:43 +0000866///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000867
reede8f30622016-03-23 18:59:25 -0700868sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700869 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000870}
871
mtkleine0694002014-11-12 12:49:47 -0800872// If we already have a stored, can we reuse it instead of also storing b?
873static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
874 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
875 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
876 // but it sure makes things easier to reason about below.
877 return false;
878 }
879 if (a.pixelRef() == b.pixelRef()) {
880 return true; // Same shape and same pixels -> same bitmap.
881 }
882
883 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
884 if (!a.pixelRef() || !b.pixelRef()) {
885 return false;
886 }
887
888 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
889 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
890 encB(b.pixelRef()->refEncodedData());
891 if (encA && encB) {
892 return encA->equals(encB);
893 } else if (encA || encB) {
894 return false; // One has encoded data but the other does not.
895 }
896
897 // As a last resort, we have to look at the pixels. This will read back textures.
898 SkAutoLockPixels al(a), bl(b);
899 const char* ap = (const char*)a.getPixels();
900 const char* bp = (const char*)b.getPixels();
901 if (ap && bp) {
902 // We check row by row; row bytes might differ.
903 SkASSERT(a.info() == b.info()); // We checked this above.
904 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
905 const SkImageInfo info = a.info();
906 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
907 for (int row = 0; row < info.height(); row++) {
908 if (0 != memcmp(ap, bp, bytesToCompare)) {
909 return false;
910 }
911 ap += a.rowBytes();
912 bp += b.rowBytes();
913 }
914 return true;
915 }
916 return false; // Couldn't get pixels for both bitmaps.
917}
918
919void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
920 // First see if we already have this bitmap. This deduplication should really
921 // only be important for our tests, where bitmaps tend not to be tagged immutable.
922 // In Chrome (and hopefully Android?) they're typically immutable.
923 for (int i = 0; i < fBitmaps.count(); i++) {
924 if (equivalent(fBitmaps[i], bitmap)) {
925 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
926 return;
927 }
928 }
929 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800930 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800931 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800932 fBitmaps.push_back(bitmap);
933 } else {
mtkleine0694002014-11-12 12:49:47 -0800934 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800935 SkBitmap copy;
936 bitmap.copyTo(&copy);
937 copy.setImmutable();
938 fBitmaps.push_back(copy);
939 }
mtkleine0694002014-11-12 12:49:47 -0800940 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000941}
942
reed871872f2015-06-22 12:48:26 -0700943void SkPictureRecord::addImage(const SkImage* image) {
944 int index = fImageRefs.find(image);
945 if (index >= 0) {
946 this->addInt(index);
947 } else {
948 *fImageRefs.append() = SkRef(image);
949 this->addInt(fImageRefs.count()-1);
950 }
951}
952
reed@android.com8a1c16f2008-12-17 15:59:43 +0000953void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000954 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000955}
956
mtklein46616af2014-09-30 14:47:10 -0700957void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700958 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000959
mtklein46616af2014-09-30 14:47:10 -0700960 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800961 fPaints.push_back(*paint);
962 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700963 } else {
964 this->addInt(0);
965 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000966}
967
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000968int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700969 if (int* n = fPaths.find(path)) {
970 return *n;
971 }
972 int n = fPaths.count() + 1; // 0 is reserved for null / error.
973 fPaths.set(path, n);
974 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000975}
976
977void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000978 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000979}
980
dandovb3c9d1c2014-08-12 08:34:29 -0700981void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
982 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700983}
984
robertphillips9b14f262014-06-04 05:40:44 -0700985void SkPictureRecord::addPicture(const SkPicture* picture) {
986 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000987 if (index < 0) { // not found
988 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700989 *fPictureRefs.append() = picture;
990 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000991 }
992 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000993 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000994}
995
msarett95416f42016-04-27 13:51:20 -0700996void SkPictureRecord::addDrawable(SkDrawable* drawable) {
997 int index = fDrawableRefs.find(drawable);
998 if (index < 0) { // not found
999 index = fDrawableRefs.count();
1000 *fDrawableRefs.append() = drawable;
1001 drawable->ref();
1002 }
1003 // follow the convention of recording a 1-based index
1004 this->addInt(index + 1);
1005}
1006
reed@android.com8a1c16f2008-12-17 15:59:43 +00001007void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001008 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001009}
reed@google.com82065d62011-02-07 15:30:46 +00001010
reed@android.com8a1c16f2008-12-17 15:59:43 +00001011void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
1012 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001013}
1014
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001015void SkPictureRecord::addNoOp() {
1016 size_t size = kUInt32Size; // op
1017 this->addDraw(NOOP, &size);
1018}
1019
reed@android.com8a1c16f2008-12-17 15:59:43 +00001020void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001021 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001022}
1023
1024void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -07001025 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001026 fWriter.writeRect(*rect);
1027 }
1028}
1029
reed@google.comf0b5e112011-09-07 11:57:34 +00001030void SkPictureRecord::addIRect(const SkIRect& rect) {
1031 fWriter.write(&rect, sizeof(rect));
1032}
1033
reed@android.com8a1c16f2008-12-17 15:59:43 +00001034void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -07001035 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001036 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
1037 }
1038}
1039
reed@google.com4ed0fb72012-12-12 20:48:18 +00001040void SkPictureRecord::addRRect(const SkRRect& rrect) {
1041 fWriter.writeRRect(rrect);
1042}
1043
reed@android.com8a1c16f2008-12-17 15:59:43 +00001044void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001045 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001046}
1047
1048void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001049 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001050 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001051 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001052}
1053
fmalitab7425172014-08-26 07:56:44 -07001054void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001055 int index = fTextBlobRefs.count();
1056 *fTextBlobRefs.append() = blob;
1057 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001058 // follow the convention of recording a 1-based index
1059 this->addInt(index + 1);
1060}
1061
reed@android.com8a1c16f2008-12-17 15:59:43 +00001062///////////////////////////////////////////////////////////////////////////////