blob: 4cba3b067f2d2e1bd1d72853480785399ffdc60e [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
reed73603f32016-09-20 08:42:38 -0700233static bool clipOpExpands(SkCanvas::ClipOp op) {
reed@google.com45482d12011-08-29 19:02:39 +0000234 switch (op) {
reed73603f32016-09-20 08:42:38 -0700235 case SkCanvas::kUnion_Op:
236 case SkCanvas::kXOR_Op:
237 case SkCanvas::kReverseDifference_Op:
238 case SkCanvas::kReplace_Op:
reed@google.com45482d12011-08-29 19:02:39 +0000239 return true;
reed73603f32016-09-20 08:42:38 -0700240 case SkCanvas::kIntersect_Op:
241 case SkCanvas::kDifference_Op:
reed@google.com45482d12011-08-29 19:02:39 +0000242 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
reed73603f32016-09-20 08:42:38 -0700282size_t SkPictureRecord::recordRestoreOffsetPlaceholder(ClipOp 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
reed73603f32016-09-20 08:42:38 -0700294 if (clipOpExpands(op)) {
reed@google.com45482d12011-08-29 19:02:39 +0000295 // 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
reed73603f32016-09-20 08:42:38 -0700312void SkPictureRecord::onClipRect(const SkRect& rect, SkCanvas::ClipOp 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
reed73603f32016-09-20 08:42:38 -0700317size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkCanvas::ClipOp 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
reed73603f32016-09-20 08:42:38 -0700334void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkCanvas::ClipOp 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
reed73603f32016-09-20 08:42:38 -0700339size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkCanvas::ClipOp 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
reed73603f32016-09-20 08:42:38 -0700355void SkPictureRecord::onClipPath(const SkPath& path, SkCanvas::ClipOp 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
reed73603f32016-09-20 08:42:38 -0700361size_t SkPictureRecord::recordClipPath(int pathID, SkCanvas::ClipOp 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
reed73603f32016-09-20 08:42:38 -0700377void SkPictureRecord::onClipRegion(const SkRegion& region, ClipOp 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
reed73603f32016-09-20 08:42:38 -0700382size_t SkPictureRecord::recordClipRegion(const SkRegion& region, ClipOp op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000383 // op + clip params + region
halcanary96fcdcc2015-08-27 07:41:13 -0700384 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000385 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000386 if (!fRestoreOffsetStack.isEmpty()) {
387 // + restore offset
388 size += kUInt32Size;
389 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000390 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000391 this->addRegion(region);
392 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000393 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000394
robertphillips@google.com8b169312013-10-15 17:47:36 +0000395 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000396 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000397}
398
reed41af9662015-01-05 07:49:08 -0800399void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000400 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000401 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000402 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000403 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000404 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000405}
406
reed41af9662015-01-05 07:49:08 -0800407void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
408 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700409 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000410
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000411 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000412 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000413 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000414 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700415
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000416 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000417 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000419 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000420}
421
reed41af9662015-01-05 07:49:08 -0800422void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000423 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000424 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000425 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000426 this->addPaint(paint);
427 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000428 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000429}
430
bsalomonac3aa242016-08-19 11:25:19 -0700431void SkPictureRecord::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
432 bool useCenter, const SkPaint& paint) {
433 // op + paint index + rect + start + sweep + bool (as int)
434 size_t size = 2 * kUInt32Size + sizeof(oval) + sizeof(startAngle) + sizeof(sweepAngle) +
435 sizeof(int);
436 size_t initialOffset = this->addDraw(DRAW_ARC, &size);
437 this->addPaint(paint);
438 this->addRect(oval);
439 this->addScalar(startAngle);
440 this->addScalar(sweepAngle);
441 this->addInt(useCenter);
442 this->validate(initialOffset, size);
443}
444
reed41af9662015-01-05 07:49:08 -0800445void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000446 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000447 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000448 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000449 this->addPaint(paint);
450 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000451 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000452}
453
msarett44df6512016-08-25 13:54:30 -0700454void SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
455 // op + paint index + region
456 size_t regionBytes = region.writeToMemory(nullptr);
457 size_t size = 2 * kUInt32Size + regionBytes;
458 size_t initialOffset = this->addDraw(DRAW_REGION, &size);
459 this->addPaint(paint);
460 fWriter.writeRegion(region);
461 this->validate(initialOffset, size);
462}
463
reed41af9662015-01-05 07:49:08 -0800464void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700465 // op + paint index + rrect
466 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
467 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein46616af2014-09-30 14:47:10 -0700468 this->addPaint(paint);
469 this->addRRect(rrect);
470 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000471}
472
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000473void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
474 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000475 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000476 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
477 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000478 this->addPaint(paint);
479 this->addRRect(outer);
480 this->addRRect(inner);
481 this->validate(initialOffset, size);
482}
483
reed41af9662015-01-05 07:49:08 -0800484void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700485 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000486
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000487 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000488 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000489 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000490 this->addPaint(paint);
491 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000492 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000493}
494
reeda85d4d02015-05-06 12:56:48 -0700495void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
496 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700497 // op + paint_index + image_index + x + y
498 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
499 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
reed871872f2015-06-22 12:48:26 -0700500 this->addPaintPtr(paint);
501 this->addImage(image);
502 this->addScalar(x);
503 this->addScalar(y);
504 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700505}
506
507void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700508 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700509 // id + paint_index + image_index + bool_for_src + constraint
510 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700511 if (src) {
512 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700513 }
reed871872f2015-06-22 12:48:26 -0700514 size += sizeof(dst); // + rect
mtkleinc2e29772015-10-30 05:24:58 -0700515
reed871872f2015-06-22 12:48:26 -0700516 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
reed871872f2015-06-22 12:48:26 -0700517 this->addPaintPtr(paint);
518 this->addImage(image);
519 this->addRectPtr(src); // may be null
520 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700521 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700522 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700523}
524
reed4c21dc52015-06-25 12:32:03 -0700525void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
526 const SkPaint* paint) {
527 // id + paint_index + image_index + center + dst
528 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
mtkleinc2e29772015-10-30 05:24:58 -0700529
reed4c21dc52015-06-25 12:32:03 -0700530 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
reed4c21dc52015-06-25 12:32:03 -0700531 this->addPaintPtr(paint);
532 this->addImage(img);
533 this->addIRect(center);
534 this->addRect(dst);
535 this->validate(initialOffset, size);
536}
537
msarett16882062016-08-16 09:31:08 -0700538void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
539 const SkRect& dst, const SkPaint* paint) {
540 // xCount + xDivs + yCount+ yDivs
msarett0764efe2016-09-02 11:24:30 -0700541 int flagCount = (nullptr == lattice.fFlags) ? 0 : (lattice.fXCount + 1) * (lattice.fYCount + 1);
542 size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size +
543 SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags));
msarett16882062016-08-16 09:31:08 -0700544
545 // op + paint index + image index + lattice + dst rect
546 size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
547 size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
548 this->addPaintPtr(paint);
549 this->addImage(image);
550 this->addInt(lattice.fXCount);
551 fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
552 this->addInt(lattice.fYCount);
553 fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
msarett0764efe2016-09-02 11:24:30 -0700554 this->addInt(flagCount);
555 fWriter.writePad(lattice.fFlags, flagCount * sizeof(SkCanvas::Lattice::Flags));
msarett16882062016-08-16 09:31:08 -0700556 this->addRect(dst);
557 this->validate(initialOffset, size);
558}
559
reed@google.come0d9ce82014-04-23 04:00:17 +0000560void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
561 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000562 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000563 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000564
mtklein46616af2014-09-30 14:47:10 -0700565 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000566 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700567 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000568 this->addText(text, byteLength);
569 this->addScalar(x);
570 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000571 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000572}
573
reed@google.come0d9ce82014-04-23 04:00:17 +0000574void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
575 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000576 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000577
mtklein46616af2014-09-30 14:47:10 -0700578 // op + paint index + length + 'length' worth of data + num points + x&y point data
579 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000580
mtklein46616af2014-09-30 14:47:10 -0700581 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000582
robertphillips@google.com8b169312013-10-15 17:47:36 +0000583 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700584 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000585 this->addText(text, byteLength);
586 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700587 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000588 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000589}
590
reed@google.come0d9ce82014-04-23 04:00:17 +0000591void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
592 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000593 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000594
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000595 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000596 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000597 // + y + the actual points
598 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000599
mtklein46616af2014-09-30 14:47:10 -0700600 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
601 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000602 this->addText(text, byteLength);
603 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000604 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000605 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000606 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000607}
608
reed@google.come0d9ce82014-04-23 04:00:17 +0000609void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
610 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000611 // op + paint index + length + 'length' worth of data + path index + matrix
612 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700613 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000614 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000615 this->addPaint(paint);
616 this->addText(text, byteLength);
617 this->addPath(path);
618 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000619 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000620}
621
reed45561a02016-07-07 12:47:17 -0700622void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
623 const SkRSXform xform[], const SkRect* cull,
624 const SkPaint& paint) {
625 const int count = paint.countText(text, byteLength);
626 // [op + paint-index + count + flags + length] + [text] + [xform] + cull
627 size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
628 uint32_t flags = 0;
629 if (cull) {
630 flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
631 size += sizeof(SkRect);
632 }
633
634 size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
635 this->addPaint(paint);
636 this->addInt(count);
637 this->addInt(flags);
638 this->addText(text, byteLength);
639 fWriter.write(xform, count * sizeof(SkRSXform));
640 if (cull) {
641 fWriter.write(cull, sizeof(SkRect));
642 }
643 this->validate(initialOffset, size);
644}
645
fmalitab7425172014-08-26 07:56:44 -0700646void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
647 const SkPaint& paint) {
648
649 // op + paint index + blob index + x/y
650 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
651 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
fmalitab7425172014-08-26 07:56:44 -0700652
653 this->addPaint(paint);
654 this->addTextBlob(blob);
655 this->addScalar(x);
656 this->addScalar(y);
657
658 this->validate(initialOffset, size);
659}
660
reedd5fa1a42014-08-09 11:08:05 -0700661void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
662 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000663 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000664 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700665 size_t initialOffset;
666
halcanary96fcdcc2015-08-27 07:41:13 -0700667 if (nullptr == matrix && nullptr == paint) {
reedd5fa1a42014-08-09 11:08:05 -0700668 initialOffset = this->addDraw(DRAW_PICTURE, &size);
669 this->addPicture(picture);
670 } else {
671 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700672 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
reedd5fa1a42014-08-09 11:08:05 -0700673 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
reedd5fa1a42014-08-09 11:08:05 -0700674 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700675 this->addMatrix(m);
676 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700677 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000678 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000679}
680
vjiaoblack95302da2016-07-21 10:25:54 -0700681void SkPictureRecord::onDrawShadowedPicture(const SkPicture* picture,
682 const SkMatrix* matrix,
vjiaoblacke6f5d562016-08-25 06:30:23 -0700683 const SkPaint* paint,
684 const SkShadowParams& params) {
vjiaoblack95302da2016-07-21 10:25:54 -0700685 // op + picture index
686 size_t size = 2 * kUInt32Size;
687 size_t initialOffset;
688
vjiaoblacke6f5d562016-08-25 06:30:23 -0700689 // TODO: handle recording params.
vjiaoblack95302da2016-07-21 10:25:54 -0700690 if (nullptr == matrix && nullptr == paint) {
691 initialOffset = this->addDraw(DRAW_PICTURE, &size);
692 this->addPicture(picture);
693 } else {
694 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
695 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
696 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
697 this->addPaintPtr(paint);
698 this->addMatrix(m);
699 this->addPicture(picture);
700 }
701 this->validate(initialOffset, size);
702}
703
msarett95416f42016-04-27 13:51:20 -0700704void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
705 // op + drawable index
706 size_t size = 2 * kUInt32Size;
707 size_t initialOffset;
708
709 if (nullptr == matrix) {
710 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
711 this->addDrawable(drawable);
712 } else {
713 size += matrix->writeToMemory(nullptr); // matrix
714 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
715 this->addMatrix(*matrix);
716 this->addDrawable(drawable);
717 }
718 this->validate(initialOffset, size);
719}
720
reed41af9662015-01-05 07:49:08 -0800721void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
722 const SkPoint vertices[], const SkPoint texs[],
723 const SkColor colors[], SkXfermode* xfer,
724 const uint16_t indices[], int indexCount,
725 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000726 uint32_t flags = 0;
727 if (texs) {
728 flags |= DRAW_VERTICES_HAS_TEXS;
729 }
730 if (colors) {
731 flags |= DRAW_VERTICES_HAS_COLORS;
732 }
733 if (indexCount > 0) {
734 flags |= DRAW_VERTICES_HAS_INDICES;
735 }
bsalomon49f085d2014-09-05 13:34:00 -0700736 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000737 SkXfermode::Mode mode;
738 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
739 flags |= DRAW_VERTICES_HAS_XFER;
740 }
741 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000742
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000743 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000744 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000745 if (flags & DRAW_VERTICES_HAS_TEXS) {
746 size += vertexCount * sizeof(SkPoint); // + uvs
747 }
748 if (flags & DRAW_VERTICES_HAS_COLORS) {
749 size += vertexCount * sizeof(SkColor); // + vert colors
750 }
751 if (flags & DRAW_VERTICES_HAS_INDICES) {
752 // + num indices + indices
753 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
754 }
reed@google.com85e143c2013-12-30 15:51:25 +0000755 if (flags & DRAW_VERTICES_HAS_XFER) {
756 size += kUInt32Size; // mode enum
757 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000758
robertphillips@google.com8b169312013-10-15 17:47:36 +0000759 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000760 this->addPaint(paint);
761 this->addInt(flags);
762 this->addInt(vmode);
763 this->addInt(vertexCount);
764 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000765 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000766 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000767 }
768 if (flags & DRAW_VERTICES_HAS_COLORS) {
769 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
770 }
771 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000772 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000773 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
774 }
reed@google.com85e143c2013-12-30 15:51:25 +0000775 if (flags & DRAW_VERTICES_HAS_XFER) {
776 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
777 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000778 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000779 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000780 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000781}
782
dandovb3c9d1c2014-08-12 08:34:29 -0700783void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
784 const SkPoint texCoords[4], SkXfermode* xmode,
785 const SkPaint& paint) {
786 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
787 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
788 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700789 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700790 flag |= DRAW_VERTICES_HAS_COLORS;
791 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
792 }
bsalomon49f085d2014-09-05 13:34:00 -0700793 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700794 flag |= DRAW_VERTICES_HAS_TEXS;
795 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
796 }
bsalomon49f085d2014-09-05 13:34:00 -0700797 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700798 SkXfermode::Mode mode;
799 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
800 flag |= DRAW_VERTICES_HAS_XFER;
801 size += kUInt32Size;
802 }
803 }
mtklein46616af2014-09-30 14:47:10 -0700804
dandov963137b2014-08-07 07:49:53 -0700805 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
dandov963137b2014-08-07 07:49:53 -0700806 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700807 this->addPatch(cubics);
808 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700809
dandovb3c9d1c2014-08-12 08:34:29 -0700810 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700811 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700812 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
813 }
bsalomon49f085d2014-09-05 13:34:00 -0700814 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700815 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
816 }
817 if (flag & DRAW_VERTICES_HAS_XFER) {
818 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
819 xmode->asMode(&mode);
820 this->addInt(mode);
821 }
dandov963137b2014-08-07 07:49:53 -0700822 this->validate(initialOffset, size);
823}
824
reed71c3c762015-06-24 10:29:17 -0700825void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
826 const SkColor colors[], int count, SkXfermode::Mode mode,
827 const SkRect* cull, const SkPaint* paint) {
828 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
829 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
830 uint32_t flags = 0;
831 if (colors) {
832 flags |= DRAW_ATLAS_HAS_COLORS;
833 size += count * sizeof(SkColor);
834 size += sizeof(uint32_t); // xfermode::mode
835 }
836 if (cull) {
837 flags |= DRAW_ATLAS_HAS_CULL;
838 size += sizeof(SkRect);
839 }
mtkleinc2e29772015-10-30 05:24:58 -0700840
reed71c3c762015-06-24 10:29:17 -0700841 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
reed71c3c762015-06-24 10:29:17 -0700842 this->addPaintPtr(paint);
843 this->addImage(atlas);
844 this->addInt(flags);
845 this->addInt(count);
846 fWriter.write(xform, count * sizeof(SkRSXform));
847 fWriter.write(tex, count * sizeof(SkRect));
848
849 // write optional parameters
850 if (colors) {
851 fWriter.write(colors, count * sizeof(SkColor));
852 this->addInt(mode);
853 }
854 if (cull) {
855 fWriter.write(cull, sizeof(SkRect));
856 }
857 this->validate(initialOffset, size);
858}
859
reedf70b5312016-03-04 16:36:20 -0800860void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
861 size_t keyLen = fWriter.WriteStringSize(key);
862 size_t valueLen = fWriter.WriteDataSize(value);
863 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
864
865 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
866 this->addRect(rect);
867 fWriter.writeString(key);
868 fWriter.writeData(value);
869 this->validate(initialOffset, size);
870}
871
reed@android.com8a1c16f2008-12-17 15:59:43 +0000872///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000873
reed22b2af12016-08-29 07:52:13 -0700874template <typename T> int find_or_append_uniqueID(SkTDArray<const T*>& array, const T* obj) {
875 int index = array.select([&](const T* elem) {
876 return elem->uniqueID() == obj->uniqueID();
877 });
878 if (index < 0) {
879 index = array.count();
880 *array.append() = SkRef(obj);
881 }
882 return index;
883}
884
reede8f30622016-03-23 18:59:25 -0700885sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700886 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000887}
888
reed871872f2015-06-22 12:48:26 -0700889void SkPictureRecord::addImage(const SkImage* image) {
reed22b2af12016-08-29 07:52:13 -0700890 // convention for images is 0-based index
891 this->addInt(find_or_append_uniqueID(fImageRefs, image));
reed871872f2015-06-22 12:48:26 -0700892}
893
reed@android.com8a1c16f2008-12-17 15:59:43 +0000894void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000895 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000896}
897
mtklein46616af2014-09-30 14:47:10 -0700898void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700899 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000900
mtklein46616af2014-09-30 14:47:10 -0700901 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800902 fPaints.push_back(*paint);
903 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700904 } else {
905 this->addInt(0);
906 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000907}
908
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000909int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700910 if (int* n = fPaths.find(path)) {
911 return *n;
912 }
913 int n = fPaths.count() + 1; // 0 is reserved for null / error.
914 fPaths.set(path, n);
915 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000916}
917
918void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000919 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000920}
921
dandovb3c9d1c2014-08-12 08:34:29 -0700922void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
923 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700924}
925
robertphillips9b14f262014-06-04 05:40:44 -0700926void SkPictureRecord::addPicture(const SkPicture* picture) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000927 // follow the convention of recording a 1-based index
reed22b2af12016-08-29 07:52:13 -0700928 this->addInt(find_or_append_uniqueID(fPictureRefs, picture) + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000929}
930
msarett95416f42016-04-27 13:51:20 -0700931void SkPictureRecord::addDrawable(SkDrawable* drawable) {
932 int index = fDrawableRefs.find(drawable);
933 if (index < 0) { // not found
934 index = fDrawableRefs.count();
935 *fDrawableRefs.append() = drawable;
936 drawable->ref();
937 }
938 // follow the convention of recording a 1-based index
939 this->addInt(index + 1);
940}
941
reed@android.com8a1c16f2008-12-17 15:59:43 +0000942void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000943 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000944}
reed@google.com82065d62011-02-07 15:30:46 +0000945
reed@android.com8a1c16f2008-12-17 15:59:43 +0000946void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
947 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000948}
949
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000950void SkPictureRecord::addNoOp() {
951 size_t size = kUInt32Size; // op
952 this->addDraw(NOOP, &size);
953}
954
reed@android.com8a1c16f2008-12-17 15:59:43 +0000955void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000956 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000957}
958
959void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700960 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000961 fWriter.writeRect(*rect);
962 }
963}
964
reed@google.comf0b5e112011-09-07 11:57:34 +0000965void SkPictureRecord::addIRect(const SkIRect& rect) {
966 fWriter.write(&rect, sizeof(rect));
967}
968
reed@android.com8a1c16f2008-12-17 15:59:43 +0000969void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700970 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000971 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
972 }
973}
974
reed@google.com4ed0fb72012-12-12 20:48:18 +0000975void SkPictureRecord::addRRect(const SkRRect& rrect) {
976 fWriter.writeRRect(rrect);
977}
978
reed@android.com8a1c16f2008-12-17 15:59:43 +0000979void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000980 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000981}
982
983void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -0700984 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000985 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000986 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000987}
988
reed22b2af12016-08-29 07:52:13 -0700989void SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
fmalitab7425172014-08-26 07:56:44 -0700990 // follow the convention of recording a 1-based index
reed22b2af12016-08-29 07:52:13 -0700991 this->addInt(find_or_append_uniqueID(fTextBlobRefs, blob) + 1);
fmalitab7425172014-08-26 07:56:44 -0700992}
993
reed@android.com8a1c16f2008-12-17 15:59:43 +0000994///////////////////////////////////////////////////////////////////////////////