blob: d179b06438cb8163f61f547e39534822fad8fa6a [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"
Hal Canaryc640d0d2018-06-13 09:59:02 -04009
Mike Reed7c9c9e42018-01-03 09:23:34 -050010#include "SkCanvasPriv.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040011#include "SkClipOpPriv.h"
Jim Van Verth1af03d42017-07-31 09:34:58 -040012#include "SkDrawShadowInfo.h"
reeda85d4d02015-05-06 12:56:48 -070013#include "SkImage_Base.h"
Cary Clark6d6d6032017-10-20 12:14:33 -040014#include "SkMatrixPriv.h"
dandovb3c9d1c2014-08-12 08:34:29 -070015#include "SkPatchUtils.h"
dandovb3c9d1c2014-08-12 08:34:29 -070016#include "SkRRect.h"
reed71c3c762015-06-24 10:29:17 -070017#include "SkRSXform.h"
Hal Canaryfdcfb8b2018-06-13 09:42:32 -040018#include "SkTSearch.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040019#include "SkTextBlob.h"
20#include "SkTo.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000021
reed@android.com8a1c16f2008-12-17 15:59:43 +000022#define HEAP_BLOCK_SIZE 4096
23
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000024enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000025 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000026 kNoInitialSave = -1,
27};
28
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000029// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
30static int const kUInt32Size = 4;
31
robertphillips0bdbea72014-06-11 11:37:55 -070032SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000033 : INHERITED(dimensions.width(), dimensions.height())
mtklein71a23632014-11-12 10:24:55 -080034 , fRecordFlags(flags)
35 , fInitialSaveCount(kNoInitialSave) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000036}
37
reed@android.com8a1c16f2008-12-17 15:59:43 +000038///////////////////////////////////////////////////////////////////////////////
39
Mike Klein7cc49d62017-08-14 10:39:28 -040040void SkPictureRecord::onFlush() {
41 size_t size = sizeof(kUInt32Size);
42 size_t initialOffset = this->addDraw(FLUSH, &size);
43 this->validate(initialOffset, size);
44}
45
Florin Malita5f6102d2014-06-30 10:13:28 -040046void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +000047 // record the offset to us, making it non-positive to distinguish a save
48 // from a clip entry.
Mike Reed5edcd312018-08-08 11:23:41 -040049 fRestoreOffsetStack.push_back(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -040050 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000051
Florin Malita5f6102d2014-06-30 10:13:28 -040052 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +000053}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +000054
Florin Malita5f6102d2014-06-30 10:13:28 -040055void SkPictureRecord::recordSave() {
56 // op only
reed512f3e32016-01-04 14:11:31 -080057 size_t size = sizeof(kUInt32Size);
robertphillips@google.com8b169312013-10-15 17:47:36 +000058 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +000059
robertphillips@google.com8b169312013-10-15 17:47:36 +000060 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +000061}
62
reed4960eee2015-12-18 07:09:18 -080063SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
reed@google.comffacd3c2012-08-30 15:31:23 +000064 // record the offset to us, making it non-positive to distinguish a save
65 // from a clip entry.
Mike Reed5edcd312018-08-08 11:23:41 -040066 fRestoreOffsetStack.push_back(-(int32_t)fWriter.bytesWritten());
reed4960eee2015-12-18 07:09:18 -080067 this->recordSaveLayer(rec);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +000068
reed4960eee2015-12-18 07:09:18 -080069 (void)this->INHERITED::getSaveLayerStrategy(rec);
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000070 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +000071 at this time (and may not be able to afford since during record our
72 clip starts out the size of the picture, which is often much larger
73 than the size of the actual device we'll use during playback).
74 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000075 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +000076}
77
Mike Reed148b7fd2018-12-18 17:38:18 -050078bool SkPictureRecord::onDoSaveBehind(const SkRect* subset) {
79 fRestoreOffsetStack.push_back(-(int32_t)fWriter.bytesWritten());
80
81 size_t size = sizeof(kUInt32Size) + sizeof(uint32_t); // op + flags
82 uint32_t flags = 0;
83 if (subset) {
84 flags |= SAVEBEHIND_HAS_SUBSET;
85 size += sizeof(*subset);
86 }
87
88 size_t initialOffset = this->addDraw(SAVE_BEHIND, &size);
89 this->addInt(flags);
90 if (subset) {
91 this->addRect(*subset);
92 }
93
94 this->validate(initialOffset, size);
95 return false;
96}
97
reed4960eee2015-12-18 07:09:18 -080098void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
reedbfd5f172016-01-07 11:28:08 -080099 // op + flatflags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000100 size_t size = 2 * kUInt32Size;
reedbfd5f172016-01-07 11:28:08 -0800101 uint32_t flatFlags = 0;
102
reed4960eee2015-12-18 07:09:18 -0800103 if (rec.fBounds) {
reedbfd5f172016-01-07 11:28:08 -0800104 flatFlags |= SAVELAYERREC_HAS_BOUNDS;
105 size += sizeof(*rec.fBounds);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000106 }
reedbfd5f172016-01-07 11:28:08 -0800107 if (rec.fPaint) {
108 flatFlags |= SAVELAYERREC_HAS_PAINT;
109 size += sizeof(uint32_t); // index
110 }
111 if (rec.fBackdrop) {
112 flatFlags |= SAVELAYERREC_HAS_BACKDROP;
113 size += sizeof(uint32_t); // (paint) index
114 }
115 if (rec.fSaveLayerFlags) {
116 flatFlags |= SAVELAYERREC_HAS_FLAGS;
117 size += sizeof(uint32_t);
118 }
Florin Malita53f77bd2017-04-28 13:48:37 -0400119 if (rec.fClipMask) {
120 flatFlags |= SAVELAYERREC_HAS_CLIPMASK;
121 size += sizeof(uint32_t); // clip image index
122 }
123 if (rec.fClipMatrix) {
124 flatFlags |= SAVELAYERREC_HAS_CLIPMATRIX;
Cary Clark6d6d6032017-10-20 12:14:33 -0400125 size += SkMatrixPriv::WriteToMemory(*rec.fClipMatrix, nullptr);
Florin Malita53f77bd2017-04-28 13:48:37 -0400126 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000127
reedbfd5f172016-01-07 11:28:08 -0800128 const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
129 this->addInt(flatFlags);
130 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
131 this->addRect(*rec.fBounds);
132 }
133 if (flatFlags & SAVELAYERREC_HAS_PAINT) {
134 this->addPaintPtr(rec.fPaint);
135 }
136 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
137 // overkill, but we didn't already track single flattenables, so using a paint for that
138 SkPaint paint;
Mike Reed5e257172016-11-01 11:22:05 -0400139 paint.setImageFilter(sk_ref_sp(const_cast<SkImageFilter*>(rec.fBackdrop)));
reedbfd5f172016-01-07 11:28:08 -0800140 this->addPaint(paint);
141 }
142 if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
143 this->addInt(rec.fSaveLayerFlags);
144 }
Florin Malita53f77bd2017-04-28 13:48:37 -0400145 if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
Mike Kleinb34ab042017-05-01 21:34:14 +0000146 this->addImage(rec.fClipMask);
Florin Malita53f77bd2017-04-28 13:48:37 -0400147 }
148 if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
149 this->addMatrix(*rec.fClipMatrix);
150 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000151 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152}
153
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000154#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000155/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000156 * Read the op code from 'offset' in 'writer' and extract the size too.
157 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000158static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000159 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000160
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000161 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000162 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000163 if (MASK_24 == *size) {
164 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000165 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000166 }
167 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000168}
mtklein46616af2014-09-30 14:47:10 -0700169#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000170
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000171void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000172#if 0
173 SkASSERT(fRestoreOffsetStack.count() > 1);
174#endif
175
reed@android.comb4e22d62009-07-09 15:20:25 +0000176 // check for underflow
177 if (fRestoreOffsetStack.count() == 0) {
178 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000180
mtklein46616af2014-09-30 14:47:10 -0700181 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000182
reed@android.comb4e22d62009-07-09 15:20:25 +0000183 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000184
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000185 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186}
187
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000188void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000189 if (fillInSkips) {
190 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
191 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000192 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
193 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000194 this->validate(initialOffset, size);
195}
196
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000197void SkPictureRecord::recordTranslate(const SkMatrix& m) {
198 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
199
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000200 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000201 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000202 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000203 this->addScalar(m.getTranslateX());
204 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000205 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000206}
207
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000208void SkPictureRecord::recordScale(const SkMatrix& m) {
209 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000210
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000211 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000212 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000213 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000214 this->addScalar(m.getScaleX());
215 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000216 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000217}
218
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000219void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000220 switch (matrix.getType()) {
221 case SkMatrix::kTranslate_Mask:
222 this->recordTranslate(matrix);
223 break;
224 case SkMatrix::kScale_Mask:
225 this->recordScale(matrix);
226 break;
227 default:
228 this->recordConcat(matrix);
229 break;
230 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000231 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000232}
233
234void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000235 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000236 // op + matrix
Cary Clark6d6d6032017-10-20 12:14:33 -0400237 size_t size = kUInt32Size + SkMatrixPriv::WriteToMemory(matrix, nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000238 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000239 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000240 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000241}
242
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000243void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000244 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000245 // op + matrix
Cary Clark6d6d6032017-10-20 12:14:33 -0400246 size_t size = kUInt32Size + SkMatrixPriv::WriteToMemory(matrix, nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000247 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000248 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000249 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000250 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000251}
252
Mike Reedc1f77742016-12-09 09:00:50 -0500253static bool clipOpExpands(SkClipOp op) {
reed@google.com45482d12011-08-29 19:02:39 +0000254 switch (op) {
Mike Reedc1f77742016-12-09 09:00:50 -0500255 case kUnion_SkClipOp:
256 case kXOR_SkClipOp:
257 case kReverseDifference_SkClipOp:
258 case kReplace_SkClipOp:
reed@google.com45482d12011-08-29 19:02:39 +0000259 return true;
Mike Reedc1f77742016-12-09 09:00:50 -0500260 case kIntersect_SkClipOp:
261 case kDifference_SkClipOp:
reed@google.com45482d12011-08-29 19:02:39 +0000262 return false;
263 default:
Mike Reedc1f77742016-12-09 09:00:50 -0500264 SkDEBUGFAIL("unknown clipop");
reed@google.com45482d12011-08-29 19:02:39 +0000265 return false;
266 }
267}
268
robertphillips@google.come37ad352013-03-01 19:44:30 +0000269void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000270 int32_t offset = fRestoreOffsetStack.top();
271 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000272 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
273 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000274 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000275 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000276
reed@google.comffacd3c2012-08-30 15:31:23 +0000277#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800278 // offset of 0 has been disabled, so we skip it
279 if (offset > 0) {
280 // assert that the final offset value points to a save verb
281 uint32_t opSize;
282 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
reedbfd5f172016-01-07 11:28:08 -0800283 SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
reed2ff1fce2014-12-11 07:07:37 -0800284 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000285#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000286}
287
reed@google.comd86e7ab2012-09-27 20:31:31 +0000288void SkPictureRecord::beginRecording() {
289 // we have to call this *after* our constructor, to ensure that it gets
290 // recorded. This is balanced by restoreToCount() call from endRecording,
291 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000292 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000293}
294
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000295void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000296 SkASSERT(kNoInitialSave != fInitialSaveCount);
297 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000298}
299
Mike Reedc1f77742016-12-09 09:00:50 -0500300size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkClipOp op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000301 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000302 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000303 }
304
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000305 // The RestoreOffset field is initially filled with a placeholder
306 // value that points to the offset of the previous RestoreOffset
307 // in the current stack level, thus forming a linked list so that
308 // the restore offsets can be filled in when the corresponding
309 // restore command is recorded.
310 int32_t prevOffset = fRestoreOffsetStack.top();
311
reed73603f32016-09-20 08:42:38 -0700312 if (clipOpExpands(op)) {
reed@google.com45482d12011-08-29 19:02:39 +0000313 // Run back through any previous clip ops, and mark their offset to
314 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
315 // they could hide this clips ability to expand the clip (i.e. go from
316 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000317 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000318
319 // Reset the pointer back to the previous clip so that subsequent
320 // restores don't overwrite the offsets we just cleared.
321 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000322 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000323
reed@google.com44699382013-10-31 17:28:30 +0000324 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000325 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000326 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000327 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000328}
329
Mike Reedc1f77742016-12-09 09:00:50 -0500330void SkPictureRecord::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000331 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000332 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000333}
334
Mike Reedc1f77742016-12-09 09:00:50 -0500335size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkClipOp op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000336 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000337 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000338 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000339 if (!fRestoreOffsetStack.isEmpty()) {
340 // + restore offset
341 size += kUInt32Size;
342 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000343 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000344 this->addRect(rect);
345 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000346 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000347
robertphillips@google.com8b169312013-10-15 17:47:36 +0000348 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000349 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000350}
351
Mike Reedc1f77742016-12-09 09:00:50 -0500352void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000353 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700354 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000355}
356
Mike Reedc1f77742016-12-09 09:00:50 -0500357size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000358 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000359 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000360 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000361 if (!fRestoreOffsetStack.isEmpty()) {
362 // + restore offset
363 size += kUInt32Size;
364 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000365 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000366 this->addRRect(rrect);
367 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000368 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000369 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000370 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000371}
372
Mike Reedc1f77742016-12-09 09:00:50 -0500373void SkPictureRecord::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000374 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000375 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700376 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000377}
378
Mike Reedc1f77742016-12-09 09:00:50 -0500379size_t SkPictureRecord::recordClipPath(int pathID, SkClipOp op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000380 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000381 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000382 // recordRestoreOffsetPlaceholder doesn't always write an offset
383 if (!fRestoreOffsetStack.isEmpty()) {
384 // + restore offset
385 size += kUInt32Size;
386 }
387 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000388 this->addInt(pathID);
389 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000390 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000391 this->validate(initialOffset, size);
392 return offset;
393}
394
Mike Reedc1f77742016-12-09 09:00:50 -0500395void SkPictureRecord::onClipRegion(const SkRegion& region, SkClipOp op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000396 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000397 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000398}
399
Mike Reedc1f77742016-12-09 09:00:50 -0500400size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkClipOp op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000401 // op + clip params + region
halcanary96fcdcc2015-08-27 07:41:13 -0700402 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000403 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000404 if (!fRestoreOffsetStack.isEmpty()) {
405 // + restore offset
406 size += kUInt32Size;
407 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000408 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000409 this->addRegion(region);
410 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000411 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000412
robertphillips@google.com8b169312013-10-15 17:47:36 +0000413 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000414 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000415}
416
reed41af9662015-01-05 07:49:08 -0800417void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000418 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000419 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000420 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000421 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000422 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000423}
424
reed41af9662015-01-05 07:49:08 -0800425void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
426 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000427 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000428 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000429 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000430 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700431
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000432 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000433 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000434 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000435 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000436}
437
reed41af9662015-01-05 07:49:08 -0800438void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000439 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000440 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000441 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000442 this->addPaint(paint);
443 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000444 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000445}
446
bsalomonac3aa242016-08-19 11:25:19 -0700447void SkPictureRecord::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
448 bool useCenter, const SkPaint& paint) {
449 // op + paint index + rect + start + sweep + bool (as int)
450 size_t size = 2 * kUInt32Size + sizeof(oval) + sizeof(startAngle) + sizeof(sweepAngle) +
451 sizeof(int);
452 size_t initialOffset = this->addDraw(DRAW_ARC, &size);
453 this->addPaint(paint);
454 this->addRect(oval);
455 this->addScalar(startAngle);
456 this->addScalar(sweepAngle);
457 this->addInt(useCenter);
458 this->validate(initialOffset, size);
459}
460
reed41af9662015-01-05 07:49:08 -0800461void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000462 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000463 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000464 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000465 this->addPaint(paint);
466 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000467 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000468}
469
msarett44df6512016-08-25 13:54:30 -0700470void SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
471 // op + paint index + region
472 size_t regionBytes = region.writeToMemory(nullptr);
473 size_t size = 2 * kUInt32Size + regionBytes;
474 size_t initialOffset = this->addDraw(DRAW_REGION, &size);
475 this->addPaint(paint);
476 fWriter.writeRegion(region);
477 this->validate(initialOffset, size);
478}
479
reed41af9662015-01-05 07:49:08 -0800480void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700481 // op + paint index + rrect
482 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
483 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein46616af2014-09-30 14:47:10 -0700484 this->addPaint(paint);
485 this->addRRect(rrect);
486 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000487}
488
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000489void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
490 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000491 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000492 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
493 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000494 this->addPaint(paint);
495 this->addRRect(outer);
496 this->addRRect(inner);
497 this->validate(initialOffset, size);
498}
499
reed41af9662015-01-05 07:49:08 -0800500void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000501 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000502 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000503 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000504 this->addPaint(paint);
505 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000506 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000507}
508
reeda85d4d02015-05-06 12:56:48 -0700509void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
510 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700511 // op + paint_index + image_index + x + y
512 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
513 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
reed871872f2015-06-22 12:48:26 -0700514 this->addPaintPtr(paint);
515 this->addImage(image);
516 this->addScalar(x);
517 this->addScalar(y);
518 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700519}
520
521void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700522 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700523 // id + paint_index + image_index + bool_for_src + constraint
524 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700525 if (src) {
526 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700527 }
reed871872f2015-06-22 12:48:26 -0700528 size += sizeof(dst); // + rect
mtkleinc2e29772015-10-30 05:24:58 -0700529
reed871872f2015-06-22 12:48:26 -0700530 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
reed871872f2015-06-22 12:48:26 -0700531 this->addPaintPtr(paint);
532 this->addImage(image);
533 this->addRectPtr(src); // may be null
534 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700535 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700536 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700537}
538
reed4c21dc52015-06-25 12:32:03 -0700539void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
540 const SkPaint* paint) {
541 // id + paint_index + image_index + center + dst
542 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
mtkleinc2e29772015-10-30 05:24:58 -0700543
reed4c21dc52015-06-25 12:32:03 -0700544 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
reed4c21dc52015-06-25 12:32:03 -0700545 this->addPaintPtr(paint);
546 this->addImage(img);
547 this->addIRect(center);
548 this->addRect(dst);
549 this->validate(initialOffset, size);
550}
551
msarett16882062016-08-16 09:31:08 -0700552void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
553 const SkRect& dst, const SkPaint* paint) {
Mike Reed7c9c9e42018-01-03 09:23:34 -0500554 size_t latticeSize = SkCanvasPriv::WriteLattice(nullptr, lattice);
msarett16882062016-08-16 09:31:08 -0700555 // op + paint index + image index + lattice + dst rect
556 size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
557 size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
558 this->addPaintPtr(paint);
559 this->addImage(image);
Mike Reed7c9c9e42018-01-03 09:23:34 -0500560 (void)SkCanvasPriv::WriteLattice(fWriter.reservePad(latticeSize), lattice);
msarett16882062016-08-16 09:31:08 -0700561 this->addRect(dst);
562 this->validate(initialOffset, size);
563}
564
Brian Salomond003d222018-11-26 13:25:05 -0500565void SkPictureRecord::onDrawImageSet(const SkCanvas::ImageSetEntry set[], int count,
Brian Salomond7065e72018-10-12 11:42:02 -0400566 SkFilterQuality filterQuality, SkBlendMode mode) {
Brian Salomon1da5cad2018-11-21 09:21:18 -0500567 // op + count + alpha + fq + mode + (image index, src rect, dst rect, alpha, aa flags) * cnt
Brian Salomond003d222018-11-26 13:25:05 -0500568 size_t size =
569 4 * kUInt32Size + (2 * kUInt32Size + 2 * sizeof(SkRect) + sizeof(SkScalar)) * count;
Brian Salomond7065e72018-10-12 11:42:02 -0400570 size_t initialOffset = this->addDraw(DRAW_IMAGE_SET, &size);
571 this->addInt(count);
Brian Salomond7065e72018-10-12 11:42:02 -0400572 this->addInt((int)filterQuality);
573 this->addInt((int)mode);
574 for (int i = 0; i < count; ++i) {
575 this->addImage(set[i].fImage.get());
576 this->addRect(set[i].fSrcRect);
577 this->addRect(set[i].fDstRect);
Brian Salomon1da5cad2018-11-21 09:21:18 -0500578 this->addScalar(set[i].fAlpha);
Brian Salomond7065e72018-10-12 11:42:02 -0400579 this->addInt((int)set[i].fAAFlags);
580 }
581 this->validate(initialOffset, size);
582}
583
fmalitab7425172014-08-26 07:56:44 -0700584void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
585 const SkPaint& paint) {
586
587 // op + paint index + blob index + x/y
588 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
589 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
fmalitab7425172014-08-26 07:56:44 -0700590
591 this->addPaint(paint);
592 this->addTextBlob(blob);
593 this->addScalar(x);
594 this->addScalar(y);
595
596 this->validate(initialOffset, size);
597}
598
reedd5fa1a42014-08-09 11:08:05 -0700599void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
600 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000601 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000602 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700603 size_t initialOffset;
604
halcanary96fcdcc2015-08-27 07:41:13 -0700605 if (nullptr == matrix && nullptr == paint) {
reedd5fa1a42014-08-09 11:08:05 -0700606 initialOffset = this->addDraw(DRAW_PICTURE, &size);
607 this->addPicture(picture);
608 } else {
609 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
Cary Clark6d6d6032017-10-20 12:14:33 -0400610 size += SkMatrixPriv::WriteToMemory(m, nullptr) + kUInt32Size; // matrix + paint
reedd5fa1a42014-08-09 11:08:05 -0700611 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
reedd5fa1a42014-08-09 11:08:05 -0700612 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700613 this->addMatrix(m);
614 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700615 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000616 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000617}
618
msarett95416f42016-04-27 13:51:20 -0700619void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
620 // op + drawable index
621 size_t size = 2 * kUInt32Size;
622 size_t initialOffset;
623
624 if (nullptr == matrix) {
625 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
626 this->addDrawable(drawable);
627 } else {
Cary Clark6d6d6032017-10-20 12:14:33 -0400628 size += SkMatrixPriv::WriteToMemory(*matrix, nullptr); // matrix
msarett95416f42016-04-27 13:51:20 -0700629 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
630 this->addMatrix(*matrix);
631 this->addDrawable(drawable);
632 }
633 this->validate(initialOffset, size);
634}
635
Ruiqi Maoc97a3392018-08-15 10:44:19 -0400636void SkPictureRecord::onDrawVerticesObject(const SkVertices* vertices,
637 const SkVertices::Bone bones[], int boneCount,
638 SkBlendMode mode, const SkPaint& paint) {
Ruiqi Maof5101492018-06-29 14:32:21 -0400639 // op + paint index + vertices index + number of bones + bone matrices + mode
Ruiqi Maoc97a3392018-08-15 10:44:19 -0400640 size_t size = 5 * kUInt32Size + boneCount * sizeof(SkVertices::Bone);
Mike Reede88a1cb2017-03-17 09:50:46 -0400641 size_t initialOffset = this->addDraw(DRAW_VERTICES_OBJECT, &size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000642
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000643 this->addPaint(paint);
Mike Reede88a1cb2017-03-17 09:50:46 -0400644 this->addVertices(vertices);
Ruiqi Maof5101492018-06-29 14:32:21 -0400645 this->addInt(boneCount);
Ruiqi Maoc97a3392018-08-15 10:44:19 -0400646 fWriter.write(bones, boneCount * sizeof(SkVertices::Bone));
Mike Reede88a1cb2017-03-17 09:50:46 -0400647 this->addInt(static_cast<uint32_t>(mode));
648
robertphillips@google.com8b169312013-10-15 17:47:36 +0000649 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000650}
651
dandovb3c9d1c2014-08-12 08:34:29 -0700652void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
Mike Reedfaba3712016-11-03 14:45:31 -0400653 const SkPoint texCoords[4], SkBlendMode bmode,
dandovb3c9d1c2014-08-12 08:34:29 -0700654 const SkPaint& paint) {
655 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
656 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
657 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700658 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700659 flag |= DRAW_VERTICES_HAS_COLORS;
660 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
661 }
bsalomon49f085d2014-09-05 13:34:00 -0700662 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700663 flag |= DRAW_VERTICES_HAS_TEXS;
664 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
665 }
Mike Reed7d954ad2016-10-28 15:42:34 -0400666 if (SkBlendMode::kModulate != bmode) {
667 flag |= DRAW_VERTICES_HAS_XFER;
668 size += kUInt32Size;
dandovb3c9d1c2014-08-12 08:34:29 -0700669 }
mtklein46616af2014-09-30 14:47:10 -0700670
dandov963137b2014-08-07 07:49:53 -0700671 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
dandov963137b2014-08-07 07:49:53 -0700672 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700673 this->addPatch(cubics);
674 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700675
dandovb3c9d1c2014-08-12 08:34:29 -0700676 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700677 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700678 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
679 }
bsalomon49f085d2014-09-05 13:34:00 -0700680 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700681 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
682 }
683 if (flag & DRAW_VERTICES_HAS_XFER) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400684 this->addInt((int)bmode);
dandovb3c9d1c2014-08-12 08:34:29 -0700685 }
dandov963137b2014-08-07 07:49:53 -0700686 this->validate(initialOffset, size);
687}
688
reed71c3c762015-06-24 10:29:17 -0700689void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
Mike Reedfaba3712016-11-03 14:45:31 -0400690 const SkColor colors[], int count, SkBlendMode mode,
reed71c3c762015-06-24 10:29:17 -0700691 const SkRect* cull, const SkPaint* paint) {
692 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
693 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
694 uint32_t flags = 0;
695 if (colors) {
696 flags |= DRAW_ATLAS_HAS_COLORS;
697 size += count * sizeof(SkColor);
698 size += sizeof(uint32_t); // xfermode::mode
699 }
700 if (cull) {
701 flags |= DRAW_ATLAS_HAS_CULL;
702 size += sizeof(SkRect);
703 }
mtkleinc2e29772015-10-30 05:24:58 -0700704
reed71c3c762015-06-24 10:29:17 -0700705 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
reed71c3c762015-06-24 10:29:17 -0700706 this->addPaintPtr(paint);
707 this->addImage(atlas);
708 this->addInt(flags);
709 this->addInt(count);
710 fWriter.write(xform, count * sizeof(SkRSXform));
711 fWriter.write(tex, count * sizeof(SkRect));
712
713 // write optional parameters
714 if (colors) {
715 fWriter.write(colors, count * sizeof(SkColor));
Mike Reed7d954ad2016-10-28 15:42:34 -0400716 this->addInt((int)mode);
reed71c3c762015-06-24 10:29:17 -0700717 }
718 if (cull) {
719 fWriter.write(cull, sizeof(SkRect));
720 }
721 this->validate(initialOffset, size);
722}
723
Jim Van Verth4123d0f2017-05-22 12:02:21 -0400724void SkPictureRecord::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
725 // op + path index + zParams + lightPos + lightRadius + spot/ambient alphas + color + flags
Mike Reed04f8b792018-01-24 13:48:08 -0500726 size_t size = 2 * kUInt32Size + 2 * sizeof(SkPoint3) + 1 * sizeof(SkScalar) + 3 * kUInt32Size;
Jim Van Verth4123d0f2017-05-22 12:02:21 -0400727 size_t initialOffset = this->addDraw(DRAW_SHADOW_REC, &size);
728
729 this->addPath(path);
730
731 fWriter.writePoint3(rec.fZPlaneParams);
732 fWriter.writePoint3(rec.fLightPos);
733 fWriter.writeScalar(rec.fLightRadius);
Jim Van Verthb1b80f72018-01-18 15:19:13 -0500734 fWriter.write32(rec.fAmbientColor);
735 fWriter.write32(rec.fSpotColor);
Jim Van Verth4123d0f2017-05-22 12:02:21 -0400736 fWriter.write32(rec.fFlags);
737
738 this->validate(initialOffset, size);
739}
740
reedf70b5312016-03-04 16:36:20 -0800741void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
742 size_t keyLen = fWriter.WriteStringSize(key);
743 size_t valueLen = fWriter.WriteDataSize(value);
744 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
745
746 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
747 this->addRect(rect);
748 fWriter.writeString(key);
749 fWriter.writeData(value);
750 this->validate(initialOffset, size);
751}
752
reed@android.com8a1c16f2008-12-17 15:59:43 +0000753///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000754
Florin Malita8fd15d82018-05-15 14:57:12 -0400755// De-duping helper.
756
757template <typename T>
758static bool equals(T* a, T* b) { return a->uniqueID() == b->uniqueID(); }
759
760template <>
761bool equals(SkDrawable* a, SkDrawable* b) {
762 // SkDrawable's generationID is not a stable unique identifier.
763 return a == b;
764}
765
766template <typename T>
767static int find_or_append(SkTArray<sk_sp<T>>& array, T* obj) {
Mike Kleinbd000a12018-04-19 09:24:57 -0400768 for (int i = 0; i < array.count(); i++) {
Florin Malita8fd15d82018-05-15 14:57:12 -0400769 if (equals(array[i].get(), obj)) {
Mike Kleinbd000a12018-04-19 09:24:57 -0400770 return i;
771 }
reed22b2af12016-08-29 07:52:13 -0700772 }
Florin Malita8fd15d82018-05-15 14:57:12 -0400773
774 array.push_back(sk_ref_sp(obj));
775
776 return array.count() - 1;
reed22b2af12016-08-29 07:52:13 -0700777}
778
reede8f30622016-03-23 18:59:25 -0700779sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700780 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000781}
782
reed871872f2015-06-22 12:48:26 -0700783void SkPictureRecord::addImage(const SkImage* image) {
reed22b2af12016-08-29 07:52:13 -0700784 // convention for images is 0-based index
Florin Malita8fd15d82018-05-15 14:57:12 -0400785 this->addInt(find_or_append(fImages, image));
reed871872f2015-06-22 12:48:26 -0700786}
787
reed@android.com8a1c16f2008-12-17 15:59:43 +0000788void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000789 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000790}
791
mtklein46616af2014-09-30 14:47:10 -0700792void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
mtklein46616af2014-09-30 14:47:10 -0700793 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800794 fPaints.push_back(*paint);
795 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700796 } else {
797 this->addInt(0);
798 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000799}
800
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000801int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700802 if (int* n = fPaths.find(path)) {
803 return *n;
804 }
805 int n = fPaths.count() + 1; // 0 is reserved for null / error.
806 fPaths.set(path, n);
807 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000808}
809
810void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000811 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000812}
813
dandovb3c9d1c2014-08-12 08:34:29 -0700814void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
815 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700816}
817
robertphillips9b14f262014-06-04 05:40:44 -0700818void SkPictureRecord::addPicture(const SkPicture* picture) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000819 // follow the convention of recording a 1-based index
Florin Malita8fd15d82018-05-15 14:57:12 -0400820 this->addInt(find_or_append(fPictures, picture) + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000821}
822
msarett95416f42016-04-27 13:51:20 -0700823void SkPictureRecord::addDrawable(SkDrawable* drawable) {
msarett95416f42016-04-27 13:51:20 -0700824 // follow the convention of recording a 1-based index
Florin Malita8fd15d82018-05-15 14:57:12 -0400825 this->addInt(find_or_append(fDrawables, drawable) + 1);
msarett95416f42016-04-27 13:51:20 -0700826}
827
reed@android.com8a1c16f2008-12-17 15:59:43 +0000828void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000829 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000830}
reed@google.com82065d62011-02-07 15:30:46 +0000831
reed@android.com8a1c16f2008-12-17 15:59:43 +0000832void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
833 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000834}
835
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000836void SkPictureRecord::addNoOp() {
837 size_t size = kUInt32Size; // op
838 this->addDraw(NOOP, &size);
839}
840
reed@android.com8a1c16f2008-12-17 15:59:43 +0000841void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000842 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000843}
844
845void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700846 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000847 fWriter.writeRect(*rect);
848 }
849}
850
reed@google.comf0b5e112011-09-07 11:57:34 +0000851void SkPictureRecord::addIRect(const SkIRect& rect) {
852 fWriter.write(&rect, sizeof(rect));
853}
854
reed@android.com8a1c16f2008-12-17 15:59:43 +0000855void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700856 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000857 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
858 }
859}
860
reed@google.com4ed0fb72012-12-12 20:48:18 +0000861void SkPictureRecord::addRRect(const SkRRect& rrect) {
862 fWriter.writeRRect(rrect);
863}
864
reed@android.com8a1c16f2008-12-17 15:59:43 +0000865void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000866 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000867}
868
869void SkPictureRecord::addText(const void* text, size_t byteLength) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000870 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000871 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000872}
873
reed22b2af12016-08-29 07:52:13 -0700874void SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
fmalitab7425172014-08-26 07:56:44 -0700875 // follow the convention of recording a 1-based index
Florin Malita8fd15d82018-05-15 14:57:12 -0400876 this->addInt(find_or_append(fTextBlobs, blob) + 1);
fmalitab7425172014-08-26 07:56:44 -0700877}
878
Mike Reede88a1cb2017-03-17 09:50:46 -0400879void SkPictureRecord::addVertices(const SkVertices* vertices) {
880 // follow the convention of recording a 1-based index
Florin Malita8fd15d82018-05-15 14:57:12 -0400881 this->addInt(find_or_append(fVertices, vertices) + 1);
Mike Reede88a1cb2017-03-17 09:50:46 -0400882}
883
reed@android.com8a1c16f2008-12-17 15:59:43 +0000884///////////////////////////////////////////////////////////////////////////////