blob: f2a0fd857c3a4338626ebea35737c61cef2fc849 [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) {
222 this->validate(fWriter.bytesWritten(), 0);
223 // op + scalar
224 size_t size = 1 * kUInt32Size + 1 * sizeof(SkScalar);
225 size_t initialOffset = this->addDraw(TRANSLATE_Z, &size);
226 this->addScalar(z);
227 this->validate(initialOffset, size);
228 this->INHERITED::didTranslateZ(z);
229}
230
reed@google.com45482d12011-08-29 19:02:39 +0000231static bool regionOpExpands(SkRegion::Op op) {
232 switch (op) {
233 case SkRegion::kUnion_Op:
234 case SkRegion::kXOR_Op:
235 case SkRegion::kReverseDifference_Op:
236 case SkRegion::kReplace_Op:
237 return true;
238 case SkRegion::kIntersect_Op:
239 case SkRegion::kDifference_Op:
240 return false;
241 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000242 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000243 return false;
244 }
245}
246
robertphillips@google.come37ad352013-03-01 19:44:30 +0000247void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000248 int32_t offset = fRestoreOffsetStack.top();
249 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000250 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
251 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000252 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000253 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000254
reed@google.comffacd3c2012-08-30 15:31:23 +0000255#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800256 // offset of 0 has been disabled, so we skip it
257 if (offset > 0) {
258 // assert that the final offset value points to a save verb
259 uint32_t opSize;
260 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
reed4960eee2015-12-18 07:09:18 -0800261 SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
reedbfd5f172016-01-07 11:28:08 -0800262 SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
263 SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
reed2ff1fce2014-12-11 07:07:37 -0800264 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000265#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000266}
267
reed@google.comd86e7ab2012-09-27 20:31:31 +0000268void SkPictureRecord::beginRecording() {
269 // we have to call this *after* our constructor, to ensure that it gets
270 // recorded. This is balanced by restoreToCount() call from endRecording,
271 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000272 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000273}
274
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000275void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000276 SkASSERT(kNoInitialSave != fInitialSaveCount);
277 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000278}
279
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000280size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000281 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000282 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000283 }
284
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000285 // The RestoreOffset field is initially filled with a placeholder
286 // value that points to the offset of the previous RestoreOffset
287 // in the current stack level, thus forming a linked list so that
288 // the restore offsets can be filled in when the corresponding
289 // restore command is recorded.
290 int32_t prevOffset = fRestoreOffsetStack.top();
291
reed@google.com45482d12011-08-29 19:02:39 +0000292 if (regionOpExpands(op)) {
293 // Run back through any previous clip ops, and mark their offset to
294 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
295 // they could hide this clips ability to expand the clip (i.e. go from
296 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000297 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000298
299 // Reset the pointer back to the previous clip so that subsequent
300 // restores don't overwrite the offsets we just cleared.
301 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000302 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000303
reed@google.com44699382013-10-31 17:28:30 +0000304 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000305 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000306 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000307 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000308}
309
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000310void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000311 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000312 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000313}
314
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000315size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000316 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000317 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000318 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000319 if (!fRestoreOffsetStack.isEmpty()) {
320 // + restore offset
321 size += kUInt32Size;
322 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000323 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000324 this->addRect(rect);
325 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000326 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000327
robertphillips@google.com8b169312013-10-15 17:47:36 +0000328 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000329 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000330}
331
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000332void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000333 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700334 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000335}
336
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000337size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000338 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000339 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000340 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000341 if (!fRestoreOffsetStack.isEmpty()) {
342 // + restore offset
343 size += kUInt32Size;
344 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000345 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000346 this->addRRect(rrect);
347 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000348 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000349 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000350 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000351}
352
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000353void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000354 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000355 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700356 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000357}
358
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000359size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000360 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000361 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000362 // recordRestoreOffsetPlaceholder doesn't always write an offset
363 if (!fRestoreOffsetStack.isEmpty()) {
364 // + restore offset
365 size += kUInt32Size;
366 }
367 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000368 this->addInt(pathID);
369 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000370 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000371 this->validate(initialOffset, size);
372 return offset;
373}
374
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000375void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000376 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000377 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000378}
379
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000380size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000381 // op + clip params + region
halcanary96fcdcc2015-08-27 07:41:13 -0700382 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000383 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000384 if (!fRestoreOffsetStack.isEmpty()) {
385 // + restore offset
386 size += kUInt32Size;
387 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000388 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000389 this->addRegion(region);
390 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000391 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000392
robertphillips@google.com8b169312013-10-15 17:47:36 +0000393 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000394 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000395}
396
reed41af9662015-01-05 07:49:08 -0800397void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000398 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000399 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000400 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000401 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000402 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000403}
404
reed41af9662015-01-05 07:49:08 -0800405void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
406 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700407 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000408
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000409 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000410 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000411 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000412 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700413
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000414 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000415 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000416 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000417 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418}
419
reed41af9662015-01-05 07:49:08 -0800420void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000421 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000422 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000423 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000424 this->addPaint(paint);
425 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000426 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000427}
428
reed41af9662015-01-05 07:49:08 -0800429void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000430 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000431 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000432 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000433 this->addPaint(paint);
434 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000435 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000436}
437
reed41af9662015-01-05 07:49:08 -0800438void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700439 // op + paint index + rrect
440 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
441 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein46616af2014-09-30 14:47:10 -0700442 this->addPaint(paint);
443 this->addRRect(rrect);
444 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000445}
446
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000447void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
448 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000449 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000450 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
451 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000452 this->addPaint(paint);
453 this->addRRect(outer);
454 this->addRRect(inner);
455 this->validate(initialOffset, size);
456}
457
reed41af9662015-01-05 07:49:08 -0800458void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700459 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000460
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000461 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000462 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000463 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000464 this->addPaint(paint);
465 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000466 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000467}
468
reed41af9662015-01-05 07:49:08 -0800469void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
470 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000471 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000472 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000473 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000474 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000475 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000476 this->addScalar(left);
477 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000478 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000479}
480
reed41af9662015-01-05 07:49:08 -0800481void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700482 const SkPaint* paint, SrcRectConstraint constraint) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000483 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000484 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700485 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000486 size += sizeof(*src); // + rect
487 }
488 size += sizeof(dst); // + rect
489
reeda5517e22015-07-14 10:54:12 -0700490 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000491 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000492 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000493 this->addRectPtr(src); // may be null
494 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700495 this->addInt(constraint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000496 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000497}
498
reeda85d4d02015-05-06 12:56:48 -0700499void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
500 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700501 // op + paint_index + image_index + x + y
502 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
503 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
reed871872f2015-06-22 12:48:26 -0700504 this->addPaintPtr(paint);
505 this->addImage(image);
506 this->addScalar(x);
507 this->addScalar(y);
508 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700509}
510
511void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700512 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700513 // id + paint_index + image_index + bool_for_src + constraint
514 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700515 if (src) {
516 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700517 }
reed871872f2015-06-22 12:48:26 -0700518 size += sizeof(dst); // + rect
mtkleinc2e29772015-10-30 05:24:58 -0700519
reed871872f2015-06-22 12:48:26 -0700520 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
reed871872f2015-06-22 12:48:26 -0700521 this->addPaintPtr(paint);
522 this->addImage(image);
523 this->addRectPtr(src); // may be null
524 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700525 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700526 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700527}
528
reed4c21dc52015-06-25 12:32:03 -0700529void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
530 const SkPaint* paint) {
531 // id + paint_index + image_index + center + dst
532 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
mtkleinc2e29772015-10-30 05:24:58 -0700533
reed4c21dc52015-06-25 12:32:03 -0700534 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
reed4c21dc52015-06-25 12:32:03 -0700535 this->addPaintPtr(paint);
536 this->addImage(img);
537 this->addIRect(center);
538 this->addRect(dst);
539 this->validate(initialOffset, size);
540}
541
reed41af9662015-01-05 07:49:08 -0800542void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
543 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000544 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000545 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000546 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000547 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000548 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000549 this->addIRect(center);
550 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000551 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000552}
553
reed@google.come0d9ce82014-04-23 04:00:17 +0000554void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
555 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000556 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000557 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000558
mtklein46616af2014-09-30 14:47:10 -0700559 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000560 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700561 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000562 this->addText(text, byteLength);
563 this->addScalar(x);
564 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000565 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000566}
567
reed@google.come0d9ce82014-04-23 04:00:17 +0000568void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
569 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000570 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000571
mtklein46616af2014-09-30 14:47:10 -0700572 // op + paint index + length + 'length' worth of data + num points + x&y point data
573 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000574
mtklein46616af2014-09-30 14:47:10 -0700575 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000576
robertphillips@google.com8b169312013-10-15 17:47:36 +0000577 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700578 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000579 this->addText(text, byteLength);
580 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700581 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000582 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000583}
584
reed@google.come0d9ce82014-04-23 04:00:17 +0000585void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
586 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000587 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000588
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000589 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000590 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000591 // + y + the actual points
592 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000593
mtklein46616af2014-09-30 14:47:10 -0700594 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
595 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000596 this->addText(text, byteLength);
597 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000598 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000599 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000600 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000601}
602
reed@google.come0d9ce82014-04-23 04:00:17 +0000603void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
604 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000605 // op + paint index + length + 'length' worth of data + path index + matrix
606 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700607 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000608 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000609 this->addPaint(paint);
610 this->addText(text, byteLength);
611 this->addPath(path);
612 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000613 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000614}
615
reed45561a02016-07-07 12:47:17 -0700616void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
617 const SkRSXform xform[], const SkRect* cull,
618 const SkPaint& paint) {
619 const int count = paint.countText(text, byteLength);
620 // [op + paint-index + count + flags + length] + [text] + [xform] + cull
621 size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
622 uint32_t flags = 0;
623 if (cull) {
624 flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
625 size += sizeof(SkRect);
626 }
627
628 size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
629 this->addPaint(paint);
630 this->addInt(count);
631 this->addInt(flags);
632 this->addText(text, byteLength);
633 fWriter.write(xform, count * sizeof(SkRSXform));
634 if (cull) {
635 fWriter.write(cull, sizeof(SkRect));
636 }
637 this->validate(initialOffset, size);
638}
639
fmalitab7425172014-08-26 07:56:44 -0700640void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
641 const SkPaint& paint) {
642
643 // op + paint index + blob index + x/y
644 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
645 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
fmalitab7425172014-08-26 07:56:44 -0700646
647 this->addPaint(paint);
648 this->addTextBlob(blob);
649 this->addScalar(x);
650 this->addScalar(y);
651
652 this->validate(initialOffset, size);
653}
654
reedd5fa1a42014-08-09 11:08:05 -0700655void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
656 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000657 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000658 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700659 size_t initialOffset;
660
halcanary96fcdcc2015-08-27 07:41:13 -0700661 if (nullptr == matrix && nullptr == paint) {
reedd5fa1a42014-08-09 11:08:05 -0700662 initialOffset = this->addDraw(DRAW_PICTURE, &size);
663 this->addPicture(picture);
664 } else {
665 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700666 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
reedd5fa1a42014-08-09 11:08:05 -0700667 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
reedd5fa1a42014-08-09 11:08:05 -0700668 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700669 this->addMatrix(m);
670 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700671 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000672 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000673}
674
msarett95416f42016-04-27 13:51:20 -0700675void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
676 // op + drawable index
677 size_t size = 2 * kUInt32Size;
678 size_t initialOffset;
679
680 if (nullptr == matrix) {
681 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
682 this->addDrawable(drawable);
683 } else {
684 size += matrix->writeToMemory(nullptr); // matrix
685 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
686 this->addMatrix(*matrix);
687 this->addDrawable(drawable);
688 }
689 this->validate(initialOffset, size);
690}
691
reed41af9662015-01-05 07:49:08 -0800692void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
693 const SkPoint vertices[], const SkPoint texs[],
694 const SkColor colors[], SkXfermode* xfer,
695 const uint16_t indices[], int indexCount,
696 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000697 uint32_t flags = 0;
698 if (texs) {
699 flags |= DRAW_VERTICES_HAS_TEXS;
700 }
701 if (colors) {
702 flags |= DRAW_VERTICES_HAS_COLORS;
703 }
704 if (indexCount > 0) {
705 flags |= DRAW_VERTICES_HAS_INDICES;
706 }
bsalomon49f085d2014-09-05 13:34:00 -0700707 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000708 SkXfermode::Mode mode;
709 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
710 flags |= DRAW_VERTICES_HAS_XFER;
711 }
712 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000713
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000714 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000715 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000716 if (flags & DRAW_VERTICES_HAS_TEXS) {
717 size += vertexCount * sizeof(SkPoint); // + uvs
718 }
719 if (flags & DRAW_VERTICES_HAS_COLORS) {
720 size += vertexCount * sizeof(SkColor); // + vert colors
721 }
722 if (flags & DRAW_VERTICES_HAS_INDICES) {
723 // + num indices + indices
724 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
725 }
reed@google.com85e143c2013-12-30 15:51:25 +0000726 if (flags & DRAW_VERTICES_HAS_XFER) {
727 size += kUInt32Size; // mode enum
728 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000729
robertphillips@google.com8b169312013-10-15 17:47:36 +0000730 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000731 this->addPaint(paint);
732 this->addInt(flags);
733 this->addInt(vmode);
734 this->addInt(vertexCount);
735 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000736 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000737 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000738 }
739 if (flags & DRAW_VERTICES_HAS_COLORS) {
740 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
741 }
742 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000743 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000744 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
745 }
reed@google.com85e143c2013-12-30 15:51:25 +0000746 if (flags & DRAW_VERTICES_HAS_XFER) {
747 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
748 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000749 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000750 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000751 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000752}
753
dandovb3c9d1c2014-08-12 08:34:29 -0700754void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
755 const SkPoint texCoords[4], SkXfermode* xmode,
756 const SkPaint& paint) {
757 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
758 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
759 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700760 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700761 flag |= DRAW_VERTICES_HAS_COLORS;
762 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
763 }
bsalomon49f085d2014-09-05 13:34:00 -0700764 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700765 flag |= DRAW_VERTICES_HAS_TEXS;
766 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
767 }
bsalomon49f085d2014-09-05 13:34:00 -0700768 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700769 SkXfermode::Mode mode;
770 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
771 flag |= DRAW_VERTICES_HAS_XFER;
772 size += kUInt32Size;
773 }
774 }
mtklein46616af2014-09-30 14:47:10 -0700775
dandov963137b2014-08-07 07:49:53 -0700776 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
dandov963137b2014-08-07 07:49:53 -0700777 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700778 this->addPatch(cubics);
779 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700780
dandovb3c9d1c2014-08-12 08:34:29 -0700781 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700782 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700783 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
784 }
bsalomon49f085d2014-09-05 13:34:00 -0700785 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700786 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
787 }
788 if (flag & DRAW_VERTICES_HAS_XFER) {
789 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
790 xmode->asMode(&mode);
791 this->addInt(mode);
792 }
dandov963137b2014-08-07 07:49:53 -0700793 this->validate(initialOffset, size);
794}
795
reed71c3c762015-06-24 10:29:17 -0700796void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
797 const SkColor colors[], int count, SkXfermode::Mode mode,
798 const SkRect* cull, const SkPaint* paint) {
799 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
800 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
801 uint32_t flags = 0;
802 if (colors) {
803 flags |= DRAW_ATLAS_HAS_COLORS;
804 size += count * sizeof(SkColor);
805 size += sizeof(uint32_t); // xfermode::mode
806 }
807 if (cull) {
808 flags |= DRAW_ATLAS_HAS_CULL;
809 size += sizeof(SkRect);
810 }
mtkleinc2e29772015-10-30 05:24:58 -0700811
reed71c3c762015-06-24 10:29:17 -0700812 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
reed71c3c762015-06-24 10:29:17 -0700813 this->addPaintPtr(paint);
814 this->addImage(atlas);
815 this->addInt(flags);
816 this->addInt(count);
817 fWriter.write(xform, count * sizeof(SkRSXform));
818 fWriter.write(tex, count * sizeof(SkRect));
819
820 // write optional parameters
821 if (colors) {
822 fWriter.write(colors, count * sizeof(SkColor));
823 this->addInt(mode);
824 }
825 if (cull) {
826 fWriter.write(cull, sizeof(SkRect));
827 }
828 this->validate(initialOffset, size);
829}
830
reedf70b5312016-03-04 16:36:20 -0800831void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
832 size_t keyLen = fWriter.WriteStringSize(key);
833 size_t valueLen = fWriter.WriteDataSize(value);
834 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
835
836 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
837 this->addRect(rect);
838 fWriter.writeString(key);
839 fWriter.writeData(value);
840 this->validate(initialOffset, size);
841}
842
reed@android.com8a1c16f2008-12-17 15:59:43 +0000843///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000844
reede8f30622016-03-23 18:59:25 -0700845sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700846 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000847}
848
mtkleine0694002014-11-12 12:49:47 -0800849// If we already have a stored, can we reuse it instead of also storing b?
850static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
851 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
852 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
853 // but it sure makes things easier to reason about below.
854 return false;
855 }
856 if (a.pixelRef() == b.pixelRef()) {
857 return true; // Same shape and same pixels -> same bitmap.
858 }
859
860 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
861 if (!a.pixelRef() || !b.pixelRef()) {
862 return false;
863 }
864
865 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
866 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
867 encB(b.pixelRef()->refEncodedData());
868 if (encA && encB) {
869 return encA->equals(encB);
870 } else if (encA || encB) {
871 return false; // One has encoded data but the other does not.
872 }
873
874 // As a last resort, we have to look at the pixels. This will read back textures.
875 SkAutoLockPixels al(a), bl(b);
876 const char* ap = (const char*)a.getPixels();
877 const char* bp = (const char*)b.getPixels();
878 if (ap && bp) {
879 // We check row by row; row bytes might differ.
880 SkASSERT(a.info() == b.info()); // We checked this above.
881 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
882 const SkImageInfo info = a.info();
883 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
884 for (int row = 0; row < info.height(); row++) {
885 if (0 != memcmp(ap, bp, bytesToCompare)) {
886 return false;
887 }
888 ap += a.rowBytes();
889 bp += b.rowBytes();
890 }
891 return true;
892 }
893 return false; // Couldn't get pixels for both bitmaps.
894}
895
896void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
897 // First see if we already have this bitmap. This deduplication should really
898 // only be important for our tests, where bitmaps tend not to be tagged immutable.
899 // In Chrome (and hopefully Android?) they're typically immutable.
900 for (int i = 0; i < fBitmaps.count(); i++) {
901 if (equivalent(fBitmaps[i], bitmap)) {
902 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
903 return;
904 }
905 }
906 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800907 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800908 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800909 fBitmaps.push_back(bitmap);
910 } else {
mtkleine0694002014-11-12 12:49:47 -0800911 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800912 SkBitmap copy;
913 bitmap.copyTo(&copy);
914 copy.setImmutable();
915 fBitmaps.push_back(copy);
916 }
mtkleine0694002014-11-12 12:49:47 -0800917 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000918}
919
reed871872f2015-06-22 12:48:26 -0700920void SkPictureRecord::addImage(const SkImage* image) {
921 int index = fImageRefs.find(image);
922 if (index >= 0) {
923 this->addInt(index);
924 } else {
925 *fImageRefs.append() = SkRef(image);
926 this->addInt(fImageRefs.count()-1);
927 }
928}
929
reed@android.com8a1c16f2008-12-17 15:59:43 +0000930void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000931 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000932}
933
mtklein46616af2014-09-30 14:47:10 -0700934void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700935 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000936
mtklein46616af2014-09-30 14:47:10 -0700937 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800938 fPaints.push_back(*paint);
939 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700940 } else {
941 this->addInt(0);
942 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000943}
944
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000945int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700946 if (int* n = fPaths.find(path)) {
947 return *n;
948 }
949 int n = fPaths.count() + 1; // 0 is reserved for null / error.
950 fPaths.set(path, n);
951 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000952}
953
954void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000955 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000956}
957
dandovb3c9d1c2014-08-12 08:34:29 -0700958void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
959 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700960}
961
robertphillips9b14f262014-06-04 05:40:44 -0700962void SkPictureRecord::addPicture(const SkPicture* picture) {
963 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000964 if (index < 0) { // not found
965 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700966 *fPictureRefs.append() = picture;
967 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000968 }
969 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000970 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000971}
972
msarett95416f42016-04-27 13:51:20 -0700973void SkPictureRecord::addDrawable(SkDrawable* drawable) {
974 int index = fDrawableRefs.find(drawable);
975 if (index < 0) { // not found
976 index = fDrawableRefs.count();
977 *fDrawableRefs.append() = drawable;
978 drawable->ref();
979 }
980 // follow the convention of recording a 1-based index
981 this->addInt(index + 1);
982}
983
reed@android.com8a1c16f2008-12-17 15:59:43 +0000984void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000985 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000986}
reed@google.com82065d62011-02-07 15:30:46 +0000987
reed@android.com8a1c16f2008-12-17 15:59:43 +0000988void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
989 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000990}
991
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000992void SkPictureRecord::addNoOp() {
993 size_t size = kUInt32Size; // op
994 this->addDraw(NOOP, &size);
995}
996
reed@android.com8a1c16f2008-12-17 15:59:43 +0000997void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000998 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000999}
1000
1001void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -07001002 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001003 fWriter.writeRect(*rect);
1004 }
1005}
1006
reed@google.comf0b5e112011-09-07 11:57:34 +00001007void SkPictureRecord::addIRect(const SkIRect& rect) {
1008 fWriter.write(&rect, sizeof(rect));
1009}
1010
reed@android.com8a1c16f2008-12-17 15:59:43 +00001011void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -07001012 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001013 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
1014 }
1015}
1016
reed@google.com4ed0fb72012-12-12 20:48:18 +00001017void SkPictureRecord::addRRect(const SkRRect& rrect) {
1018 fWriter.writeRRect(rrect);
1019}
1020
reed@android.com8a1c16f2008-12-17 15:59:43 +00001021void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001022 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001023}
1024
1025void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001026 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001027 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001028 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001029}
1030
fmalitab7425172014-08-26 07:56:44 -07001031void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001032 int index = fTextBlobRefs.count();
1033 *fTextBlobRefs.append() = blob;
1034 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001035 // follow the convention of recording a 1-based index
1036 this->addInt(index + 1);
1037}
1038
reed@android.com8a1c16f2008-12-17 15:59:43 +00001039///////////////////////////////////////////////////////////////////////////////