blob: 2ebe7bbe506402a1ec072d7918709eaaa6e4a704 [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"
Jim Van Verth1af03d42017-07-31 09:34:58 -04009#include "SkDrawShadowInfo.h"
reeda85d4d02015-05-06 12:56:48 -070010#include "SkImage_Base.h"
dandovb3c9d1c2014-08-12 08:34:29 -070011#include "SkPatchUtils.h"
dandovb3c9d1c2014-08-12 08:34:29 -070012#include "SkPixelRef.h"
13#include "SkRRect.h"
reed71c3c762015-06-24 10:29:17 -070014#include "SkRSXform.h"
fmalitab7425172014-08-26 07:56:44 -070015#include "SkTextBlob.h"
dandovb3c9d1c2014-08-12 08:34:29 -070016#include "SkTSearch.h"
Mike Reedebfce6d2016-12-12 10:02:12 -050017#include "SkClipOpPriv.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000018
reed@android.com8a1c16f2008-12-17 15:59:43 +000019#define HEAP_BLOCK_SIZE 4096
20
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000021enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000022 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000023 kNoInitialSave = -1,
24};
25
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000026// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
27static int const kUInt32Size = 4;
28
robertphillips0bdbea72014-06-11 11:37:55 -070029SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000030 : INHERITED(dimensions.width(), dimensions.height())
mtklein71a23632014-11-12 10:24:55 -080031 , fRecordFlags(flags)
32 , fInitialSaveCount(kNoInitialSave) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000033}
34
35SkPictureRecord::~SkPictureRecord() {
robertphillips5351aad2015-06-23 06:54:56 -070036 fImageRefs.unrefAll();
djsollen@google.com21830d92012-08-07 19:49:41 +000037 fPictureRefs.unrefAll();
msarett95416f42016-04-27 13:51:20 -070038 fDrawableRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070039 fTextBlobRefs.unrefAll();
Mike Reede88a1cb2017-03-17 09:50:46 -040040 fVerticesRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000041}
42
43///////////////////////////////////////////////////////////////////////////////
44
Mike Klein7cc49d62017-08-14 10:39:28 -040045void SkPictureRecord::onFlush() {
46 size_t size = sizeof(kUInt32Size);
47 size_t initialOffset = this->addDraw(FLUSH, &size);
48 this->validate(initialOffset, size);
49}
50
Florin Malita5f6102d2014-06-30 10:13:28 -040051void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +000052 // record the offset to us, making it non-positive to distinguish a save
53 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +000054 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -040055 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000056
Florin Malita5f6102d2014-06-30 10:13:28 -040057 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +000058}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +000059
Florin Malita5f6102d2014-06-30 10:13:28 -040060void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -070061 fContentInfo.onSave();
62
Florin Malita5f6102d2014-06-30 10:13:28 -040063 // op only
reed512f3e32016-01-04 14:11:31 -080064 size_t size = sizeof(kUInt32Size);
robertphillips@google.com8b169312013-10-15 17:47:36 +000065 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +000066
robertphillips@google.com8b169312013-10-15 17:47:36 +000067 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +000068}
69
reed4960eee2015-12-18 07:09:18 -080070SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
reed@google.comffacd3c2012-08-30 15:31:23 +000071 // record the offset to us, making it non-positive to distinguish a save
72 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +000073 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
reed4960eee2015-12-18 07:09:18 -080074 this->recordSaveLayer(rec);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +000075
reed4960eee2015-12-18 07:09:18 -080076 (void)this->INHERITED::getSaveLayerStrategy(rec);
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000077 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +000078 at this time (and may not be able to afford since during record our
79 clip starts out the size of the picture, which is often much larger
80 than the size of the actual device we'll use during playback).
81 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +000082 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +000083}
84
reed4960eee2015-12-18 07:09:18 -080085void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
robertphillipsc019ec42014-08-12 05:35:58 -070086 fContentInfo.onSaveLayer();
87
reedbfd5f172016-01-07 11:28:08 -080088 // op + flatflags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +000089 size_t size = 2 * kUInt32Size;
reedbfd5f172016-01-07 11:28:08 -080090 uint32_t flatFlags = 0;
91
reed4960eee2015-12-18 07:09:18 -080092 if (rec.fBounds) {
reedbfd5f172016-01-07 11:28:08 -080093 flatFlags |= SAVELAYERREC_HAS_BOUNDS;
94 size += sizeof(*rec.fBounds);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000095 }
reedbfd5f172016-01-07 11:28:08 -080096 if (rec.fPaint) {
97 flatFlags |= SAVELAYERREC_HAS_PAINT;
98 size += sizeof(uint32_t); // index
99 }
100 if (rec.fBackdrop) {
101 flatFlags |= SAVELAYERREC_HAS_BACKDROP;
102 size += sizeof(uint32_t); // (paint) index
103 }
104 if (rec.fSaveLayerFlags) {
105 flatFlags |= SAVELAYERREC_HAS_FLAGS;
106 size += sizeof(uint32_t);
107 }
Florin Malita53f77bd2017-04-28 13:48:37 -0400108 if (rec.fClipMask) {
109 flatFlags |= SAVELAYERREC_HAS_CLIPMASK;
110 size += sizeof(uint32_t); // clip image index
111 }
112 if (rec.fClipMatrix) {
113 flatFlags |= SAVELAYERREC_HAS_CLIPMATRIX;
114 size += rec.fClipMatrix->writeToMemory(nullptr);
115 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000116
reedbfd5f172016-01-07 11:28:08 -0800117 const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
118 this->addInt(flatFlags);
119 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
120 this->addRect(*rec.fBounds);
121 }
122 if (flatFlags & SAVELAYERREC_HAS_PAINT) {
123 this->addPaintPtr(rec.fPaint);
124 }
125 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
126 // overkill, but we didn't already track single flattenables, so using a paint for that
127 SkPaint paint;
Mike Reed5e257172016-11-01 11:22:05 -0400128 paint.setImageFilter(sk_ref_sp(const_cast<SkImageFilter*>(rec.fBackdrop)));
reedbfd5f172016-01-07 11:28:08 -0800129 this->addPaint(paint);
130 }
131 if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
132 this->addInt(rec.fSaveLayerFlags);
133 }
Florin Malita53f77bd2017-04-28 13:48:37 -0400134 if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
Mike Kleinb34ab042017-05-01 21:34:14 +0000135 this->addImage(rec.fClipMask);
Florin Malita53f77bd2017-04-28 13:48:37 -0400136 }
137 if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
138 this->addMatrix(*rec.fClipMatrix);
139 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000140 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000141}
142
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000143#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000144/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000145 * Read the op code from 'offset' in 'writer' and extract the size too.
146 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000147static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000148 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000149
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000150 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000151 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000152 if (MASK_24 == *size) {
153 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000154 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000155 }
156 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000157}
mtklein46616af2014-09-30 14:47:10 -0700158#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000159
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000160void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000161#if 0
162 SkASSERT(fRestoreOffsetStack.count() > 1);
163#endif
164
reed@android.comb4e22d62009-07-09 15:20:25 +0000165 // check for underflow
166 if (fRestoreOffsetStack.count() == 0) {
167 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000169
mtklein46616af2014-09-30 14:47:10 -0700170 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000171
reed@android.comb4e22d62009-07-09 15:20:25 +0000172 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000173
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000174 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175}
176
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000177void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700178 fContentInfo.onRestore();
179
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000180 if (fillInSkips) {
181 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
182 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000183 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
184 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000185 this->validate(initialOffset, size);
186}
187
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000188void SkPictureRecord::recordTranslate(const SkMatrix& m) {
189 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
190
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000191 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000192 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000193 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000194 this->addScalar(m.getTranslateX());
195 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000196 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000197}
198
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000199void SkPictureRecord::recordScale(const SkMatrix& m) {
200 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000201
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000202 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000203 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000204 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000205 this->addScalar(m.getScaleX());
206 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000207 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208}
209
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000210void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000211 switch (matrix.getType()) {
212 case SkMatrix::kTranslate_Mask:
213 this->recordTranslate(matrix);
214 break;
215 case SkMatrix::kScale_Mask:
216 this->recordScale(matrix);
217 break;
218 default:
219 this->recordConcat(matrix);
220 break;
221 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000222 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000223}
224
225void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000226 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000227 // op + matrix
halcanary96fcdcc2015-08-27 07:41:13 -0700228 size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000229 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000230 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000231 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000232}
233
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000234void SkPictureRecord::didSetMatrix(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
halcanary96fcdcc2015-08-27 07:41:13 -0700237 size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000238 size_t initialOffset = this->addDraw(SET_MATRIX, &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);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000241 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000242}
243
Mike Reedc1f77742016-12-09 09:00:50 -0500244static bool clipOpExpands(SkClipOp op) {
reed@google.com45482d12011-08-29 19:02:39 +0000245 switch (op) {
Mike Reedc1f77742016-12-09 09:00:50 -0500246 case kUnion_SkClipOp:
247 case kXOR_SkClipOp:
248 case kReverseDifference_SkClipOp:
249 case kReplace_SkClipOp:
reed@google.com45482d12011-08-29 19:02:39 +0000250 return true;
Mike Reedc1f77742016-12-09 09:00:50 -0500251 case kIntersect_SkClipOp:
252 case kDifference_SkClipOp:
reed@google.com45482d12011-08-29 19:02:39 +0000253 return false;
254 default:
Mike Reedc1f77742016-12-09 09:00:50 -0500255 SkDEBUGFAIL("unknown clipop");
reed@google.com45482d12011-08-29 19:02:39 +0000256 return false;
257 }
258}
259
robertphillips@google.come37ad352013-03-01 19:44:30 +0000260void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000261 int32_t offset = fRestoreOffsetStack.top();
262 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000263 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
264 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000265 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000266 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000267
reed@google.comffacd3c2012-08-30 15:31:23 +0000268#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800269 // offset of 0 has been disabled, so we skip it
270 if (offset > 0) {
271 // assert that the final offset value points to a save verb
272 uint32_t opSize;
273 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
reed4960eee2015-12-18 07:09:18 -0800274 SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
reedbfd5f172016-01-07 11:28:08 -0800275 SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
276 SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
reed2ff1fce2014-12-11 07:07:37 -0800277 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000278#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000279}
280
reed@google.comd86e7ab2012-09-27 20:31:31 +0000281void SkPictureRecord::beginRecording() {
282 // we have to call this *after* our constructor, to ensure that it gets
283 // recorded. This is balanced by restoreToCount() call from endRecording,
284 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000285 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000286}
287
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000288void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000289 SkASSERT(kNoInitialSave != fInitialSaveCount);
290 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000291}
292
Mike Reedc1f77742016-12-09 09:00:50 -0500293size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkClipOp op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000294 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000295 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000296 }
297
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000298 // The RestoreOffset field is initially filled with a placeholder
299 // value that points to the offset of the previous RestoreOffset
300 // in the current stack level, thus forming a linked list so that
301 // the restore offsets can be filled in when the corresponding
302 // restore command is recorded.
303 int32_t prevOffset = fRestoreOffsetStack.top();
304
reed73603f32016-09-20 08:42:38 -0700305 if (clipOpExpands(op)) {
reed@google.com45482d12011-08-29 19:02:39 +0000306 // Run back through any previous clip ops, and mark their offset to
307 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
308 // they could hide this clips ability to expand the clip (i.e. go from
309 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000310 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000311
312 // Reset the pointer back to the previous clip so that subsequent
313 // restores don't overwrite the offsets we just cleared.
314 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000315 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000316
reed@google.com44699382013-10-31 17:28:30 +0000317 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000318 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000319 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000320 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000321}
322
Mike Reedc1f77742016-12-09 09:00:50 -0500323void SkPictureRecord::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000324 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000325 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000326}
327
Mike Reedc1f77742016-12-09 09:00:50 -0500328size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkClipOp op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000329 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000330 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000331 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000332 if (!fRestoreOffsetStack.isEmpty()) {
333 // + restore offset
334 size += kUInt32Size;
335 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000336 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000337 this->addRect(rect);
338 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000339 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000340
robertphillips@google.com8b169312013-10-15 17:47:36 +0000341 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000342 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000343}
344
Mike Reedc1f77742016-12-09 09:00:50 -0500345void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000346 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700347 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000348}
349
Mike Reedc1f77742016-12-09 09:00:50 -0500350size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000351 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000352 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000353 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000354 if (!fRestoreOffsetStack.isEmpty()) {
355 // + restore offset
356 size += kUInt32Size;
357 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000358 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000359 this->addRRect(rrect);
360 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000361 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000362 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000363 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000364}
365
Mike Reedc1f77742016-12-09 09:00:50 -0500366void SkPictureRecord::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000367 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000368 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700369 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000370}
371
Mike Reedc1f77742016-12-09 09:00:50 -0500372size_t SkPictureRecord::recordClipPath(int pathID, SkClipOp op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000373 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000374 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000375 // recordRestoreOffsetPlaceholder doesn't always write an offset
376 if (!fRestoreOffsetStack.isEmpty()) {
377 // + restore offset
378 size += kUInt32Size;
379 }
380 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000381 this->addInt(pathID);
382 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000383 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000384 this->validate(initialOffset, size);
385 return offset;
386}
387
Mike Reedc1f77742016-12-09 09:00:50 -0500388void SkPictureRecord::onClipRegion(const SkRegion& region, SkClipOp op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000389 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000390 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000391}
392
Mike Reedc1f77742016-12-09 09:00:50 -0500393size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkClipOp op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000394 // op + clip params + region
halcanary96fcdcc2015-08-27 07:41:13 -0700395 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000396 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000397 if (!fRestoreOffsetStack.isEmpty()) {
398 // + restore offset
399 size += kUInt32Size;
400 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000401 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000402 this->addRegion(region);
403 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000404 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000405
robertphillips@google.com8b169312013-10-15 17:47:36 +0000406 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000407 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000408}
409
reed41af9662015-01-05 07:49:08 -0800410void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000411 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000412 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000413 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000414 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000415 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000416}
417
reed41af9662015-01-05 07:49:08 -0800418void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
419 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700420 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000421
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000422 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000423 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000424 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000425 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700426
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000427 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000428 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000429 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000430 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000431}
432
reed41af9662015-01-05 07:49:08 -0800433void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000434 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000435 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000436 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000437 this->addPaint(paint);
438 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000439 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000440}
441
bsalomonac3aa242016-08-19 11:25:19 -0700442void SkPictureRecord::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
443 bool useCenter, const SkPaint& paint) {
444 // op + paint index + rect + start + sweep + bool (as int)
445 size_t size = 2 * kUInt32Size + sizeof(oval) + sizeof(startAngle) + sizeof(sweepAngle) +
446 sizeof(int);
447 size_t initialOffset = this->addDraw(DRAW_ARC, &size);
448 this->addPaint(paint);
449 this->addRect(oval);
450 this->addScalar(startAngle);
451 this->addScalar(sweepAngle);
452 this->addInt(useCenter);
453 this->validate(initialOffset, size);
454}
455
reed41af9662015-01-05 07:49:08 -0800456void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000457 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000458 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000459 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000460 this->addPaint(paint);
461 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000462 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000463}
464
msarett44df6512016-08-25 13:54:30 -0700465void SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
466 // op + paint index + region
467 size_t regionBytes = region.writeToMemory(nullptr);
468 size_t size = 2 * kUInt32Size + regionBytes;
469 size_t initialOffset = this->addDraw(DRAW_REGION, &size);
470 this->addPaint(paint);
471 fWriter.writeRegion(region);
472 this->validate(initialOffset, size);
473}
474
reed41af9662015-01-05 07:49:08 -0800475void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700476 // op + paint index + rrect
477 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
478 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein46616af2014-09-30 14:47:10 -0700479 this->addPaint(paint);
480 this->addRRect(rrect);
481 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000482}
483
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000484void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
485 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000486 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000487 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
488 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000489 this->addPaint(paint);
490 this->addRRect(outer);
491 this->addRRect(inner);
492 this->validate(initialOffset, size);
493}
494
reed41af9662015-01-05 07:49:08 -0800495void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700496 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000497
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000498 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000499 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000500 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000501 this->addPaint(paint);
502 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000503 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000504}
505
reeda85d4d02015-05-06 12:56:48 -0700506void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
507 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700508 // op + paint_index + image_index + x + y
509 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
510 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
reed871872f2015-06-22 12:48:26 -0700511 this->addPaintPtr(paint);
512 this->addImage(image);
513 this->addScalar(x);
514 this->addScalar(y);
515 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700516}
517
518void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700519 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700520 // id + paint_index + image_index + bool_for_src + constraint
521 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700522 if (src) {
523 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700524 }
reed871872f2015-06-22 12:48:26 -0700525 size += sizeof(dst); // + rect
mtkleinc2e29772015-10-30 05:24:58 -0700526
reed871872f2015-06-22 12:48:26 -0700527 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
reed871872f2015-06-22 12:48:26 -0700528 this->addPaintPtr(paint);
529 this->addImage(image);
530 this->addRectPtr(src); // may be null
531 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700532 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700533 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700534}
535
reed4c21dc52015-06-25 12:32:03 -0700536void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
537 const SkPaint* paint) {
538 // id + paint_index + image_index + center + dst
539 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
mtkleinc2e29772015-10-30 05:24:58 -0700540
reed4c21dc52015-06-25 12:32:03 -0700541 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
reed4c21dc52015-06-25 12:32:03 -0700542 this->addPaintPtr(paint);
543 this->addImage(img);
544 this->addIRect(center);
545 this->addRect(dst);
546 this->validate(initialOffset, size);
547}
548
msarett16882062016-08-16 09:31:08 -0700549void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
550 const SkRect& dst, const SkPaint* paint) {
551 // xCount + xDivs + yCount+ yDivs
msarett0764efe2016-09-02 11:24:30 -0700552 int flagCount = (nullptr == lattice.fFlags) ? 0 : (lattice.fXCount + 1) * (lattice.fYCount + 1);
553 size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size +
msarett71df2d72016-09-30 12:41:42 -0700554 SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)) + sizeof(SkIRect);
msarett16882062016-08-16 09:31:08 -0700555
556 // op + paint index + image index + lattice + dst rect
557 size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
558 size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
559 this->addPaintPtr(paint);
560 this->addImage(image);
561 this->addInt(lattice.fXCount);
562 fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
563 this->addInt(lattice.fYCount);
564 fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
msarett0764efe2016-09-02 11:24:30 -0700565 this->addInt(flagCount);
566 fWriter.writePad(lattice.fFlags, flagCount * sizeof(SkCanvas::Lattice::Flags));
msarett71df2d72016-09-30 12:41:42 -0700567 SkASSERT(lattice.fBounds);
568 this->addIRect(*lattice.fBounds);
msarett16882062016-08-16 09:31:08 -0700569 this->addRect(dst);
570 this->validate(initialOffset, size);
571}
572
reed@google.come0d9ce82014-04-23 04:00:17 +0000573void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
574 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000575 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000576 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000577
mtklein46616af2014-09-30 14:47:10 -0700578 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000579 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700580 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000581 this->addText(text, byteLength);
582 this->addScalar(x);
583 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000584 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000585}
586
reed@google.come0d9ce82014-04-23 04:00:17 +0000587void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
588 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000589 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590
mtklein46616af2014-09-30 14:47:10 -0700591 // op + paint index + length + 'length' worth of data + num points + x&y point data
592 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000593
mtklein46616af2014-09-30 14:47:10 -0700594 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000595
robertphillips@google.com8b169312013-10-15 17:47:36 +0000596 size_t initialOffset = this->addDraw(op, &size);
mtklein46616af2014-09-30 14:47:10 -0700597 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000598 this->addText(text, byteLength);
599 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700600 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000601 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000602}
603
reed@google.come0d9ce82014-04-23 04:00:17 +0000604void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
605 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000606 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000607
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000608 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000609 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000610 // + y + the actual points
611 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000612
mtklein46616af2014-09-30 14:47:10 -0700613 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
614 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000615 this->addText(text, byteLength);
616 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000617 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000618 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000619 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000620}
621
reed@google.come0d9ce82014-04-23 04:00:17 +0000622void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
623 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000624 // op + paint index + length + 'length' worth of data + path index + matrix
625 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700626 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000627 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000628 this->addPaint(paint);
629 this->addText(text, byteLength);
630 this->addPath(path);
631 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000632 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000633}
634
reed45561a02016-07-07 12:47:17 -0700635void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
636 const SkRSXform xform[], const SkRect* cull,
637 const SkPaint& paint) {
638 const int count = paint.countText(text, byteLength);
639 // [op + paint-index + count + flags + length] + [text] + [xform] + cull
640 size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
641 uint32_t flags = 0;
642 if (cull) {
643 flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
644 size += sizeof(SkRect);
645 }
646
647 size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
648 this->addPaint(paint);
649 this->addInt(count);
650 this->addInt(flags);
651 this->addText(text, byteLength);
652 fWriter.write(xform, count * sizeof(SkRSXform));
653 if (cull) {
654 fWriter.write(cull, sizeof(SkRect));
655 }
656 this->validate(initialOffset, size);
657}
658
fmalitab7425172014-08-26 07:56:44 -0700659void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
660 const SkPaint& paint) {
661
662 // op + paint index + blob index + x/y
663 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
664 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
fmalitab7425172014-08-26 07:56:44 -0700665
666 this->addPaint(paint);
667 this->addTextBlob(blob);
668 this->addScalar(x);
669 this->addScalar(y);
670
671 this->validate(initialOffset, size);
672}
673
reedd5fa1a42014-08-09 11:08:05 -0700674void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
675 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000676 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000677 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700678 size_t initialOffset;
679
halcanary96fcdcc2015-08-27 07:41:13 -0700680 if (nullptr == matrix && nullptr == paint) {
reedd5fa1a42014-08-09 11:08:05 -0700681 initialOffset = this->addDraw(DRAW_PICTURE, &size);
682 this->addPicture(picture);
683 } else {
684 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
halcanary96fcdcc2015-08-27 07:41:13 -0700685 size += m.writeToMemory(nullptr) + kUInt32Size; // matrix + paint
reedd5fa1a42014-08-09 11:08:05 -0700686 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
reedd5fa1a42014-08-09 11:08:05 -0700687 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700688 this->addMatrix(m);
689 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700690 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000691 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000692}
693
msarett95416f42016-04-27 13:51:20 -0700694void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
695 // op + drawable index
696 size_t size = 2 * kUInt32Size;
697 size_t initialOffset;
698
699 if (nullptr == matrix) {
700 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
701 this->addDrawable(drawable);
702 } else {
703 size += matrix->writeToMemory(nullptr); // matrix
704 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
705 this->addMatrix(*matrix);
706 this->addDrawable(drawable);
707 }
708 this->validate(initialOffset, size);
709}
710
Mike Reede88a1cb2017-03-17 09:50:46 -0400711void SkPictureRecord::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
712 const SkPaint& paint) {
713 // op + paint index + vertices index + mode
714 size_t size = 4 * kUInt32Size;
715 size_t initialOffset = this->addDraw(DRAW_VERTICES_OBJECT, &size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000716
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000717 this->addPaint(paint);
Mike Reede88a1cb2017-03-17 09:50:46 -0400718 this->addVertices(vertices);
719 this->addInt(static_cast<uint32_t>(mode));
720
robertphillips@google.com8b169312013-10-15 17:47:36 +0000721 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000722}
723
dandovb3c9d1c2014-08-12 08:34:29 -0700724void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
Mike Reedfaba3712016-11-03 14:45:31 -0400725 const SkPoint texCoords[4], SkBlendMode bmode,
dandovb3c9d1c2014-08-12 08:34:29 -0700726 const SkPaint& paint) {
727 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
728 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
729 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700730 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700731 flag |= DRAW_VERTICES_HAS_COLORS;
732 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
733 }
bsalomon49f085d2014-09-05 13:34:00 -0700734 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700735 flag |= DRAW_VERTICES_HAS_TEXS;
736 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
737 }
Mike Reed7d954ad2016-10-28 15:42:34 -0400738 if (SkBlendMode::kModulate != bmode) {
739 flag |= DRAW_VERTICES_HAS_XFER;
740 size += kUInt32Size;
dandovb3c9d1c2014-08-12 08:34:29 -0700741 }
mtklein46616af2014-09-30 14:47:10 -0700742
dandov963137b2014-08-07 07:49:53 -0700743 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
dandov963137b2014-08-07 07:49:53 -0700744 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700745 this->addPatch(cubics);
746 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700747
dandovb3c9d1c2014-08-12 08:34:29 -0700748 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700749 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700750 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
751 }
bsalomon49f085d2014-09-05 13:34:00 -0700752 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700753 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
754 }
755 if (flag & DRAW_VERTICES_HAS_XFER) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400756 this->addInt((int)bmode);
dandovb3c9d1c2014-08-12 08:34:29 -0700757 }
dandov963137b2014-08-07 07:49:53 -0700758 this->validate(initialOffset, size);
759}
760
reed71c3c762015-06-24 10:29:17 -0700761void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
Mike Reedfaba3712016-11-03 14:45:31 -0400762 const SkColor colors[], int count, SkBlendMode mode,
reed71c3c762015-06-24 10:29:17 -0700763 const SkRect* cull, const SkPaint* paint) {
764 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
765 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
766 uint32_t flags = 0;
767 if (colors) {
768 flags |= DRAW_ATLAS_HAS_COLORS;
769 size += count * sizeof(SkColor);
770 size += sizeof(uint32_t); // xfermode::mode
771 }
772 if (cull) {
773 flags |= DRAW_ATLAS_HAS_CULL;
774 size += sizeof(SkRect);
775 }
mtkleinc2e29772015-10-30 05:24:58 -0700776
reed71c3c762015-06-24 10:29:17 -0700777 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
reed71c3c762015-06-24 10:29:17 -0700778 this->addPaintPtr(paint);
779 this->addImage(atlas);
780 this->addInt(flags);
781 this->addInt(count);
782 fWriter.write(xform, count * sizeof(SkRSXform));
783 fWriter.write(tex, count * sizeof(SkRect));
784
785 // write optional parameters
786 if (colors) {
787 fWriter.write(colors, count * sizeof(SkColor));
Mike Reed7d954ad2016-10-28 15:42:34 -0400788 this->addInt((int)mode);
reed71c3c762015-06-24 10:29:17 -0700789 }
790 if (cull) {
791 fWriter.write(cull, sizeof(SkRect));
792 }
793 this->validate(initialOffset, size);
794}
795
Jim Van Verth4123d0f2017-05-22 12:02:21 -0400796void SkPictureRecord::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
797 // op + path index + zParams + lightPos + lightRadius + spot/ambient alphas + color + flags
798 size_t size = 2 * kUInt32Size + 2 * sizeof(SkPoint3) + 3 * sizeof(SkScalar) + 2 * kUInt32Size;
799 size_t initialOffset = this->addDraw(DRAW_SHADOW_REC, &size);
800
801 this->addPath(path);
802
803 fWriter.writePoint3(rec.fZPlaneParams);
804 fWriter.writePoint3(rec.fLightPos);
805 fWriter.writeScalar(rec.fLightRadius);
806 fWriter.writeScalar(rec.fAmbientAlpha);
807 fWriter.writeScalar(rec.fSpotAlpha);
808 fWriter.write32(rec.fColor);
809 fWriter.write32(rec.fFlags);
810
811 this->validate(initialOffset, size);
812}
813
reedf70b5312016-03-04 16:36:20 -0800814void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
815 size_t keyLen = fWriter.WriteStringSize(key);
816 size_t valueLen = fWriter.WriteDataSize(value);
817 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
818
819 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
820 this->addRect(rect);
821 fWriter.writeString(key);
822 fWriter.writeData(value);
823 this->validate(initialOffset, size);
824}
825
reed@android.com8a1c16f2008-12-17 15:59:43 +0000826///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000827
reed22b2af12016-08-29 07:52:13 -0700828template <typename T> int find_or_append_uniqueID(SkTDArray<const T*>& array, const T* obj) {
829 int index = array.select([&](const T* elem) {
830 return elem->uniqueID() == obj->uniqueID();
831 });
832 if (index < 0) {
833 index = array.count();
834 *array.append() = SkRef(obj);
835 }
836 return index;
837}
838
reede8f30622016-03-23 18:59:25 -0700839sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
halcanary96fcdcc2015-08-27 07:41:13 -0700840 return nullptr;
reed@google.com76f10a32014-02-05 15:32:21 +0000841}
842
reed871872f2015-06-22 12:48:26 -0700843void SkPictureRecord::addImage(const SkImage* image) {
reed22b2af12016-08-29 07:52:13 -0700844 // convention for images is 0-based index
845 this->addInt(find_or_append_uniqueID(fImageRefs, image));
reed871872f2015-06-22 12:48:26 -0700846}
847
reed@android.com8a1c16f2008-12-17 15:59:43 +0000848void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000849 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000850}
851
mtklein46616af2014-09-30 14:47:10 -0700852void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700853 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000854
mtklein46616af2014-09-30 14:47:10 -0700855 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800856 fPaints.push_back(*paint);
857 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700858 } else {
859 this->addInt(0);
860 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000861}
862
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000863int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtkleinc2e29772015-10-30 05:24:58 -0700864 if (int* n = fPaths.find(path)) {
865 return *n;
866 }
867 int n = fPaths.count() + 1; // 0 is reserved for null / error.
868 fPaths.set(path, n);
869 return n;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000870}
871
872void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000873 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000874}
875
dandovb3c9d1c2014-08-12 08:34:29 -0700876void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
877 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700878}
879
robertphillips9b14f262014-06-04 05:40:44 -0700880void SkPictureRecord::addPicture(const SkPicture* picture) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000881 // follow the convention of recording a 1-based index
reed22b2af12016-08-29 07:52:13 -0700882 this->addInt(find_or_append_uniqueID(fPictureRefs, picture) + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000883}
884
msarett95416f42016-04-27 13:51:20 -0700885void SkPictureRecord::addDrawable(SkDrawable* drawable) {
886 int index = fDrawableRefs.find(drawable);
887 if (index < 0) { // not found
888 index = fDrawableRefs.count();
889 *fDrawableRefs.append() = drawable;
890 drawable->ref();
891 }
892 // follow the convention of recording a 1-based index
893 this->addInt(index + 1);
894}
895
reed@android.com8a1c16f2008-12-17 15:59:43 +0000896void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000897 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000898}
reed@google.com82065d62011-02-07 15:30:46 +0000899
reed@android.com8a1c16f2008-12-17 15:59:43 +0000900void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
901 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000902}
903
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000904void SkPictureRecord::addNoOp() {
905 size_t size = kUInt32Size; // op
906 this->addDraw(NOOP, &size);
907}
908
reed@android.com8a1c16f2008-12-17 15:59:43 +0000909void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000910 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000911}
912
913void SkPictureRecord::addRectPtr(const SkRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700914 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000915 fWriter.writeRect(*rect);
916 }
917}
918
reed@google.comf0b5e112011-09-07 11:57:34 +0000919void SkPictureRecord::addIRect(const SkIRect& rect) {
920 fWriter.write(&rect, sizeof(rect));
921}
922
reed@android.com8a1c16f2008-12-17 15:59:43 +0000923void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
halcanary96fcdcc2015-08-27 07:41:13 -0700924 if (fWriter.writeBool(rect != nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000925 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
926 }
927}
928
reed@google.com4ed0fb72012-12-12 20:48:18 +0000929void SkPictureRecord::addRRect(const SkRRect& rrect) {
930 fWriter.writeRRect(rrect);
931}
932
reed@android.com8a1c16f2008-12-17 15:59:43 +0000933void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000934 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000935}
936
937void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -0700938 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000939 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000940 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000941}
942
reed22b2af12016-08-29 07:52:13 -0700943void SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
fmalitab7425172014-08-26 07:56:44 -0700944 // follow the convention of recording a 1-based index
reed22b2af12016-08-29 07:52:13 -0700945 this->addInt(find_or_append_uniqueID(fTextBlobRefs, blob) + 1);
fmalitab7425172014-08-26 07:56:44 -0700946}
947
Mike Reede88a1cb2017-03-17 09:50:46 -0400948void SkPictureRecord::addVertices(const SkVertices* vertices) {
949 // follow the convention of recording a 1-based index
950 this->addInt(find_or_append_uniqueID(fVerticesRefs, vertices) + 1);
951}
952
reed@android.com8a1c16f2008-12-17 15:59:43 +0000953///////////////////////////////////////////////////////////////////////////////