blob: 8eab63016b82998365c8a12ea3ef376046bad1b4 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
reed@google.com76f10a32014-02-05 15:32:21 +00007
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkPictureRecord.h"
reeda85d4d02015-05-06 12:56:48 -07009#include "SkImage_Base.h"
dandovb3c9d1c2014-08-12 08:34:29 -070010#include "SkPatchUtils.h"
dandovb3c9d1c2014-08-12 08:34:29 -070011#include "SkPixelRef.h"
12#include "SkRRect.h"
reed71c3c762015-06-24 10:29:17 -070013#include "SkRSXform.h"
fmalitab7425172014-08-26 07:56:44 -070014#include "SkTextBlob.h"
dandovb3c9d1c2014-08-12 08:34:29 -070015#include "SkTSearch.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000016
reed@android.com8a1c16f2008-12-17 15:59:43 +000017#define HEAP_BLOCK_SIZE 4096
18
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000019enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000020 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000021 kNoInitialSave = -1,
22};
23
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000024// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
25static int const kUInt32Size = 4;
26
robertphillips0bdbea72014-06-11 11:37:55 -070027SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000028 : INHERITED(dimensions.width(), dimensions.height())
mtklein71a23632014-11-12 10:24:55 -080029 , fRecordFlags(flags)
30 , fInitialSaveCount(kNoInitialSave) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000031}
32
33SkPictureRecord::~SkPictureRecord() {
robertphillips5351aad2015-06-23 06:54:56 -070034 fImageRefs.unrefAll();
djsollen@google.com21830d92012-08-07 19:49:41 +000035 fPictureRefs.unrefAll();
msarett95416f42016-04-27 13:51:20 -070036 fDrawableRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070037 fTextBlobRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000038}
39
40///////////////////////////////////////////////////////////////////////////////
41
Florin Malita5f6102d2014-06-30 10:13:28 -040042void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +000043 // record the offset to us, making it non-positive to distinguish a save
44 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +000045 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -040046 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000047
Florin Malita5f6102d2014-06-30 10:13:28 -040048 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +000049}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +000050
Florin Malita5f6102d2014-06-30 10:13:28 -040051void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -070052 fContentInfo.onSave();
53
Florin Malita5f6102d2014-06-30 10:13:28 -040054 // op only
reed512f3e32016-01-04 14:11:31 -080055 size_t size = sizeof(kUInt32Size);
robertphillips@google.com8b169312013-10-15 17:47:36 +000056 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +000057
robertphillips@google.com8b169312013-10-15 17:47:36 +000058 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +000059}
60
reed4960eee2015-12-18 07:09:18 -080061SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
reed@google.comffacd3c2012-08-30 15:31:23 +000062 // record the offset to us, making it non-positive to distinguish a save
63 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +000064 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
reed4960eee2015-12-18 07:09:18 -080065 this->recordSaveLayer(rec);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +000066
reed4960eee2015-12-18 07:09:18 -080067 (void)this->INHERITED::getSaveLayerStrategy(rec);
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000068 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +000069 at this time (and may not be able to afford since during record our
70 clip starts out the size of the picture, which is often much larger
71 than the size of the actual device we'll use during playback).
72 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000073 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +000074}
75
reed4960eee2015-12-18 07:09:18 -080076void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
robertphillipsc019ec42014-08-12 05:35:58 -070077 fContentInfo.onSaveLayer();
78
reedbfd5f172016-01-07 11:28:08 -080079 // op + flatflags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +000080 size_t size = 2 * kUInt32Size;
reedbfd5f172016-01-07 11:28:08 -080081 uint32_t flatFlags = 0;
82
reed4960eee2015-12-18 07:09:18 -080083 if (rec.fBounds) {
reedbfd5f172016-01-07 11:28:08 -080084 flatFlags |= SAVELAYERREC_HAS_BOUNDS;
85 size += sizeof(*rec.fBounds);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000086 }
reedbfd5f172016-01-07 11:28:08 -080087 if (rec.fPaint) {
88 flatFlags |= SAVELAYERREC_HAS_PAINT;
89 size += sizeof(uint32_t); // index
90 }
91 if (rec.fBackdrop) {
92 flatFlags |= SAVELAYERREC_HAS_BACKDROP;
93 size += sizeof(uint32_t); // (paint) index
94 }
95 if (rec.fSaveLayerFlags) {
96 flatFlags |= SAVELAYERREC_HAS_FLAGS;
97 size += sizeof(uint32_t);
98 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000099
reedbfd5f172016-01-07 11:28:08 -0800100 const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
101 this->addInt(flatFlags);
102 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
103 this->addRect(*rec.fBounds);
104 }
105 if (flatFlags & SAVELAYERREC_HAS_PAINT) {
106 this->addPaintPtr(rec.fPaint);
107 }
108 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
109 // overkill, but we didn't already track single flattenables, so using a paint for that
110 SkPaint paint;
111 paint.setImageFilter(const_cast<SkImageFilter*>(rec.fBackdrop));
112 this->addPaint(paint);
113 }
114 if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
115 this->addInt(rec.fSaveLayerFlags);
116 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000117 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000118}
119
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000120#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000121/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000122 * Read the op code from 'offset' in 'writer' and extract the size too.
123 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000124static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000125 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000126
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000127 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000128 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000129 if (MASK_24 == *size) {
130 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000131 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000132 }
133 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000134}
mtklein46616af2014-09-30 14:47:10 -0700135#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000136
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000137void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000138#if 0
139 SkASSERT(fRestoreOffsetStack.count() > 1);
140#endif
141
reed@android.comb4e22d62009-07-09 15:20:25 +0000142 // check for underflow
143 if (fRestoreOffsetStack.count() == 0) {
144 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000146
mtklein46616af2014-09-30 14:47:10 -0700147 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000148
reed@android.comb4e22d62009-07-09 15:20:25 +0000149 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000150
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000151 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152}
153
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000154void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700155 fContentInfo.onRestore();
156
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000157 if (fillInSkips) {
158 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
159 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000160 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
161 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000162 this->validate(initialOffset, size);
163}
164
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000165void SkPictureRecord::recordTranslate(const SkMatrix& m) {
166 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
167
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000168 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000169 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000170 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000171 this->addScalar(m.getTranslateX());
172 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000173 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174}
175
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000176void SkPictureRecord::recordScale(const SkMatrix& m) {
177 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000178
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000179 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000180 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000181 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000182 this->addScalar(m.getScaleX());
183 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000184 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185}
186
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000187void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000188 switch (matrix.getType()) {
189 case SkMatrix::kTranslate_Mask:
190 this->recordTranslate(matrix);
191 break;
192 case SkMatrix::kScale_Mask:
193 this->recordScale(matrix);
194 break;
195 default:
196 this->recordConcat(matrix);
197 break;
198 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000199 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000200}
201
202void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000203 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000204 // op + matrix
halcanary96fcdcc2015-08-27 07:41:13 -0700205 size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000206 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000207 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000208 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209}
210
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000211void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000212 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000213 // op + matrix
halcanary96fcdcc2015-08-27 07:41:13 -0700214 size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000215 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000216 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000217 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000218 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000219}
220
vjiaoblacke5de1302016-07-13 14:05:28 -0700221void SkPictureRecord::didTranslateZ(SkScalar z) {
vjiaoblack95302da2016-07-21 10:25:54 -0700222#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke5de1302016-07-13 14:05:28 -0700223 this->validate(fWriter.bytesWritten(), 0);
224 // op + scalar
225 size_t size = 1 * kUInt32Size + 1 * sizeof(SkScalar);
226 size_t initialOffset = this->addDraw(TRANSLATE_Z, &size);
227 this->addScalar(z);
228 this->validate(initialOffset, size);
229 this->INHERITED::didTranslateZ(z);
vjiaoblack95302da2016-07-21 10:25:54 -0700230#endif
vjiaoblacke5de1302016-07-13 14:05:28 -0700231}
232
reed@google.com45482d12011-08-29 19:02:39 +0000233static bool regionOpExpands(SkRegion::Op op) {
234 switch (op) {
235 case SkRegion::kUnion_Op:
236 case SkRegion::kXOR_Op:
237 case SkRegion::kReverseDifference_Op:
238 case SkRegion::kReplace_Op:
239 return true;
240 case SkRegion::kIntersect_Op:
241 case SkRegion::kDifference_Op:
242 return false;
243 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000244 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000245 return false;
246 }
247}
248
robertphillips@google.come37ad352013-03-01 19:44:30 +0000249void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000250 int32_t offset = fRestoreOffsetStack.top();
251 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000252 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
253 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000254 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000255 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000256
reed@google.comffacd3c2012-08-30 15:31:23 +0000257#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800258 // offset of 0 has been disabled, so we skip it
259 if (offset > 0) {
260 // assert that the final offset value points to a save verb
261 uint32_t opSize;
262 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
reed4960eee2015-12-18 07:09:18 -0800263 SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
reedbfd5f172016-01-07 11:28:08 -0800264 SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
265 SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
reed2ff1fce2014-12-11 07:07:37 -0800266 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000267#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000268}
269
reed@google.comd86e7ab2012-09-27 20:31:31 +0000270void SkPictureRecord::beginRecording() {
271 // we have to call this *after* our constructor, to ensure that it gets
272 // recorded. This is balanced by restoreToCount() call from endRecording,
273 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000274 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000275}
276
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000277void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000278 SkASSERT(kNoInitialSave != fInitialSaveCount);
279 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000280}
281
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000282size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000283 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000284 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000285 }
286
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000287 // The RestoreOffset field is initially filled with a placeholder
288 // value that points to the offset of the previous RestoreOffset
289 // in the current stack level, thus forming a linked list so that
290 // the restore offsets can be filled in when the corresponding
291 // restore command is recorded.
292 int32_t prevOffset = fRestoreOffsetStack.top();
293
reed@google.com45482d12011-08-29 19:02:39 +0000294 if (regionOpExpands(op)) {
295 // Run back through any previous clip ops, and mark their offset to
296 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
297 // they could hide this clips ability to expand the clip (i.e. go from
298 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000299 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000300
301 // Reset the pointer back to the previous clip so that subsequent
302 // restores don't overwrite the offsets we just cleared.
303 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000304 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000305
reed@google.com44699382013-10-31 17:28:30 +0000306 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000307 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000308 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000309 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000310}
311
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000312void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000313 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000314 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000315}
316
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000317size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000318 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000319 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000320 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000321 if (!fRestoreOffsetStack.isEmpty()) {
322 // + restore offset
323 size += kUInt32Size;
324 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000325 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000326 this->addRect(rect);
327 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000328 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000329
robertphillips@google.com8b169312013-10-15 17:47:36 +0000330 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000331 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000332}
333
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000334void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000335 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700336 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000337}
338
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000339size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000340 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000341 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000342 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000343 if (!fRestoreOffsetStack.isEmpty()) {
344 // + restore offset
345 size += kUInt32Size;
346 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000347 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000348 this->addRRect(rrect);
349 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000350 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000351 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000352 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000353}
354
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000355void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000356 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000357 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700358 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000359}
360
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000361size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000362 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000363 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000364 // recordRestoreOffsetPlaceholder doesn't always write an offset
365 if (!fRestoreOffsetStack.isEmpty()) {
366 // + restore offset
367 size += kUInt32Size;
368 }
369 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000370 this->addInt(pathID);
371 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000372 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000373 this->validate(initialOffset, size);
374 return offset;
375}
376
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000377void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000378 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000379 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000380}
381
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000382size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000383 // op + clip params + region
halcanary96fcdcc2015-08-27 07:41:13 -0700384 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000385 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000386 if (!fRestoreOffsetStack.isEmpty()) {
387 // + restore offset
388 size += kUInt32Size;
389 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000390 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000391 this->addRegion(region);
392 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000393 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000394
robertphillips@google.com8b169312013-10-15 17:47:36 +0000395 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000396 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000397}
398
reed41af9662015-01-05 07:49:08 -0800399void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000400 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000401 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000402 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000403 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000404 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000405}
406
reed41af9662015-01-05 07:49:08 -0800407void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
408 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700409 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000410
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000411 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000412 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000413 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000414 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700415
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000416 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000417 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000419 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000420}
421
reed41af9662015-01-05 07:49:08 -0800422void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000423 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000424 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000425 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000426 this->addPaint(paint);
427 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000428 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000429}
430
bsalomonac3aa242016-08-19 11:25:19 -0700431void SkPictureRecord::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
432 bool useCenter, const SkPaint& paint) {
433 // op + paint index + rect + start + sweep + bool (as int)
434 size_t size = 2 * kUInt32Size + sizeof(oval) + sizeof(startAngle) + sizeof(sweepAngle) +
435 sizeof(int);
436 size_t initialOffset = this->addDraw(DRAW_ARC, &size);
437 this->addPaint(paint);
438 this->addRect(oval);
439 this->addScalar(startAngle);
440 this->addScalar(sweepAngle);
441 this->addInt(useCenter);
442 this->validate(initialOffset, size);
443}
444
reed41af9662015-01-05 07:49:08 -0800445void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000446 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000447 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000448 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000449 this->addPaint(paint);
450 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000451 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000452}
453
msarett44df6512016-08-25 13:54:30 -0700454void SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
455 // op + paint index + region
456 size_t regionBytes = region.writeToMemory(nullptr);
457 size_t size = 2 * kUInt32Size + regionBytes;
458 size_t initialOffset = this->addDraw(DRAW_REGION, &size);
459 this->addPaint(paint);
460 fWriter.writeRegion(region);
461 this->validate(initialOffset, size);
462}
463
reed41af9662015-01-05 07:49:08 -0800464void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700465 // op + paint index + rrect
466 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
467 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein46616af2014-09-30 14:47:10 -0700468 this->addPaint(paint);
469 this->addRRect(rrect);
470 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000471}
472
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000473void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
474 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000475 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000476 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
477 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000478 this->addPaint(paint);
479 this->addRRect(outer);
480 this->addRRect(inner);
481 this->validate(initialOffset, size);
482}
483
reed41af9662015-01-05 07:49:08 -0800484void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700485 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000486
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000487 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000488 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000489 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000490 this->addPaint(paint);
491 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000492 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000493}
494
reeda85d4d02015-05-06 12:56:48 -0700495void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
496 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700497 // op + paint_index + image_index + x + y
498 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
499 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
reed871872f2015-06-22 12:48:26 -0700500 this->addPaintPtr(paint);
501 this->addImage(image);
502 this->addScalar(x);
503 this->addScalar(y);
504 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700505}
506
507void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700508 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700509 // id + paint_index + image_index + bool_for_src + constraint
510 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700511 if (src) {
512 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700513 }
reed871872f2015-06-22 12:48:26 -0700514 size += sizeof(dst); // + rect
mtkleinc2e29772015-10-30 05:24:58 -0700515
reed871872f2015-06-22 12:48:26 -0700516 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
reed871872f2015-06-22 12:48:26 -0700517 this->addPaintPtr(paint);
518 this->addImage(image);
519 this->addRectPtr(src); // may be null
520 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700521 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700522 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700523}
524
reed4c21dc52015-06-25 12:32:03 -0700525void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
526 const SkPaint* paint) {
527 // id + paint_index + image_index + center + dst
528 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
mtkleinc2e29772015-10-30 05:24:58 -0700529
reed4c21dc52015-06-25 12:32:03 -0700530 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
reed4c21dc52015-06-25 12:32:03 -0700531 this->addPaintPtr(paint);
532 this->addImage(img);
533 this->addIRect(center);
534 this->addRect(dst);
535 this->validate(initialOffset, size);
536}
537
msarett16882062016-08-16 09:31:08 -0700538void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
539 const SkRect& dst, const SkPaint* paint) {
540 // xCount + xDivs + yCount+ yDivs
541 size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount) * kUInt32Size;
542
543 // op + paint index + image index + lattice + dst rect
544 size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
545 size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
546 this->addPaintPtr(paint);
547 this->addImage(image);
548 this->addInt(lattice.fXCount);
549 fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
550 this->addInt(lattice.fYCount);
551 fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
552 this->addRect(dst);
553 this->validate(initialOffset, size);
554}
555
reed@google.come0d9ce82014-04-23 04:00:17 +0000556void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
557 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000558 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000559 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000560
mtklein46616af2014-09-30 14:47:10 -0700561 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000562 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700563 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000564 this->addText(text, byteLength);
565 this->addScalar(x);
566 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000567 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000568}
569
reed@google.come0d9ce82014-04-23 04:00:17 +0000570void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
571 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000572 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000573
mtklein46616af2014-09-30 14:47:10 -0700574 // op + paint index + length + 'length' worth of data + num points + x&y point data
575 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000576
mtklein46616af2014-09-30 14:47:10 -0700577 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000578
robertphillips@google.com8b169312013-10-15 17:47:36 +0000579 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700580 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000581 this->addText(text, byteLength);
582 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700583 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000584 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000585}
586
reed@google.come0d9ce82014-04-23 04:00:17 +0000587void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
588 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000589 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000591 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000592 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000593 // + y + the actual points
594 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000595
mtklein46616af2014-09-30 14:47:10 -0700596 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
597 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000598 this->addText(text, byteLength);
599 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000600 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000601 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000602 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000603}
604
reed@google.come0d9ce82014-04-23 04:00:17 +0000605void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
606 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000607 // op + paint index + length + 'length' worth of data + path index + matrix
608 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700609 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000610 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000611 this->addPaint(paint);
612 this->addText(text, byteLength);
613 this->addPath(path);
614 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000615 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616}
617
reed45561a02016-07-07 12:47:17 -0700618void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
619 const SkRSXform xform[], const SkRect* cull,
620 const SkPaint& paint) {
621 const int count = paint.countText(text, byteLength);
622 // [op + paint-index + count + flags + length] + [text] + [xform] + cull
623 size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
624 uint32_t flags = 0;
625 if (cull) {
626 flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
627 size += sizeof(SkRect);
628 }
629
630 size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
631 this->addPaint(paint);
632 this->addInt(count);
633 this->addInt(flags);
634 this->addText(text, byteLength);
635 fWriter.write(xform, count * sizeof(SkRSXform));
636 if (cull) {
637 fWriter.write(cull, sizeof(SkRect));
638 }
639 this->validate(initialOffset, size);
640}
641
fmalitab7425172014-08-26 07:56:44 -0700642void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
643 const SkPaint& paint) {
644
645 // op + paint index + blob index + x/y
646 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
647 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
fmalitab7425172014-08-26 07:56:44 -0700648
649 this->addPaint(paint);
650 this->addTextBlob(blob);
651 this->addScalar(x);
652 this->addScalar(y);
653
654 this->validate(initialOffset, size);
655}
656
reedd5fa1a42014-08-09 11:08:05 -0700657void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
658 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000659 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000660 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700661 size_t initialOffset;
662
halcanary96fcdcc2015-08-27 07:41:13 -0700663 if (nullptr == matrix && nullptr == paint) {
reedd5fa1a42014-08-09 11:08:05 -0700664 initialOffset = this->addDraw(DRAW_PICTURE, &size);
665 this->addPicture(picture);
666 } else {
667 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700668 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
reedd5fa1a42014-08-09 11:08:05 -0700669 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
reedd5fa1a42014-08-09 11:08:05 -0700670 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700671 this->addMatrix(m);
672 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700673 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000674 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000675}
676
vjiaoblack95302da2016-07-21 10:25:54 -0700677void SkPictureRecord::onDrawShadowedPicture(const SkPicture* picture,
678 const SkMatrix* matrix,
vjiaoblacke6f5d562016-08-25 06:30:23 -0700679 const SkPaint* paint,
680 const SkShadowParams& params) {
vjiaoblack95302da2016-07-21 10:25:54 -0700681 // op + picture index
682 size_t size = 2 * kUInt32Size;
683 size_t initialOffset;
684
vjiaoblacke6f5d562016-08-25 06:30:23 -0700685 // TODO: handle recording params.
vjiaoblack95302da2016-07-21 10:25:54 -0700686 if (nullptr == matrix && nullptr == paint) {
687 initialOffset = this->addDraw(DRAW_PICTURE, &size);
688 this->addPicture(picture);
689 } else {
690 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
691 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
692 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
693 this->addPaintPtr(paint);
694 this->addMatrix(m);
695 this->addPicture(picture);
696 }
697 this->validate(initialOffset, size);
698}
699
msarett95416f42016-04-27 13:51:20 -0700700void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
701 // op + drawable index
702 size_t size = 2 * kUInt32Size;
703 size_t initialOffset;
704
705 if (nullptr == matrix) {
706 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
707 this->addDrawable(drawable);
708 } else {
709 size += matrix->writeToMemory(nullptr); // matrix
710 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
711 this->addMatrix(*matrix);
712 this->addDrawable(drawable);
713 }
714 this->validate(initialOffset, size);
715}
716
reed41af9662015-01-05 07:49:08 -0800717void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
718 const SkPoint vertices[], const SkPoint texs[],
719 const SkColor colors[], SkXfermode* xfer,
720 const uint16_t indices[], int indexCount,
721 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000722 uint32_t flags = 0;
723 if (texs) {
724 flags |= DRAW_VERTICES_HAS_TEXS;
725 }
726 if (colors) {
727 flags |= DRAW_VERTICES_HAS_COLORS;
728 }
729 if (indexCount > 0) {
730 flags |= DRAW_VERTICES_HAS_INDICES;
731 }
bsalomon49f085d2014-09-05 13:34:00 -0700732 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000733 SkXfermode::Mode mode;
734 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
735 flags |= DRAW_VERTICES_HAS_XFER;
736 }
737 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000738
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000739 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000740 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000741 if (flags & DRAW_VERTICES_HAS_TEXS) {
742 size += vertexCount * sizeof(SkPoint); // + uvs
743 }
744 if (flags & DRAW_VERTICES_HAS_COLORS) {
745 size += vertexCount * sizeof(SkColor); // + vert colors
746 }
747 if (flags & DRAW_VERTICES_HAS_INDICES) {
748 // + num indices + indices
749 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
750 }
reed@google.com85e143c2013-12-30 15:51:25 +0000751 if (flags & DRAW_VERTICES_HAS_XFER) {
752 size += kUInt32Size; // mode enum
753 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000754
robertphillips@google.com8b169312013-10-15 17:47:36 +0000755 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000756 this->addPaint(paint);
757 this->addInt(flags);
758 this->addInt(vmode);
759 this->addInt(vertexCount);
760 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000761 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000762 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000763 }
764 if (flags & DRAW_VERTICES_HAS_COLORS) {
765 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
766 }
767 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000768 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000769 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
770 }
reed@google.com85e143c2013-12-30 15:51:25 +0000771 if (flags & DRAW_VERTICES_HAS_XFER) {
772 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
773 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000774 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000775 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000776 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000777}
778
dandovb3c9d1c2014-08-12 08:34:29 -0700779void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
780 const SkPoint texCoords[4], SkXfermode* xmode,
781 const SkPaint& paint) {
782 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
783 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
784 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700785 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700786 flag |= DRAW_VERTICES_HAS_COLORS;
787 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
788 }
bsalomon49f085d2014-09-05 13:34:00 -0700789 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700790 flag |= DRAW_VERTICES_HAS_TEXS;
791 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
792 }
bsalomon49f085d2014-09-05 13:34:00 -0700793 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700794 SkXfermode::Mode mode;
795 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
796 flag |= DRAW_VERTICES_HAS_XFER;
797 size += kUInt32Size;
798 }
799 }
mtklein46616af2014-09-30 14:47:10 -0700800
dandov963137b2014-08-07 07:49:53 -0700801 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
dandov963137b2014-08-07 07:49:53 -0700802 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700803 this->addPatch(cubics);
804 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700805
dandovb3c9d1c2014-08-12 08:34:29 -0700806 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700807 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700808 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
809 }
bsalomon49f085d2014-09-05 13:34:00 -0700810 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700811 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
812 }
813 if (flag & DRAW_VERTICES_HAS_XFER) {
814 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
815 xmode->asMode(&mode);
816 this->addInt(mode);
817 }
dandov963137b2014-08-07 07:49:53 -0700818 this->validate(initialOffset, size);
819}
820
reed71c3c762015-06-24 10:29:17 -0700821void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
822 const SkColor colors[], int count, SkXfermode::Mode mode,
823 const SkRect* cull, const SkPaint* paint) {
824 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
825 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
826 uint32_t flags = 0;
827 if (colors) {
828 flags |= DRAW_ATLAS_HAS_COLORS;
829 size += count * sizeof(SkColor);
830 size += sizeof(uint32_t); // xfermode::mode
831 }
832 if (cull) {
833 flags |= DRAW_ATLAS_HAS_CULL;
834 size += sizeof(SkRect);
835 }
mtkleinc2e29772015-10-30 05:24:58 -0700836
reed71c3c762015-06-24 10:29:17 -0700837 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
reed71c3c762015-06-24 10:29:17 -0700838 this->addPaintPtr(paint);
839 this->addImage(atlas);
840 this->addInt(flags);
841 this->addInt(count);
842 fWriter.write(xform, count * sizeof(SkRSXform));
843 fWriter.write(tex, count * sizeof(SkRect));
844
845 // write optional parameters
846 if (colors) {
847 fWriter.write(colors, count * sizeof(SkColor));
848 this->addInt(mode);
849 }
850 if (cull) {
851 fWriter.write(cull, sizeof(SkRect));
852 }
853 this->validate(initialOffset, size);
854}
855
reedf70b5312016-03-04 16:36:20 -0800856void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
857 size_t keyLen = fWriter.WriteStringSize(key);
858 size_t valueLen = fWriter.WriteDataSize(value);
859 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
860
861 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
862 this->addRect(rect);
863 fWriter.writeString(key);
864 fWriter.writeData(value);
865 this->validate(initialOffset, size);
866}
867
reed@android.com8a1c16f2008-12-17 15:59:43 +0000868///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000869
reed22b2af12016-08-29 07:52:13 -0700870template <typename T> int find_or_append_uniqueID(SkTDArray<const T*>& array, const T* obj) {
871 int index = array.select([&](const T* elem) {
872 return elem->uniqueID() == obj->uniqueID();
873 });
874 if (index < 0) {
875 index = array.count();
876 *array.append() = SkRef(obj);
877 }
878 return index;
879}
880
reede8f30622016-03-23 18:59:25 -0700881sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700882 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000883}
884
reed871872f2015-06-22 12:48:26 -0700885void SkPictureRecord::addImage(const SkImage* image) {
reed22b2af12016-08-29 07:52:13 -0700886 // convention for images is 0-based index
887 this->addInt(find_or_append_uniqueID(fImageRefs, image));
reed871872f2015-06-22 12:48:26 -0700888}
889
reed@android.com8a1c16f2008-12-17 15:59:43 +0000890void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000891 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000892}
893
mtklein46616af2014-09-30 14:47:10 -0700894void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700895 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000896
mtklein46616af2014-09-30 14:47:10 -0700897 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800898 fPaints.push_back(*paint);
899 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700900 } else {
901 this->addInt(0);
902 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000903}
904
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000905int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700906 if (int* n = fPaths.find(path)) {
907 return *n;
908 }
909 int n = fPaths.count() + 1; // 0 is reserved for null / error.
910 fPaths.set(path, n);
911 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000912}
913
914void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000915 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000916}
917
dandovb3c9d1c2014-08-12 08:34:29 -0700918void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
919 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700920}
921
robertphillips9b14f262014-06-04 05:40:44 -0700922void SkPictureRecord::addPicture(const SkPicture* picture) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000923 // follow the convention of recording a 1-based index
reed22b2af12016-08-29 07:52:13 -0700924 this->addInt(find_or_append_uniqueID(fPictureRefs, picture) + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000925}
926
msarett95416f42016-04-27 13:51:20 -0700927void SkPictureRecord::addDrawable(SkDrawable* drawable) {
928 int index = fDrawableRefs.find(drawable);
929 if (index < 0) { // not found
930 index = fDrawableRefs.count();
931 *fDrawableRefs.append() = drawable;
932 drawable->ref();
933 }
934 // follow the convention of recording a 1-based index
935 this->addInt(index + 1);
936}
937
reed@android.com8a1c16f2008-12-17 15:59:43 +0000938void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000939 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000940}
reed@google.com82065d62011-02-07 15:30:46 +0000941
reed@android.com8a1c16f2008-12-17 15:59:43 +0000942void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
943 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000944}
945
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000946void SkPictureRecord::addNoOp() {
947 size_t size = kUInt32Size; // op
948 this->addDraw(NOOP, &size);
949}
950
reed@android.com8a1c16f2008-12-17 15:59:43 +0000951void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000952 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000953}
954
955void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700956 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000957 fWriter.writeRect(*rect);
958 }
959}
960
reed@google.comf0b5e112011-09-07 11:57:34 +0000961void SkPictureRecord::addIRect(const SkIRect& rect) {
962 fWriter.write(&rect, sizeof(rect));
963}
964
reed@android.com8a1c16f2008-12-17 15:59:43 +0000965void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700966 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000967 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
968 }
969}
970
reed@google.com4ed0fb72012-12-12 20:48:18 +0000971void SkPictureRecord::addRRect(const SkRRect& rrect) {
972 fWriter.writeRRect(rrect);
973}
974
reed@android.com8a1c16f2008-12-17 15:59:43 +0000975void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000976 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000977}
978
979void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -0700980 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000981 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000982 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000983}
984
reed22b2af12016-08-29 07:52:13 -0700985void SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
fmalitab7425172014-08-26 07:56:44 -0700986 // follow the convention of recording a 1-based index
reed22b2af12016-08-29 07:52:13 -0700987 this->addInt(find_or_append_uniqueID(fTextBlobRefs, blob) + 1);
fmalitab7425172014-08-26 07:56:44 -0700988}
989
reed@android.com8a1c16f2008-12-17 15:59:43 +0000990///////////////////////////////////////////////////////////////////////////////