blob: 17ed1aa20b69ea5c1470e82c06280d935bde01a7 [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
reed@google.com45482d12011-08-29 19:02:39 +0000221static bool regionOpExpands(SkRegion::Op op) {
222 switch (op) {
223 case SkRegion::kUnion_Op:
224 case SkRegion::kXOR_Op:
225 case SkRegion::kReverseDifference_Op:
226 case SkRegion::kReplace_Op:
227 return true;
228 case SkRegion::kIntersect_Op:
229 case SkRegion::kDifference_Op:
230 return false;
231 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000232 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000233 return false;
234 }
235}
236
robertphillips@google.come37ad352013-03-01 19:44:30 +0000237void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000238 int32_t offset = fRestoreOffsetStack.top();
239 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000240 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
241 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000242 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000243 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000244
reed@google.comffacd3c2012-08-30 15:31:23 +0000245#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800246 // offset of 0 has been disabled, so we skip it
247 if (offset > 0) {
248 // assert that the final offset value points to a save verb
249 uint32_t opSize;
250 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
reed4960eee2015-12-18 07:09:18 -0800251 SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
reedbfd5f172016-01-07 11:28:08 -0800252 SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
253 SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
reed2ff1fce2014-12-11 07:07:37 -0800254 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000255#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000256}
257
reed@google.comd86e7ab2012-09-27 20:31:31 +0000258void SkPictureRecord::beginRecording() {
259 // we have to call this *after* our constructor, to ensure that it gets
260 // recorded. This is balanced by restoreToCount() call from endRecording,
261 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000262 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000263}
264
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000265void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000266 SkASSERT(kNoInitialSave != fInitialSaveCount);
267 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000268}
269
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000270size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000271 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000272 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000273 }
274
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000275 // The RestoreOffset field is initially filled with a placeholder
276 // value that points to the offset of the previous RestoreOffset
277 // in the current stack level, thus forming a linked list so that
278 // the restore offsets can be filled in when the corresponding
279 // restore command is recorded.
280 int32_t prevOffset = fRestoreOffsetStack.top();
281
reed@google.com45482d12011-08-29 19:02:39 +0000282 if (regionOpExpands(op)) {
283 // Run back through any previous clip ops, and mark their offset to
284 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
285 // they could hide this clips ability to expand the clip (i.e. go from
286 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000287 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000288
289 // Reset the pointer back to the previous clip so that subsequent
290 // restores don't overwrite the offsets we just cleared.
291 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000292 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000293
reed@google.com44699382013-10-31 17:28:30 +0000294 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000295 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000296 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000297 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000298}
299
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000300void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000301 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000302 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000303}
304
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000305size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000306 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000307 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000308 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000309 if (!fRestoreOffsetStack.isEmpty()) {
310 // + restore offset
311 size += kUInt32Size;
312 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000313 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000314 this->addRect(rect);
315 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000316 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000317
robertphillips@google.com8b169312013-10-15 17:47:36 +0000318 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000319 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000320}
321
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000322void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000323 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700324 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000325}
326
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000327size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000328 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000329 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000330 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000331 if (!fRestoreOffsetStack.isEmpty()) {
332 // + restore offset
333 size += kUInt32Size;
334 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000335 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000336 this->addRRect(rrect);
337 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000338 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000339 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000340 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000341}
342
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000343void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000344 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000345 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700346 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000347}
348
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000349size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000350 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000351 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000352 // recordRestoreOffsetPlaceholder doesn't always write an offset
353 if (!fRestoreOffsetStack.isEmpty()) {
354 // + restore offset
355 size += kUInt32Size;
356 }
357 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000358 this->addInt(pathID);
359 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000360 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000361 this->validate(initialOffset, size);
362 return offset;
363}
364
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000365void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000366 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000367 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000368}
369
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000370size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000371 // op + clip params + region
halcanary96fcdcc2015-08-27 07:41:13 -0700372 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000373 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000374 if (!fRestoreOffsetStack.isEmpty()) {
375 // + restore offset
376 size += kUInt32Size;
377 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000378 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000379 this->addRegion(region);
380 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000381 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000382
robertphillips@google.com8b169312013-10-15 17:47:36 +0000383 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000384 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000385}
386
reed41af9662015-01-05 07:49:08 -0800387void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000388 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000389 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000390 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000391 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000392 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000393}
394
reed41af9662015-01-05 07:49:08 -0800395void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
396 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700397 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000398
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000399 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000400 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000401 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000402 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700403
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000404 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000405 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000406 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000407 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000408}
409
reed41af9662015-01-05 07:49:08 -0800410void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000411 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000412 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000413 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000414 this->addPaint(paint);
415 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000416 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000417}
418
reed41af9662015-01-05 07:49:08 -0800419void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000420 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000421 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000422 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000423 this->addPaint(paint);
424 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000425 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000426}
427
reed41af9662015-01-05 07:49:08 -0800428void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700429 // op + paint index + rrect
430 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
431 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein46616af2014-09-30 14:47:10 -0700432 this->addPaint(paint);
433 this->addRRect(rrect);
434 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000435}
436
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000437void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
438 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000439 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000440 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
441 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000442 this->addPaint(paint);
443 this->addRRect(outer);
444 this->addRRect(inner);
445 this->validate(initialOffset, size);
446}
447
reed41af9662015-01-05 07:49:08 -0800448void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700449 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000450
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000451 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000452 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000453 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000454 this->addPaint(paint);
455 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000456 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000457}
458
reed41af9662015-01-05 07:49:08 -0800459void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
460 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000461 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000462 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000463 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000464 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000465 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000466 this->addScalar(left);
467 this->addScalar(top);
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::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700472 const SkPaint* paint, SrcRectConstraint constraint) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000473 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000474 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700475 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000476 size += sizeof(*src); // + rect
477 }
478 size += sizeof(dst); // + rect
479
reeda5517e22015-07-14 10:54:12 -0700480 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000481 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000482 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000483 this->addRectPtr(src); // may be null
484 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700485 this->addInt(constraint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000486 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000487}
488
reeda85d4d02015-05-06 12:56:48 -0700489void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
490 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700491 // op + paint_index + image_index + x + y
492 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
493 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
reed871872f2015-06-22 12:48:26 -0700494 this->addPaintPtr(paint);
495 this->addImage(image);
496 this->addScalar(x);
497 this->addScalar(y);
498 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700499}
500
501void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700502 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700503 // id + paint_index + image_index + bool_for_src + constraint
504 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700505 if (src) {
506 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700507 }
reed871872f2015-06-22 12:48:26 -0700508 size += sizeof(dst); // + rect
mtkleinc2e29772015-10-30 05:24:58 -0700509
reed871872f2015-06-22 12:48:26 -0700510 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
reed871872f2015-06-22 12:48:26 -0700511 this->addPaintPtr(paint);
512 this->addImage(image);
513 this->addRectPtr(src); // may be null
514 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700515 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700516 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700517}
518
reed4c21dc52015-06-25 12:32:03 -0700519void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
520 const SkPaint* paint) {
521 // id + paint_index + image_index + center + dst
522 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
mtkleinc2e29772015-10-30 05:24:58 -0700523
reed4c21dc52015-06-25 12:32:03 -0700524 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
reed4c21dc52015-06-25 12:32:03 -0700525 this->addPaintPtr(paint);
526 this->addImage(img);
527 this->addIRect(center);
528 this->addRect(dst);
529 this->validate(initialOffset, size);
530}
531
reed41af9662015-01-05 07:49:08 -0800532void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
533 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000534 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000535 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000536 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000537 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000538 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000539 this->addIRect(center);
540 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000541 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000542}
543
reed@google.come0d9ce82014-04-23 04:00:17 +0000544void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
545 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000546 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000547 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000548
mtklein46616af2014-09-30 14:47:10 -0700549 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000550 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700551 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000552 this->addText(text, byteLength);
553 this->addScalar(x);
554 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000555 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000556}
557
reed@google.come0d9ce82014-04-23 04:00:17 +0000558void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
559 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000560 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000561
mtklein46616af2014-09-30 14:47:10 -0700562 // op + paint index + length + 'length' worth of data + num points + x&y point data
563 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000564
mtklein46616af2014-09-30 14:47:10 -0700565 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000566
robertphillips@google.com8b169312013-10-15 17:47:36 +0000567 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700568 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000569 this->addText(text, byteLength);
570 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700571 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000572 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000573}
574
reed@google.come0d9ce82014-04-23 04:00:17 +0000575void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
576 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000577 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000578
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000579 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000580 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000581 // + y + the actual points
582 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000583
mtklein46616af2014-09-30 14:47:10 -0700584 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
585 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000586 this->addText(text, byteLength);
587 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000588 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000589 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000590 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000591}
592
reed@google.come0d9ce82014-04-23 04:00:17 +0000593void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
594 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000595 // op + paint index + length + 'length' worth of data + path index + matrix
596 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700597 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000598 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000599 this->addPaint(paint);
600 this->addText(text, byteLength);
601 this->addPath(path);
602 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000603 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000604}
605
reed45561a02016-07-07 12:47:17 -0700606void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
607 const SkRSXform xform[], const SkRect* cull,
608 const SkPaint& paint) {
609 const int count = paint.countText(text, byteLength);
610 // [op + paint-index + count + flags + length] + [text] + [xform] + cull
611 size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
612 uint32_t flags = 0;
613 if (cull) {
614 flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
615 size += sizeof(SkRect);
616 }
617
618 size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
619 this->addPaint(paint);
620 this->addInt(count);
621 this->addInt(flags);
622 this->addText(text, byteLength);
623 fWriter.write(xform, count * sizeof(SkRSXform));
624 if (cull) {
625 fWriter.write(cull, sizeof(SkRect));
626 }
627 this->validate(initialOffset, size);
628}
629
fmalitab7425172014-08-26 07:56:44 -0700630void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
631 const SkPaint& paint) {
632
633 // op + paint index + blob index + x/y
634 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
635 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
fmalitab7425172014-08-26 07:56:44 -0700636
637 this->addPaint(paint);
638 this->addTextBlob(blob);
639 this->addScalar(x);
640 this->addScalar(y);
641
642 this->validate(initialOffset, size);
643}
644
reedd5fa1a42014-08-09 11:08:05 -0700645void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
646 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000647 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000648 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700649 size_t initialOffset;
650
halcanary96fcdcc2015-08-27 07:41:13 -0700651 if (nullptr == matrix && nullptr == paint) {
reedd5fa1a42014-08-09 11:08:05 -0700652 initialOffset = this->addDraw(DRAW_PICTURE, &size);
653 this->addPicture(picture);
654 } else {
655 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700656 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
reedd5fa1a42014-08-09 11:08:05 -0700657 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
reedd5fa1a42014-08-09 11:08:05 -0700658 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700659 this->addMatrix(m);
660 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700661 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000662 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000663}
664
msarett95416f42016-04-27 13:51:20 -0700665void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
666 // op + drawable index
667 size_t size = 2 * kUInt32Size;
668 size_t initialOffset;
669
670 if (nullptr == matrix) {
671 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
672 this->addDrawable(drawable);
673 } else {
674 size += matrix->writeToMemory(nullptr); // matrix
675 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
676 this->addMatrix(*matrix);
677 this->addDrawable(drawable);
678 }
679 this->validate(initialOffset, size);
680}
681
reed41af9662015-01-05 07:49:08 -0800682void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
683 const SkPoint vertices[], const SkPoint texs[],
684 const SkColor colors[], SkXfermode* xfer,
685 const uint16_t indices[], int indexCount,
686 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000687 uint32_t flags = 0;
688 if (texs) {
689 flags |= DRAW_VERTICES_HAS_TEXS;
690 }
691 if (colors) {
692 flags |= DRAW_VERTICES_HAS_COLORS;
693 }
694 if (indexCount > 0) {
695 flags |= DRAW_VERTICES_HAS_INDICES;
696 }
bsalomon49f085d2014-09-05 13:34:00 -0700697 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000698 SkXfermode::Mode mode;
699 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
700 flags |= DRAW_VERTICES_HAS_XFER;
701 }
702 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000703
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000704 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000705 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000706 if (flags & DRAW_VERTICES_HAS_TEXS) {
707 size += vertexCount * sizeof(SkPoint); // + uvs
708 }
709 if (flags & DRAW_VERTICES_HAS_COLORS) {
710 size += vertexCount * sizeof(SkColor); // + vert colors
711 }
712 if (flags & DRAW_VERTICES_HAS_INDICES) {
713 // + num indices + indices
714 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
715 }
reed@google.com85e143c2013-12-30 15:51:25 +0000716 if (flags & DRAW_VERTICES_HAS_XFER) {
717 size += kUInt32Size; // mode enum
718 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000719
robertphillips@google.com8b169312013-10-15 17:47:36 +0000720 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000721 this->addPaint(paint);
722 this->addInt(flags);
723 this->addInt(vmode);
724 this->addInt(vertexCount);
725 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000726 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000727 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000728 }
729 if (flags & DRAW_VERTICES_HAS_COLORS) {
730 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
731 }
732 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000733 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000734 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
735 }
reed@google.com85e143c2013-12-30 15:51:25 +0000736 if (flags & DRAW_VERTICES_HAS_XFER) {
737 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
738 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000739 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000740 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000741 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000742}
743
dandovb3c9d1c2014-08-12 08:34:29 -0700744void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
745 const SkPoint texCoords[4], SkXfermode* xmode,
746 const SkPaint& paint) {
747 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
748 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
749 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700750 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700751 flag |= DRAW_VERTICES_HAS_COLORS;
752 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
753 }
bsalomon49f085d2014-09-05 13:34:00 -0700754 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700755 flag |= DRAW_VERTICES_HAS_TEXS;
756 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
757 }
bsalomon49f085d2014-09-05 13:34:00 -0700758 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700759 SkXfermode::Mode mode;
760 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
761 flag |= DRAW_VERTICES_HAS_XFER;
762 size += kUInt32Size;
763 }
764 }
mtklein46616af2014-09-30 14:47:10 -0700765
dandov963137b2014-08-07 07:49:53 -0700766 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
dandov963137b2014-08-07 07:49:53 -0700767 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700768 this->addPatch(cubics);
769 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700770
dandovb3c9d1c2014-08-12 08:34:29 -0700771 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700772 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700773 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
774 }
bsalomon49f085d2014-09-05 13:34:00 -0700775 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700776 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
777 }
778 if (flag & DRAW_VERTICES_HAS_XFER) {
779 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
780 xmode->asMode(&mode);
781 this->addInt(mode);
782 }
dandov963137b2014-08-07 07:49:53 -0700783 this->validate(initialOffset, size);
784}
785
reed71c3c762015-06-24 10:29:17 -0700786void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
787 const SkColor colors[], int count, SkXfermode::Mode mode,
788 const SkRect* cull, const SkPaint* paint) {
789 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
790 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
791 uint32_t flags = 0;
792 if (colors) {
793 flags |= DRAW_ATLAS_HAS_COLORS;
794 size += count * sizeof(SkColor);
795 size += sizeof(uint32_t); // xfermode::mode
796 }
797 if (cull) {
798 flags |= DRAW_ATLAS_HAS_CULL;
799 size += sizeof(SkRect);
800 }
mtkleinc2e29772015-10-30 05:24:58 -0700801
reed71c3c762015-06-24 10:29:17 -0700802 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
reed71c3c762015-06-24 10:29:17 -0700803 this->addPaintPtr(paint);
804 this->addImage(atlas);
805 this->addInt(flags);
806 this->addInt(count);
807 fWriter.write(xform, count * sizeof(SkRSXform));
808 fWriter.write(tex, count * sizeof(SkRect));
809
810 // write optional parameters
811 if (colors) {
812 fWriter.write(colors, count * sizeof(SkColor));
813 this->addInt(mode);
814 }
815 if (cull) {
816 fWriter.write(cull, sizeof(SkRect));
817 }
818 this->validate(initialOffset, size);
819}
820
reedf70b5312016-03-04 16:36:20 -0800821void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
822 size_t keyLen = fWriter.WriteStringSize(key);
823 size_t valueLen = fWriter.WriteDataSize(value);
824 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
825
826 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
827 this->addRect(rect);
828 fWriter.writeString(key);
829 fWriter.writeData(value);
830 this->validate(initialOffset, size);
831}
832
reed@android.com8a1c16f2008-12-17 15:59:43 +0000833///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000834
reede8f30622016-03-23 18:59:25 -0700835sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700836 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000837}
838
mtkleine0694002014-11-12 12:49:47 -0800839// If we already have a stored, can we reuse it instead of also storing b?
840static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
841 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
842 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
843 // but it sure makes things easier to reason about below.
844 return false;
845 }
846 if (a.pixelRef() == b.pixelRef()) {
847 return true; // Same shape and same pixels -> same bitmap.
848 }
849
850 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
851 if (!a.pixelRef() || !b.pixelRef()) {
852 return false;
853 }
854
855 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
856 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
857 encB(b.pixelRef()->refEncodedData());
858 if (encA && encB) {
859 return encA->equals(encB);
860 } else if (encA || encB) {
861 return false; // One has encoded data but the other does not.
862 }
863
864 // As a last resort, we have to look at the pixels. This will read back textures.
865 SkAutoLockPixels al(a), bl(b);
866 const char* ap = (const char*)a.getPixels();
867 const char* bp = (const char*)b.getPixels();
868 if (ap && bp) {
869 // We check row by row; row bytes might differ.
870 SkASSERT(a.info() == b.info()); // We checked this above.
871 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
872 const SkImageInfo info = a.info();
873 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
874 for (int row = 0; row < info.height(); row++) {
875 if (0 != memcmp(ap, bp, bytesToCompare)) {
876 return false;
877 }
878 ap += a.rowBytes();
879 bp += b.rowBytes();
880 }
881 return true;
882 }
883 return false; // Couldn't get pixels for both bitmaps.
884}
885
886void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
887 // First see if we already have this bitmap. This deduplication should really
888 // only be important for our tests, where bitmaps tend not to be tagged immutable.
889 // In Chrome (and hopefully Android?) they're typically immutable.
890 for (int i = 0; i < fBitmaps.count(); i++) {
891 if (equivalent(fBitmaps[i], bitmap)) {
892 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
893 return;
894 }
895 }
896 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800897 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800898 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800899 fBitmaps.push_back(bitmap);
900 } else {
mtkleine0694002014-11-12 12:49:47 -0800901 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800902 SkBitmap copy;
903 bitmap.copyTo(&copy);
904 copy.setImmutable();
905 fBitmaps.push_back(copy);
906 }
mtkleine0694002014-11-12 12:49:47 -0800907 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000908}
909
reed871872f2015-06-22 12:48:26 -0700910void SkPictureRecord::addImage(const SkImage* image) {
911 int index = fImageRefs.find(image);
912 if (index >= 0) {
913 this->addInt(index);
914 } else {
915 *fImageRefs.append() = SkRef(image);
916 this->addInt(fImageRefs.count()-1);
917 }
918}
919
reed@android.com8a1c16f2008-12-17 15:59:43 +0000920void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000921 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000922}
923
mtklein46616af2014-09-30 14:47:10 -0700924void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700925 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000926
mtklein46616af2014-09-30 14:47:10 -0700927 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800928 fPaints.push_back(*paint);
929 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700930 } else {
931 this->addInt(0);
932 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000933}
934
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000935int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700936 if (int* n = fPaths.find(path)) {
937 return *n;
938 }
939 int n = fPaths.count() + 1; // 0 is reserved for null / error.
940 fPaths.set(path, n);
941 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000942}
943
944void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000945 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000946}
947
dandovb3c9d1c2014-08-12 08:34:29 -0700948void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
949 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700950}
951
robertphillips9b14f262014-06-04 05:40:44 -0700952void SkPictureRecord::addPicture(const SkPicture* picture) {
953 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000954 if (index < 0) { // not found
955 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700956 *fPictureRefs.append() = picture;
957 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000958 }
959 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000960 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000961}
962
msarett95416f42016-04-27 13:51:20 -0700963void SkPictureRecord::addDrawable(SkDrawable* drawable) {
964 int index = fDrawableRefs.find(drawable);
965 if (index < 0) { // not found
966 index = fDrawableRefs.count();
967 *fDrawableRefs.append() = drawable;
968 drawable->ref();
969 }
970 // follow the convention of recording a 1-based index
971 this->addInt(index + 1);
972}
973
reed@android.com8a1c16f2008-12-17 15:59:43 +0000974void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000975 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000976}
reed@google.com82065d62011-02-07 15:30:46 +0000977
reed@android.com8a1c16f2008-12-17 15:59:43 +0000978void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
979 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000980}
981
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000982void SkPictureRecord::addNoOp() {
983 size_t size = kUInt32Size; // op
984 this->addDraw(NOOP, &size);
985}
986
reed@android.com8a1c16f2008-12-17 15:59:43 +0000987void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000988 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000989}
990
991void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700992 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000993 fWriter.writeRect(*rect);
994 }
995}
996
reed@google.comf0b5e112011-09-07 11:57:34 +0000997void SkPictureRecord::addIRect(const SkIRect& rect) {
998 fWriter.write(&rect, sizeof(rect));
999}
1000
reed@android.com8a1c16f2008-12-17 15:59:43 +00001001void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -07001002 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001003 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
1004 }
1005}
1006
reed@google.com4ed0fb72012-12-12 20:48:18 +00001007void SkPictureRecord::addRRect(const SkRRect& rrect) {
1008 fWriter.writeRRect(rrect);
1009}
1010
reed@android.com8a1c16f2008-12-17 15:59:43 +00001011void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001012 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001013}
1014
1015void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001016 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001017 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001018 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001019}
1020
fmalitab7425172014-08-26 07:56:44 -07001021void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001022 int index = fTextBlobRefs.count();
1023 *fTextBlobRefs.append() = blob;
1024 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001025 // follow the convention of recording a 1-based index
1026 this->addInt(index + 1);
1027}
1028
reed@android.com8a1c16f2008-12-17 15:59:43 +00001029///////////////////////////////////////////////////////////////////////////////