blob: c461bfbbac1953980082772dc27bb9335a4593e6 [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
reed41af9662015-01-05 07:49:08 -0800454void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700455 // op + paint index + rrect
456 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
457 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein46616af2014-09-30 14:47:10 -0700458 this->addPaint(paint);
459 this->addRRect(rrect);
460 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000461}
462
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000463void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
464 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000465 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000466 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
467 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000468 this->addPaint(paint);
469 this->addRRect(outer);
470 this->addRRect(inner);
471 this->validate(initialOffset, size);
472}
473
reed41af9662015-01-05 07:49:08 -0800474void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700475 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000476
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000477 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000478 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000479 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000480 this->addPaint(paint);
481 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000482 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000483}
484
reeda85d4d02015-05-06 12:56:48 -0700485void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
486 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700487 // op + paint_index + image_index + x + y
488 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
489 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
reed871872f2015-06-22 12:48:26 -0700490 this->addPaintPtr(paint);
491 this->addImage(image);
492 this->addScalar(x);
493 this->addScalar(y);
494 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700495}
496
497void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700498 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700499 // id + paint_index + image_index + bool_for_src + constraint
500 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700501 if (src) {
502 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700503 }
reed871872f2015-06-22 12:48:26 -0700504 size += sizeof(dst); // + rect
mtkleinc2e29772015-10-30 05:24:58 -0700505
reed871872f2015-06-22 12:48:26 -0700506 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
reed871872f2015-06-22 12:48:26 -0700507 this->addPaintPtr(paint);
508 this->addImage(image);
509 this->addRectPtr(src); // may be null
510 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700511 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700512 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700513}
514
reed4c21dc52015-06-25 12:32:03 -0700515void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
516 const SkPaint* paint) {
517 // id + paint_index + image_index + center + dst
518 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
mtkleinc2e29772015-10-30 05:24:58 -0700519
reed4c21dc52015-06-25 12:32:03 -0700520 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
reed4c21dc52015-06-25 12:32:03 -0700521 this->addPaintPtr(paint);
522 this->addImage(img);
523 this->addIRect(center);
524 this->addRect(dst);
525 this->validate(initialOffset, size);
526}
527
msarett16882062016-08-16 09:31:08 -0700528void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
529 const SkRect& dst, const SkPaint* paint) {
530 // xCount + xDivs + yCount+ yDivs
531 size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount) * kUInt32Size;
532
533 // op + paint index + image index + lattice + dst rect
534 size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
535 size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
536 this->addPaintPtr(paint);
537 this->addImage(image);
538 this->addInt(lattice.fXCount);
539 fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
540 this->addInt(lattice.fYCount);
541 fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
542 this->addRect(dst);
543 this->validate(initialOffset, size);
544}
545
reed@google.come0d9ce82014-04-23 04:00:17 +0000546void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
547 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000548 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000549 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000550
mtklein46616af2014-09-30 14:47:10 -0700551 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000552 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700553 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000554 this->addText(text, byteLength);
555 this->addScalar(x);
556 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000557 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000558}
559
reed@google.come0d9ce82014-04-23 04:00:17 +0000560void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
561 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000562 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000563
mtklein46616af2014-09-30 14:47:10 -0700564 // op + paint index + length + 'length' worth of data + num points + x&y point data
565 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000566
mtklein46616af2014-09-30 14:47:10 -0700567 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000568
robertphillips@google.com8b169312013-10-15 17:47:36 +0000569 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700570 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000571 this->addText(text, byteLength);
572 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700573 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000574 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000575}
576
reed@google.come0d9ce82014-04-23 04:00:17 +0000577void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
578 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000579 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000580
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000581 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000582 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000583 // + y + the actual points
584 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000585
mtklein46616af2014-09-30 14:47:10 -0700586 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
587 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000588 this->addText(text, byteLength);
589 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000590 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000591 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000592 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000593}
594
reed@google.come0d9ce82014-04-23 04:00:17 +0000595void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
596 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000597 // op + paint index + length + 'length' worth of data + path index + matrix
598 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700599 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000600 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000601 this->addPaint(paint);
602 this->addText(text, byteLength);
603 this->addPath(path);
604 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000605 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000606}
607
reed45561a02016-07-07 12:47:17 -0700608void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
609 const SkRSXform xform[], const SkRect* cull,
610 const SkPaint& paint) {
611 const int count = paint.countText(text, byteLength);
612 // [op + paint-index + count + flags + length] + [text] + [xform] + cull
613 size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
614 uint32_t flags = 0;
615 if (cull) {
616 flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
617 size += sizeof(SkRect);
618 }
619
620 size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
621 this->addPaint(paint);
622 this->addInt(count);
623 this->addInt(flags);
624 this->addText(text, byteLength);
625 fWriter.write(xform, count * sizeof(SkRSXform));
626 if (cull) {
627 fWriter.write(cull, sizeof(SkRect));
628 }
629 this->validate(initialOffset, size);
630}
631
fmalitab7425172014-08-26 07:56:44 -0700632void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
633 const SkPaint& paint) {
634
635 // op + paint index + blob index + x/y
636 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
637 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
fmalitab7425172014-08-26 07:56:44 -0700638
639 this->addPaint(paint);
640 this->addTextBlob(blob);
641 this->addScalar(x);
642 this->addScalar(y);
643
644 this->validate(initialOffset, size);
645}
646
reedd5fa1a42014-08-09 11:08:05 -0700647void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
648 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000649 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000650 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700651 size_t initialOffset;
652
halcanary96fcdcc2015-08-27 07:41:13 -0700653 if (nullptr == matrix && nullptr == paint) {
reedd5fa1a42014-08-09 11:08:05 -0700654 initialOffset = this->addDraw(DRAW_PICTURE, &size);
655 this->addPicture(picture);
656 } else {
657 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700658 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
reedd5fa1a42014-08-09 11:08:05 -0700659 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
reedd5fa1a42014-08-09 11:08:05 -0700660 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700661 this->addMatrix(m);
662 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700663 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000664 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000665}
666
vjiaoblack95302da2016-07-21 10:25:54 -0700667void SkPictureRecord::onDrawShadowedPicture(const SkPicture* picture,
668 const SkMatrix* matrix,
vjiaoblacke6f5d562016-08-25 06:30:23 -0700669 const SkPaint* paint,
670 const SkShadowParams& params) {
vjiaoblack95302da2016-07-21 10:25:54 -0700671 // op + picture index
672 size_t size = 2 * kUInt32Size;
673 size_t initialOffset;
674
vjiaoblacke6f5d562016-08-25 06:30:23 -0700675 // TODO: handle recording params.
vjiaoblack95302da2016-07-21 10:25:54 -0700676 if (nullptr == matrix && nullptr == paint) {
677 initialOffset = this->addDraw(DRAW_PICTURE, &size);
678 this->addPicture(picture);
679 } else {
680 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
681 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
682 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
683 this->addPaintPtr(paint);
684 this->addMatrix(m);
685 this->addPicture(picture);
686 }
687 this->validate(initialOffset, size);
688}
689
msarett95416f42016-04-27 13:51:20 -0700690void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
691 // op + drawable index
692 size_t size = 2 * kUInt32Size;
693 size_t initialOffset;
694
695 if (nullptr == matrix) {
696 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
697 this->addDrawable(drawable);
698 } else {
699 size += matrix->writeToMemory(nullptr); // matrix
700 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
701 this->addMatrix(*matrix);
702 this->addDrawable(drawable);
703 }
704 this->validate(initialOffset, size);
705}
706
reed41af9662015-01-05 07:49:08 -0800707void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
708 const SkPoint vertices[], const SkPoint texs[],
709 const SkColor colors[], SkXfermode* xfer,
710 const uint16_t indices[], int indexCount,
711 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000712 uint32_t flags = 0;
713 if (texs) {
714 flags |= DRAW_VERTICES_HAS_TEXS;
715 }
716 if (colors) {
717 flags |= DRAW_VERTICES_HAS_COLORS;
718 }
719 if (indexCount > 0) {
720 flags |= DRAW_VERTICES_HAS_INDICES;
721 }
bsalomon49f085d2014-09-05 13:34:00 -0700722 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000723 SkXfermode::Mode mode;
724 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
725 flags |= DRAW_VERTICES_HAS_XFER;
726 }
727 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000728
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000729 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000730 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000731 if (flags & DRAW_VERTICES_HAS_TEXS) {
732 size += vertexCount * sizeof(SkPoint); // + uvs
733 }
734 if (flags & DRAW_VERTICES_HAS_COLORS) {
735 size += vertexCount * sizeof(SkColor); // + vert colors
736 }
737 if (flags & DRAW_VERTICES_HAS_INDICES) {
738 // + num indices + indices
739 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
740 }
reed@google.com85e143c2013-12-30 15:51:25 +0000741 if (flags & DRAW_VERTICES_HAS_XFER) {
742 size += kUInt32Size; // mode enum
743 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000744
robertphillips@google.com8b169312013-10-15 17:47:36 +0000745 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000746 this->addPaint(paint);
747 this->addInt(flags);
748 this->addInt(vmode);
749 this->addInt(vertexCount);
750 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000751 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000752 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000753 }
754 if (flags & DRAW_VERTICES_HAS_COLORS) {
755 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
756 }
757 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000758 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000759 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
760 }
reed@google.com85e143c2013-12-30 15:51:25 +0000761 if (flags & DRAW_VERTICES_HAS_XFER) {
762 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
763 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000764 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000765 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000766 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000767}
768
dandovb3c9d1c2014-08-12 08:34:29 -0700769void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
770 const SkPoint texCoords[4], SkXfermode* xmode,
771 const SkPaint& paint) {
772 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
773 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
774 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700775 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700776 flag |= DRAW_VERTICES_HAS_COLORS;
777 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
778 }
bsalomon49f085d2014-09-05 13:34:00 -0700779 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700780 flag |= DRAW_VERTICES_HAS_TEXS;
781 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
782 }
bsalomon49f085d2014-09-05 13:34:00 -0700783 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700784 SkXfermode::Mode mode;
785 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
786 flag |= DRAW_VERTICES_HAS_XFER;
787 size += kUInt32Size;
788 }
789 }
mtklein46616af2014-09-30 14:47:10 -0700790
dandov963137b2014-08-07 07:49:53 -0700791 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
dandov963137b2014-08-07 07:49:53 -0700792 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700793 this->addPatch(cubics);
794 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700795
dandovb3c9d1c2014-08-12 08:34:29 -0700796 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700797 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700798 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
799 }
bsalomon49f085d2014-09-05 13:34:00 -0700800 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700801 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
802 }
803 if (flag & DRAW_VERTICES_HAS_XFER) {
804 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
805 xmode->asMode(&mode);
806 this->addInt(mode);
807 }
dandov963137b2014-08-07 07:49:53 -0700808 this->validate(initialOffset, size);
809}
810
reed71c3c762015-06-24 10:29:17 -0700811void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
812 const SkColor colors[], int count, SkXfermode::Mode mode,
813 const SkRect* cull, const SkPaint* paint) {
814 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
815 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
816 uint32_t flags = 0;
817 if (colors) {
818 flags |= DRAW_ATLAS_HAS_COLORS;
819 size += count * sizeof(SkColor);
820 size += sizeof(uint32_t); // xfermode::mode
821 }
822 if (cull) {
823 flags |= DRAW_ATLAS_HAS_CULL;
824 size += sizeof(SkRect);
825 }
mtkleinc2e29772015-10-30 05:24:58 -0700826
reed71c3c762015-06-24 10:29:17 -0700827 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
reed71c3c762015-06-24 10:29:17 -0700828 this->addPaintPtr(paint);
829 this->addImage(atlas);
830 this->addInt(flags);
831 this->addInt(count);
832 fWriter.write(xform, count * sizeof(SkRSXform));
833 fWriter.write(tex, count * sizeof(SkRect));
834
835 // write optional parameters
836 if (colors) {
837 fWriter.write(colors, count * sizeof(SkColor));
838 this->addInt(mode);
839 }
840 if (cull) {
841 fWriter.write(cull, sizeof(SkRect));
842 }
843 this->validate(initialOffset, size);
844}
845
reedf70b5312016-03-04 16:36:20 -0800846void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
847 size_t keyLen = fWriter.WriteStringSize(key);
848 size_t valueLen = fWriter.WriteDataSize(value);
849 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
850
851 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
852 this->addRect(rect);
853 fWriter.writeString(key);
854 fWriter.writeData(value);
855 this->validate(initialOffset, size);
856}
857
reed@android.com8a1c16f2008-12-17 15:59:43 +0000858///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000859
reede8f30622016-03-23 18:59:25 -0700860sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700861 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000862}
863
reed871872f2015-06-22 12:48:26 -0700864void SkPictureRecord::addImage(const SkImage* image) {
865 int index = fImageRefs.find(image);
866 if (index >= 0) {
867 this->addInt(index);
868 } else {
869 *fImageRefs.append() = SkRef(image);
870 this->addInt(fImageRefs.count()-1);
871 }
872}
873
reed@android.com8a1c16f2008-12-17 15:59:43 +0000874void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000875 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000876}
877
mtklein46616af2014-09-30 14:47:10 -0700878void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700879 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000880
mtklein46616af2014-09-30 14:47:10 -0700881 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800882 fPaints.push_back(*paint);
883 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700884 } else {
885 this->addInt(0);
886 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000887}
888
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000889int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700890 if (int* n = fPaths.find(path)) {
891 return *n;
892 }
893 int n = fPaths.count() + 1; // 0 is reserved for null / error.
894 fPaths.set(path, n);
895 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000896}
897
898void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000899 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000900}
901
dandovb3c9d1c2014-08-12 08:34:29 -0700902void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
903 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700904}
905
robertphillips9b14f262014-06-04 05:40:44 -0700906void SkPictureRecord::addPicture(const SkPicture* picture) {
907 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000908 if (index < 0) { // not found
909 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700910 *fPictureRefs.append() = picture;
911 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000912 }
913 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000914 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000915}
916
msarett95416f42016-04-27 13:51:20 -0700917void SkPictureRecord::addDrawable(SkDrawable* drawable) {
918 int index = fDrawableRefs.find(drawable);
919 if (index < 0) { // not found
920 index = fDrawableRefs.count();
921 *fDrawableRefs.append() = drawable;
922 drawable->ref();
923 }
924 // follow the convention of recording a 1-based index
925 this->addInt(index + 1);
926}
927
reed@android.com8a1c16f2008-12-17 15:59:43 +0000928void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000929 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000930}
reed@google.com82065d62011-02-07 15:30:46 +0000931
reed@android.com8a1c16f2008-12-17 15:59:43 +0000932void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
933 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000934}
935
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000936void SkPictureRecord::addNoOp() {
937 size_t size = kUInt32Size; // op
938 this->addDraw(NOOP, &size);
939}
940
reed@android.com8a1c16f2008-12-17 15:59:43 +0000941void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000942 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000943}
944
945void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700946 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000947 fWriter.writeRect(*rect);
948 }
949}
950
reed@google.comf0b5e112011-09-07 11:57:34 +0000951void SkPictureRecord::addIRect(const SkIRect& rect) {
952 fWriter.write(&rect, sizeof(rect));
953}
954
reed@android.com8a1c16f2008-12-17 15:59:43 +0000955void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700956 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000957 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
958 }
959}
960
reed@google.com4ed0fb72012-12-12 20:48:18 +0000961void SkPictureRecord::addRRect(const SkRRect& rrect) {
962 fWriter.writeRRect(rrect);
963}
964
reed@android.com8a1c16f2008-12-17 15:59:43 +0000965void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000966 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000967}
968
969void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -0700970 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000971 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000972 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000973}
974
fmalitab7425172014-08-26 07:56:44 -0700975void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -0700976 int index = fTextBlobRefs.count();
977 *fTextBlobRefs.append() = blob;
978 blob->ref();
fmalitab7425172014-08-26 07:56:44 -0700979 // follow the convention of recording a 1-based index
980 this->addInt(index + 1);
981}
982
reed@android.com8a1c16f2008-12-17 15:59:43 +0000983///////////////////////////////////////////////////////////////////////////////