blob: 520451cb6127e6f525e6b48c6064bbfc9e2ac473 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
reed@google.com76f10a32014-02-05 15:32:21 +00007
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkPictureRecord.h"
reeda85d4d02015-05-06 12:56:48 -07009#include "SkImage_Base.h"
dandovb3c9d1c2014-08-12 08:34:29 -070010#include "SkPatchUtils.h"
dandovb3c9d1c2014-08-12 08:34:29 -070011#include "SkPixelRef.h"
12#include "SkRRect.h"
reed71c3c762015-06-24 10:29:17 -070013#include "SkRSXform.h"
fmalitab7425172014-08-26 07:56:44 -070014#include "SkTextBlob.h"
dandovb3c9d1c2014-08-12 08:34:29 -070015#include "SkTSearch.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000016
reed@android.com8a1c16f2008-12-17 15:59:43 +000017#define HEAP_BLOCK_SIZE 4096
18
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000019enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000020 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000021 kNoInitialSave = -1,
22};
23
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000024// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
25static int const kUInt32Size = 4;
26
robertphillips0bdbea72014-06-11 11:37:55 -070027SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000028 : INHERITED(dimensions.width(), dimensions.height())
mtklein71a23632014-11-12 10:24:55 -080029 , fRecordFlags(flags)
30 , fInitialSaveCount(kNoInitialSave) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000031}
32
33SkPictureRecord::~SkPictureRecord() {
robertphillips5351aad2015-06-23 06:54:56 -070034 fImageRefs.unrefAll();
djsollen@google.com21830d92012-08-07 19:49:41 +000035 fPictureRefs.unrefAll();
msarett95416f42016-04-27 13:51:20 -070036 fDrawableRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070037 fTextBlobRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000038}
39
40///////////////////////////////////////////////////////////////////////////////
41
Florin Malita5f6102d2014-06-30 10:13:28 -040042void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +000043 // record the offset to us, making it non-positive to distinguish a save
44 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +000045 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -040046 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000047
Florin Malita5f6102d2014-06-30 10:13:28 -040048 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +000049}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +000050
Florin Malita5f6102d2014-06-30 10:13:28 -040051void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -070052 fContentInfo.onSave();
53
Florin Malita5f6102d2014-06-30 10:13:28 -040054 // op only
reed512f3e32016-01-04 14:11:31 -080055 size_t size = sizeof(kUInt32Size);
robertphillips@google.com8b169312013-10-15 17:47:36 +000056 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +000057
robertphillips@google.com8b169312013-10-15 17:47:36 +000058 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +000059}
60
reed4960eee2015-12-18 07:09:18 -080061SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
reed@google.comffacd3c2012-08-30 15:31:23 +000062 // record the offset to us, making it non-positive to distinguish a save
63 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +000064 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
reed4960eee2015-12-18 07:09:18 -080065 this->recordSaveLayer(rec);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +000066
reed4960eee2015-12-18 07:09:18 -080067 (void)this->INHERITED::getSaveLayerStrategy(rec);
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000068 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +000069 at this time (and may not be able to afford since during record our
70 clip starts out the size of the picture, which is often much larger
71 than the size of the actual device we'll use during playback).
72 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000073 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +000074}
75
reed4960eee2015-12-18 07:09:18 -080076void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
robertphillipsc019ec42014-08-12 05:35:58 -070077 fContentInfo.onSaveLayer();
78
reedbfd5f172016-01-07 11:28:08 -080079 // op + flatflags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +000080 size_t size = 2 * kUInt32Size;
reedbfd5f172016-01-07 11:28:08 -080081 uint32_t flatFlags = 0;
82
reed4960eee2015-12-18 07:09:18 -080083 if (rec.fBounds) {
reedbfd5f172016-01-07 11:28:08 -080084 flatFlags |= SAVELAYERREC_HAS_BOUNDS;
85 size += sizeof(*rec.fBounds);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000086 }
reedbfd5f172016-01-07 11:28:08 -080087 if (rec.fPaint) {
88 flatFlags |= SAVELAYERREC_HAS_PAINT;
89 size += sizeof(uint32_t); // index
90 }
91 if (rec.fBackdrop) {
92 flatFlags |= SAVELAYERREC_HAS_BACKDROP;
93 size += sizeof(uint32_t); // (paint) index
94 }
95 if (rec.fSaveLayerFlags) {
96 flatFlags |= SAVELAYERREC_HAS_FLAGS;
97 size += sizeof(uint32_t);
98 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000099
reedbfd5f172016-01-07 11:28:08 -0800100 const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
101 this->addInt(flatFlags);
102 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
103 this->addRect(*rec.fBounds);
104 }
105 if (flatFlags & SAVELAYERREC_HAS_PAINT) {
106 this->addPaintPtr(rec.fPaint);
107 }
108 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
109 // overkill, but we didn't already track single flattenables, so using a paint for that
110 SkPaint paint;
111 paint.setImageFilter(const_cast<SkImageFilter*>(rec.fBackdrop));
112 this->addPaint(paint);
113 }
114 if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
115 this->addInt(rec.fSaveLayerFlags);
116 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000117 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000118}
119
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000120#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000121/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000122 * Read the op code from 'offset' in 'writer' and extract the size too.
123 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000124static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000125 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000126
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000127 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000128 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000129 if (MASK_24 == *size) {
130 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000131 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000132 }
133 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000134}
mtklein46616af2014-09-30 14:47:10 -0700135#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000136
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000137void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000138#if 0
139 SkASSERT(fRestoreOffsetStack.count() > 1);
140#endif
141
reed@android.comb4e22d62009-07-09 15:20:25 +0000142 // check for underflow
143 if (fRestoreOffsetStack.count() == 0) {
144 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000146
mtklein46616af2014-09-30 14:47:10 -0700147 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000148
reed@android.comb4e22d62009-07-09 15:20:25 +0000149 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000150
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000151 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152}
153
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000154void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700155 fContentInfo.onRestore();
156
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000157 if (fillInSkips) {
158 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
159 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000160 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
161 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000162 this->validate(initialOffset, size);
163}
164
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000165void SkPictureRecord::recordTranslate(const SkMatrix& m) {
166 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
167
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000168 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000169 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000170 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000171 this->addScalar(m.getTranslateX());
172 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000173 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174}
175
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000176void SkPictureRecord::recordScale(const SkMatrix& m) {
177 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000178
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000179 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000180 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000181 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000182 this->addScalar(m.getScaleX());
183 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000184 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185}
186
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000187void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000188 switch (matrix.getType()) {
189 case SkMatrix::kTranslate_Mask:
190 this->recordTranslate(matrix);
191 break;
192 case SkMatrix::kScale_Mask:
193 this->recordScale(matrix);
194 break;
195 default:
196 this->recordConcat(matrix);
197 break;
198 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000199 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000200}
201
202void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000203 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000204 // op + matrix
halcanary96fcdcc2015-08-27 07:41:13 -0700205 size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000206 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000207 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000208 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209}
210
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000211void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000212 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000213 // op + matrix
halcanary96fcdcc2015-08-27 07:41:13 -0700214 size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000215 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000216 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000217 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000218 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000219}
220
vjiaoblacke5de1302016-07-13 14:05:28 -0700221void SkPictureRecord::didTranslateZ(SkScalar z) {
vjiaoblack95302da2016-07-21 10:25:54 -0700222#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke5de1302016-07-13 14:05:28 -0700223 this->validate(fWriter.bytesWritten(), 0);
224 // op + scalar
225 size_t size = 1 * kUInt32Size + 1 * sizeof(SkScalar);
226 size_t initialOffset = this->addDraw(TRANSLATE_Z, &size);
227 this->addScalar(z);
228 this->validate(initialOffset, size);
229 this->INHERITED::didTranslateZ(z);
vjiaoblack95302da2016-07-21 10:25:54 -0700230#endif
vjiaoblacke5de1302016-07-13 14:05:28 -0700231}
232
reed@google.com45482d12011-08-29 19:02:39 +0000233static bool regionOpExpands(SkRegion::Op op) {
234 switch (op) {
235 case SkRegion::kUnion_Op:
236 case SkRegion::kXOR_Op:
237 case SkRegion::kReverseDifference_Op:
238 case SkRegion::kReplace_Op:
239 return true;
240 case SkRegion::kIntersect_Op:
241 case SkRegion::kDifference_Op:
242 return false;
243 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000244 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000245 return false;
246 }
247}
248
robertphillips@google.come37ad352013-03-01 19:44:30 +0000249void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000250 int32_t offset = fRestoreOffsetStack.top();
251 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000252 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
253 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000254 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000255 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000256
reed@google.comffacd3c2012-08-30 15:31:23 +0000257#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800258 // offset of 0 has been disabled, so we skip it
259 if (offset > 0) {
260 // assert that the final offset value points to a save verb
261 uint32_t opSize;
262 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
reed4960eee2015-12-18 07:09:18 -0800263 SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
reedbfd5f172016-01-07 11:28:08 -0800264 SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
265 SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
reed2ff1fce2014-12-11 07:07:37 -0800266 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000267#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000268}
269
reed@google.comd86e7ab2012-09-27 20:31:31 +0000270void SkPictureRecord::beginRecording() {
271 // we have to call this *after* our constructor, to ensure that it gets
272 // recorded. This is balanced by restoreToCount() call from endRecording,
273 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000274 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000275}
276
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000277void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000278 SkASSERT(kNoInitialSave != fInitialSaveCount);
279 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000280}
281
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000282size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000283 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000284 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000285 }
286
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000287 // The RestoreOffset field is initially filled with a placeholder
288 // value that points to the offset of the previous RestoreOffset
289 // in the current stack level, thus forming a linked list so that
290 // the restore offsets can be filled in when the corresponding
291 // restore command is recorded.
292 int32_t prevOffset = fRestoreOffsetStack.top();
293
reed@google.com45482d12011-08-29 19:02:39 +0000294 if (regionOpExpands(op)) {
295 // Run back through any previous clip ops, and mark their offset to
296 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
297 // they could hide this clips ability to expand the clip (i.e. go from
298 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000299 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000300
301 // Reset the pointer back to the previous clip so that subsequent
302 // restores don't overwrite the offsets we just cleared.
303 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000304 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000305
reed@google.com44699382013-10-31 17:28:30 +0000306 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000307 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000308 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000309 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000310}
311
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000312void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000313 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000314 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000315}
316
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000317size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000318 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000319 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000320 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000321 if (!fRestoreOffsetStack.isEmpty()) {
322 // + restore offset
323 size += kUInt32Size;
324 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000325 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000326 this->addRect(rect);
327 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000328 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000329
robertphillips@google.com8b169312013-10-15 17:47:36 +0000330 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000331 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000332}
333
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000334void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000335 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700336 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000337}
338
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000339size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000340 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000341 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000342 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000343 if (!fRestoreOffsetStack.isEmpty()) {
344 // + restore offset
345 size += kUInt32Size;
346 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000347 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000348 this->addRRect(rrect);
349 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000350 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000351 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000352 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000353}
354
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000355void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000356 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000357 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700358 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000359}
360
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000361size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000362 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000363 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000364 // recordRestoreOffsetPlaceholder doesn't always write an offset
365 if (!fRestoreOffsetStack.isEmpty()) {
366 // + restore offset
367 size += kUInt32Size;
368 }
369 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000370 this->addInt(pathID);
371 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000372 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000373 this->validate(initialOffset, size);
374 return offset;
375}
376
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000377void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000378 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000379 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000380}
381
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000382size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000383 // op + clip params + region
halcanary96fcdcc2015-08-27 07:41:13 -0700384 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000385 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000386 if (!fRestoreOffsetStack.isEmpty()) {
387 // + restore offset
388 size += kUInt32Size;
389 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000390 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000391 this->addRegion(region);
392 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000393 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000394
robertphillips@google.com8b169312013-10-15 17:47:36 +0000395 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000396 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000397}
398
reed41af9662015-01-05 07:49:08 -0800399void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000400 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000401 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000402 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000403 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000404 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000405}
406
reed41af9662015-01-05 07:49:08 -0800407void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
408 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700409 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000410
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000411 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000412 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000413 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000414 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700415
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000416 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000417 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000419 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000420}
421
reed41af9662015-01-05 07:49:08 -0800422void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000423 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000424 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000425 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000426 this->addPaint(paint);
427 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000428 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000429}
430
reed41af9662015-01-05 07:49:08 -0800431void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000432 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000433 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000434 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000435 this->addPaint(paint);
436 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000437 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000438}
439
reed41af9662015-01-05 07:49:08 -0800440void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700441 // op + paint index + rrect
442 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
443 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein46616af2014-09-30 14:47:10 -0700444 this->addPaint(paint);
445 this->addRRect(rrect);
446 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000447}
448
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000449void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
450 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000451 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000452 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
453 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000454 this->addPaint(paint);
455 this->addRRect(outer);
456 this->addRRect(inner);
457 this->validate(initialOffset, size);
458}
459
reed41af9662015-01-05 07:49:08 -0800460void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700461 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000462
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000463 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000464 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000465 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000466 this->addPaint(paint);
467 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000468 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000469}
470
reeda85d4d02015-05-06 12:56:48 -0700471void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
472 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700473 // op + paint_index + image_index + x + y
474 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
475 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
reed871872f2015-06-22 12:48:26 -0700476 this->addPaintPtr(paint);
477 this->addImage(image);
478 this->addScalar(x);
479 this->addScalar(y);
480 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700481}
482
483void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700484 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700485 // id + paint_index + image_index + bool_for_src + constraint
486 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700487 if (src) {
488 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700489 }
reed871872f2015-06-22 12:48:26 -0700490 size += sizeof(dst); // + rect
mtkleinc2e29772015-10-30 05:24:58 -0700491
reed871872f2015-06-22 12:48:26 -0700492 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
reed871872f2015-06-22 12:48:26 -0700493 this->addPaintPtr(paint);
494 this->addImage(image);
495 this->addRectPtr(src); // may be null
496 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700497 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700498 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700499}
500
reed4c21dc52015-06-25 12:32:03 -0700501void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
502 const SkPaint* paint) {
503 // id + paint_index + image_index + center + dst
504 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
mtkleinc2e29772015-10-30 05:24:58 -0700505
reed4c21dc52015-06-25 12:32:03 -0700506 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
reed4c21dc52015-06-25 12:32:03 -0700507 this->addPaintPtr(paint);
508 this->addImage(img);
509 this->addIRect(center);
510 this->addRect(dst);
511 this->validate(initialOffset, size);
512}
513
msarett16882062016-08-16 09:31:08 -0700514void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
515 const SkRect& dst, const SkPaint* paint) {
516 // xCount + xDivs + yCount+ yDivs
517 size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount) * kUInt32Size;
518
519 // op + paint index + image index + lattice + dst rect
520 size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
521 size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
522 this->addPaintPtr(paint);
523 this->addImage(image);
524 this->addInt(lattice.fXCount);
525 fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
526 this->addInt(lattice.fYCount);
527 fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
528 this->addRect(dst);
529 this->validate(initialOffset, size);
530}
531
reed@google.come0d9ce82014-04-23 04:00:17 +0000532void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
533 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000534 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000535 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000536
mtklein46616af2014-09-30 14:47:10 -0700537 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000538 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700539 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000540 this->addText(text, byteLength);
541 this->addScalar(x);
542 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000543 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000544}
545
reed@google.come0d9ce82014-04-23 04:00:17 +0000546void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
547 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000548 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000549
mtklein46616af2014-09-30 14:47:10 -0700550 // op + paint index + length + 'length' worth of data + num points + x&y point data
551 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000552
mtklein46616af2014-09-30 14:47:10 -0700553 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000554
robertphillips@google.com8b169312013-10-15 17:47:36 +0000555 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700556 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000557 this->addText(text, byteLength);
558 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700559 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000560 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000561}
562
reed@google.come0d9ce82014-04-23 04:00:17 +0000563void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
564 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000565 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000566
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000567 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000568 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000569 // + y + the actual points
570 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000571
mtklein46616af2014-09-30 14:47:10 -0700572 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
573 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000574 this->addText(text, byteLength);
575 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000576 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000577 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000578 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000579}
580
reed@google.come0d9ce82014-04-23 04:00:17 +0000581void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
582 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000583 // op + paint index + length + 'length' worth of data + path index + matrix
584 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700585 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000586 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000587 this->addPaint(paint);
588 this->addText(text, byteLength);
589 this->addPath(path);
590 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000591 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000592}
593
reed45561a02016-07-07 12:47:17 -0700594void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
595 const SkRSXform xform[], const SkRect* cull,
596 const SkPaint& paint) {
597 const int count = paint.countText(text, byteLength);
598 // [op + paint-index + count + flags + length] + [text] + [xform] + cull
599 size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
600 uint32_t flags = 0;
601 if (cull) {
602 flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
603 size += sizeof(SkRect);
604 }
605
606 size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
607 this->addPaint(paint);
608 this->addInt(count);
609 this->addInt(flags);
610 this->addText(text, byteLength);
611 fWriter.write(xform, count * sizeof(SkRSXform));
612 if (cull) {
613 fWriter.write(cull, sizeof(SkRect));
614 }
615 this->validate(initialOffset, size);
616}
617
fmalitab7425172014-08-26 07:56:44 -0700618void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
619 const SkPaint& paint) {
620
621 // op + paint index + blob index + x/y
622 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
623 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
fmalitab7425172014-08-26 07:56:44 -0700624
625 this->addPaint(paint);
626 this->addTextBlob(blob);
627 this->addScalar(x);
628 this->addScalar(y);
629
630 this->validate(initialOffset, size);
631}
632
reedd5fa1a42014-08-09 11:08:05 -0700633void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
634 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000635 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000636 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700637 size_t initialOffset;
638
halcanary96fcdcc2015-08-27 07:41:13 -0700639 if (nullptr == matrix && nullptr == paint) {
reedd5fa1a42014-08-09 11:08:05 -0700640 initialOffset = this->addDraw(DRAW_PICTURE, &size);
641 this->addPicture(picture);
642 } else {
643 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700644 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
reedd5fa1a42014-08-09 11:08:05 -0700645 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
reedd5fa1a42014-08-09 11:08:05 -0700646 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700647 this->addMatrix(m);
648 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700649 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000650 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000651}
652
vjiaoblack95302da2016-07-21 10:25:54 -0700653void SkPictureRecord::onDrawShadowedPicture(const SkPicture* picture,
654 const SkMatrix* matrix,
655 const SkPaint* paint) {
656 // op + picture index
657 size_t size = 2 * kUInt32Size;
658 size_t initialOffset;
659
660 if (nullptr == matrix && nullptr == paint) {
661 initialOffset = this->addDraw(DRAW_PICTURE, &size);
662 this->addPicture(picture);
663 } else {
664 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
665 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
666 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
667 this->addPaintPtr(paint);
668 this->addMatrix(m);
669 this->addPicture(picture);
670 }
671 this->validate(initialOffset, size);
672}
673
msarett95416f42016-04-27 13:51:20 -0700674void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
675 // op + drawable index
676 size_t size = 2 * kUInt32Size;
677 size_t initialOffset;
678
679 if (nullptr == matrix) {
680 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
681 this->addDrawable(drawable);
682 } else {
683 size += matrix->writeToMemory(nullptr); // matrix
684 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
685 this->addMatrix(*matrix);
686 this->addDrawable(drawable);
687 }
688 this->validate(initialOffset, size);
689}
690
reed41af9662015-01-05 07:49:08 -0800691void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
692 const SkPoint vertices[], const SkPoint texs[],
693 const SkColor colors[], SkXfermode* xfer,
694 const uint16_t indices[], int indexCount,
695 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000696 uint32_t flags = 0;
697 if (texs) {
698 flags |= DRAW_VERTICES_HAS_TEXS;
699 }
700 if (colors) {
701 flags |= DRAW_VERTICES_HAS_COLORS;
702 }
703 if (indexCount > 0) {
704 flags |= DRAW_VERTICES_HAS_INDICES;
705 }
bsalomon49f085d2014-09-05 13:34:00 -0700706 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000707 SkXfermode::Mode mode;
708 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
709 flags |= DRAW_VERTICES_HAS_XFER;
710 }
711 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000712
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000713 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000714 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000715 if (flags & DRAW_VERTICES_HAS_TEXS) {
716 size += vertexCount * sizeof(SkPoint); // + uvs
717 }
718 if (flags & DRAW_VERTICES_HAS_COLORS) {
719 size += vertexCount * sizeof(SkColor); // + vert colors
720 }
721 if (flags & DRAW_VERTICES_HAS_INDICES) {
722 // + num indices + indices
723 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
724 }
reed@google.com85e143c2013-12-30 15:51:25 +0000725 if (flags & DRAW_VERTICES_HAS_XFER) {
726 size += kUInt32Size; // mode enum
727 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000728
robertphillips@google.com8b169312013-10-15 17:47:36 +0000729 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000730 this->addPaint(paint);
731 this->addInt(flags);
732 this->addInt(vmode);
733 this->addInt(vertexCount);
734 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000735 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000736 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000737 }
738 if (flags & DRAW_VERTICES_HAS_COLORS) {
739 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
740 }
741 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000742 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000743 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
744 }
reed@google.com85e143c2013-12-30 15:51:25 +0000745 if (flags & DRAW_VERTICES_HAS_XFER) {
746 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
747 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000748 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000749 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000750 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000751}
752
dandovb3c9d1c2014-08-12 08:34:29 -0700753void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
754 const SkPoint texCoords[4], SkXfermode* xmode,
755 const SkPaint& paint) {
756 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
757 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
758 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700759 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700760 flag |= DRAW_VERTICES_HAS_COLORS;
761 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
762 }
bsalomon49f085d2014-09-05 13:34:00 -0700763 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700764 flag |= DRAW_VERTICES_HAS_TEXS;
765 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
766 }
bsalomon49f085d2014-09-05 13:34:00 -0700767 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700768 SkXfermode::Mode mode;
769 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
770 flag |= DRAW_VERTICES_HAS_XFER;
771 size += kUInt32Size;
772 }
773 }
mtklein46616af2014-09-30 14:47:10 -0700774
dandov963137b2014-08-07 07:49:53 -0700775 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
dandov963137b2014-08-07 07:49:53 -0700776 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700777 this->addPatch(cubics);
778 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700779
dandovb3c9d1c2014-08-12 08:34:29 -0700780 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700781 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700782 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
783 }
bsalomon49f085d2014-09-05 13:34:00 -0700784 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700785 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
786 }
787 if (flag & DRAW_VERTICES_HAS_XFER) {
788 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
789 xmode->asMode(&mode);
790 this->addInt(mode);
791 }
dandov963137b2014-08-07 07:49:53 -0700792 this->validate(initialOffset, size);
793}
794
reed71c3c762015-06-24 10:29:17 -0700795void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
796 const SkColor colors[], int count, SkXfermode::Mode mode,
797 const SkRect* cull, const SkPaint* paint) {
798 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
799 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
800 uint32_t flags = 0;
801 if (colors) {
802 flags |= DRAW_ATLAS_HAS_COLORS;
803 size += count * sizeof(SkColor);
804 size += sizeof(uint32_t); // xfermode::mode
805 }
806 if (cull) {
807 flags |= DRAW_ATLAS_HAS_CULL;
808 size += sizeof(SkRect);
809 }
mtkleinc2e29772015-10-30 05:24:58 -0700810
reed71c3c762015-06-24 10:29:17 -0700811 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
reed71c3c762015-06-24 10:29:17 -0700812 this->addPaintPtr(paint);
813 this->addImage(atlas);
814 this->addInt(flags);
815 this->addInt(count);
816 fWriter.write(xform, count * sizeof(SkRSXform));
817 fWriter.write(tex, count * sizeof(SkRect));
818
819 // write optional parameters
820 if (colors) {
821 fWriter.write(colors, count * sizeof(SkColor));
822 this->addInt(mode);
823 }
824 if (cull) {
825 fWriter.write(cull, sizeof(SkRect));
826 }
827 this->validate(initialOffset, size);
828}
829
reedf70b5312016-03-04 16:36:20 -0800830void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
831 size_t keyLen = fWriter.WriteStringSize(key);
832 size_t valueLen = fWriter.WriteDataSize(value);
833 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
834
835 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
836 this->addRect(rect);
837 fWriter.writeString(key);
838 fWriter.writeData(value);
839 this->validate(initialOffset, size);
840}
841
reed@android.com8a1c16f2008-12-17 15:59:43 +0000842///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000843
reede8f30622016-03-23 18:59:25 -0700844sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700845 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000846}
847
reed871872f2015-06-22 12:48:26 -0700848void SkPictureRecord::addImage(const SkImage* image) {
849 int index = fImageRefs.find(image);
850 if (index >= 0) {
851 this->addInt(index);
852 } else {
853 *fImageRefs.append() = SkRef(image);
854 this->addInt(fImageRefs.count()-1);
855 }
856}
857
reed@android.com8a1c16f2008-12-17 15:59:43 +0000858void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000859 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000860}
861
mtklein46616af2014-09-30 14:47:10 -0700862void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700863 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000864
mtklein46616af2014-09-30 14:47:10 -0700865 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800866 fPaints.push_back(*paint);
867 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700868 } else {
869 this->addInt(0);
870 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000871}
872
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000873int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700874 if (int* n = fPaths.find(path)) {
875 return *n;
876 }
877 int n = fPaths.count() + 1; // 0 is reserved for null / error.
878 fPaths.set(path, n);
879 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000880}
881
882void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000883 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000884}
885
dandovb3c9d1c2014-08-12 08:34:29 -0700886void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
887 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700888}
889
robertphillips9b14f262014-06-04 05:40:44 -0700890void SkPictureRecord::addPicture(const SkPicture* picture) {
891 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000892 if (index < 0) { // not found
893 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700894 *fPictureRefs.append() = picture;
895 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000896 }
897 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000898 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000899}
900
msarett95416f42016-04-27 13:51:20 -0700901void SkPictureRecord::addDrawable(SkDrawable* drawable) {
902 int index = fDrawableRefs.find(drawable);
903 if (index < 0) { // not found
904 index = fDrawableRefs.count();
905 *fDrawableRefs.append() = drawable;
906 drawable->ref();
907 }
908 // follow the convention of recording a 1-based index
909 this->addInt(index + 1);
910}
911
reed@android.com8a1c16f2008-12-17 15:59:43 +0000912void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000913 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000914}
reed@google.com82065d62011-02-07 15:30:46 +0000915
reed@android.com8a1c16f2008-12-17 15:59:43 +0000916void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
917 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000918}
919
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000920void SkPictureRecord::addNoOp() {
921 size_t size = kUInt32Size; // op
922 this->addDraw(NOOP, &size);
923}
924
reed@android.com8a1c16f2008-12-17 15:59:43 +0000925void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000926 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000927}
928
929void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700930 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000931 fWriter.writeRect(*rect);
932 }
933}
934
reed@google.comf0b5e112011-09-07 11:57:34 +0000935void SkPictureRecord::addIRect(const SkIRect& rect) {
936 fWriter.write(&rect, sizeof(rect));
937}
938
reed@android.com8a1c16f2008-12-17 15:59:43 +0000939void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700940 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000941 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
942 }
943}
944
reed@google.com4ed0fb72012-12-12 20:48:18 +0000945void SkPictureRecord::addRRect(const SkRRect& rrect) {
946 fWriter.writeRRect(rrect);
947}
948
reed@android.com8a1c16f2008-12-17 15:59:43 +0000949void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000950 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000951}
952
953void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -0700954 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000955 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000956 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000957}
958
fmalitab7425172014-08-26 07:56:44 -0700959void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -0700960 int index = fTextBlobRefs.count();
961 *fTextBlobRefs.append() = blob;
962 blob->ref();
fmalitab7425172014-08-26 07:56:44 -0700963 // follow the convention of recording a 1-based index
964 this->addInt(index + 1);
965}
966
reed@android.com8a1c16f2008-12-17 15:59:43 +0000967///////////////////////////////////////////////////////////////////////////////