blob: 2140795b3d660592d32ee89b13accfd89a812e6c [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,
669 const SkPaint* paint) {
670 // op + picture index
671 size_t size = 2 * kUInt32Size;
672 size_t initialOffset;
673
674 if (nullptr == matrix && nullptr == paint) {
675 initialOffset = this->addDraw(DRAW_PICTURE, &size);
676 this->addPicture(picture);
677 } else {
678 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
679 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
680 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
681 this->addPaintPtr(paint);
682 this->addMatrix(m);
683 this->addPicture(picture);
684 }
685 this->validate(initialOffset, size);
686}
687
msarett95416f42016-04-27 13:51:20 -0700688void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
689 // op + drawable index
690 size_t size = 2 * kUInt32Size;
691 size_t initialOffset;
692
693 if (nullptr == matrix) {
694 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
695 this->addDrawable(drawable);
696 } else {
697 size += matrix->writeToMemory(nullptr); // matrix
698 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
699 this->addMatrix(*matrix);
700 this->addDrawable(drawable);
701 }
702 this->validate(initialOffset, size);
703}
704
reed41af9662015-01-05 07:49:08 -0800705void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
706 const SkPoint vertices[], const SkPoint texs[],
707 const SkColor colors[], SkXfermode* xfer,
708 const uint16_t indices[], int indexCount,
709 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000710 uint32_t flags = 0;
711 if (texs) {
712 flags |= DRAW_VERTICES_HAS_TEXS;
713 }
714 if (colors) {
715 flags |= DRAW_VERTICES_HAS_COLORS;
716 }
717 if (indexCount > 0) {
718 flags |= DRAW_VERTICES_HAS_INDICES;
719 }
bsalomon49f085d2014-09-05 13:34:00 -0700720 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000721 SkXfermode::Mode mode;
722 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
723 flags |= DRAW_VERTICES_HAS_XFER;
724 }
725 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000726
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000727 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000728 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000729 if (flags & DRAW_VERTICES_HAS_TEXS) {
730 size += vertexCount * sizeof(SkPoint); // + uvs
731 }
732 if (flags & DRAW_VERTICES_HAS_COLORS) {
733 size += vertexCount * sizeof(SkColor); // + vert colors
734 }
735 if (flags & DRAW_VERTICES_HAS_INDICES) {
736 // + num indices + indices
737 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
738 }
reed@google.com85e143c2013-12-30 15:51:25 +0000739 if (flags & DRAW_VERTICES_HAS_XFER) {
740 size += kUInt32Size; // mode enum
741 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000742
robertphillips@google.com8b169312013-10-15 17:47:36 +0000743 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000744 this->addPaint(paint);
745 this->addInt(flags);
746 this->addInt(vmode);
747 this->addInt(vertexCount);
748 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000749 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000750 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000751 }
752 if (flags & DRAW_VERTICES_HAS_COLORS) {
753 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
754 }
755 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000756 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000757 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
758 }
reed@google.com85e143c2013-12-30 15:51:25 +0000759 if (flags & DRAW_VERTICES_HAS_XFER) {
760 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
761 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000762 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000763 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000764 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000765}
766
dandovb3c9d1c2014-08-12 08:34:29 -0700767void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
768 const SkPoint texCoords[4], SkXfermode* xmode,
769 const SkPaint& paint) {
770 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
771 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
772 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700773 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700774 flag |= DRAW_VERTICES_HAS_COLORS;
775 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
776 }
bsalomon49f085d2014-09-05 13:34:00 -0700777 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700778 flag |= DRAW_VERTICES_HAS_TEXS;
779 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
780 }
bsalomon49f085d2014-09-05 13:34:00 -0700781 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700782 SkXfermode::Mode mode;
783 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
784 flag |= DRAW_VERTICES_HAS_XFER;
785 size += kUInt32Size;
786 }
787 }
mtklein46616af2014-09-30 14:47:10 -0700788
dandov963137b2014-08-07 07:49:53 -0700789 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
dandov963137b2014-08-07 07:49:53 -0700790 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700791 this->addPatch(cubics);
792 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700793
dandovb3c9d1c2014-08-12 08:34:29 -0700794 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700795 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700796 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
797 }
bsalomon49f085d2014-09-05 13:34:00 -0700798 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700799 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
800 }
801 if (flag & DRAW_VERTICES_HAS_XFER) {
802 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
803 xmode->asMode(&mode);
804 this->addInt(mode);
805 }
dandov963137b2014-08-07 07:49:53 -0700806 this->validate(initialOffset, size);
807}
808
reed71c3c762015-06-24 10:29:17 -0700809void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
810 const SkColor colors[], int count, SkXfermode::Mode mode,
811 const SkRect* cull, const SkPaint* paint) {
812 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
813 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
814 uint32_t flags = 0;
815 if (colors) {
816 flags |= DRAW_ATLAS_HAS_COLORS;
817 size += count * sizeof(SkColor);
818 size += sizeof(uint32_t); // xfermode::mode
819 }
820 if (cull) {
821 flags |= DRAW_ATLAS_HAS_CULL;
822 size += sizeof(SkRect);
823 }
mtkleinc2e29772015-10-30 05:24:58 -0700824
reed71c3c762015-06-24 10:29:17 -0700825 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
reed71c3c762015-06-24 10:29:17 -0700826 this->addPaintPtr(paint);
827 this->addImage(atlas);
828 this->addInt(flags);
829 this->addInt(count);
830 fWriter.write(xform, count * sizeof(SkRSXform));
831 fWriter.write(tex, count * sizeof(SkRect));
832
833 // write optional parameters
834 if (colors) {
835 fWriter.write(colors, count * sizeof(SkColor));
836 this->addInt(mode);
837 }
838 if (cull) {
839 fWriter.write(cull, sizeof(SkRect));
840 }
841 this->validate(initialOffset, size);
842}
843
reedf70b5312016-03-04 16:36:20 -0800844void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
845 size_t keyLen = fWriter.WriteStringSize(key);
846 size_t valueLen = fWriter.WriteDataSize(value);
847 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
848
849 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
850 this->addRect(rect);
851 fWriter.writeString(key);
852 fWriter.writeData(value);
853 this->validate(initialOffset, size);
854}
855
reed@android.com8a1c16f2008-12-17 15:59:43 +0000856///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000857
reede8f30622016-03-23 18:59:25 -0700858sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700859 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000860}
861
reed871872f2015-06-22 12:48:26 -0700862void SkPictureRecord::addImage(const SkImage* image) {
863 int index = fImageRefs.find(image);
864 if (index >= 0) {
865 this->addInt(index);
866 } else {
867 *fImageRefs.append() = SkRef(image);
868 this->addInt(fImageRefs.count()-1);
869 }
870}
871
reed@android.com8a1c16f2008-12-17 15:59:43 +0000872void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000873 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000874}
875
mtklein46616af2014-09-30 14:47:10 -0700876void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700877 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000878
mtklein46616af2014-09-30 14:47:10 -0700879 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800880 fPaints.push_back(*paint);
881 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700882 } else {
883 this->addInt(0);
884 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000885}
886
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000887int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700888 if (int* n = fPaths.find(path)) {
889 return *n;
890 }
891 int n = fPaths.count() + 1; // 0 is reserved for null / error.
892 fPaths.set(path, n);
893 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000894}
895
896void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000897 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000898}
899
dandovb3c9d1c2014-08-12 08:34:29 -0700900void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
901 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700902}
903
robertphillips9b14f262014-06-04 05:40:44 -0700904void SkPictureRecord::addPicture(const SkPicture* picture) {
905 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000906 if (index < 0) { // not found
907 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700908 *fPictureRefs.append() = picture;
909 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000910 }
911 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000912 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000913}
914
msarett95416f42016-04-27 13:51:20 -0700915void SkPictureRecord::addDrawable(SkDrawable* drawable) {
916 int index = fDrawableRefs.find(drawable);
917 if (index < 0) { // not found
918 index = fDrawableRefs.count();
919 *fDrawableRefs.append() = drawable;
920 drawable->ref();
921 }
922 // follow the convention of recording a 1-based index
923 this->addInt(index + 1);
924}
925
reed@android.com8a1c16f2008-12-17 15:59:43 +0000926void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000927 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000928}
reed@google.com82065d62011-02-07 15:30:46 +0000929
reed@android.com8a1c16f2008-12-17 15:59:43 +0000930void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
931 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000932}
933
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000934void SkPictureRecord::addNoOp() {
935 size_t size = kUInt32Size; // op
936 this->addDraw(NOOP, &size);
937}
938
reed@android.com8a1c16f2008-12-17 15:59:43 +0000939void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000940 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000941}
942
943void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700944 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000945 fWriter.writeRect(*rect);
946 }
947}
948
reed@google.comf0b5e112011-09-07 11:57:34 +0000949void SkPictureRecord::addIRect(const SkIRect& rect) {
950 fWriter.write(&rect, sizeof(rect));
951}
952
reed@android.com8a1c16f2008-12-17 15:59:43 +0000953void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700954 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000955 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
956 }
957}
958
reed@google.com4ed0fb72012-12-12 20:48:18 +0000959void SkPictureRecord::addRRect(const SkRRect& rrect) {
960 fWriter.writeRRect(rrect);
961}
962
reed@android.com8a1c16f2008-12-17 15:59:43 +0000963void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000964 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000965}
966
967void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -0700968 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000969 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000970 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000971}
972
fmalitab7425172014-08-26 07:56:44 -0700973void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -0700974 int index = fTextBlobRefs.count();
975 *fTextBlobRefs.append() = blob;
976 blob->ref();
fmalitab7425172014-08-26 07:56:44 -0700977 // follow the convention of recording a 1-based index
978 this->addInt(index + 1);
979}
980
reed@android.com8a1c16f2008-12-17 15:59:43 +0000981///////////////////////////////////////////////////////////////////////////////