blob: af1b8ffbc2134d0aa937c49429f61163e550d806 [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"
junov@chromium.orgd575eed2013-05-08 15:39:13 +00009#include "SkDevice.h"
dandovb3c9d1c2014-08-12 08:34:29 -070010#include "SkPatchUtils.h"
dandovb3c9d1c2014-08-12 08:34:29 -070011#include "SkPixelRef.h"
12#include "SkRRect.h"
fmalitab7425172014-08-26 07:56:44 -070013#include "SkTextBlob.h"
dandovb3c9d1c2014-08-12 08:34:29 -070014#include "SkTSearch.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015
reed@android.com8a1c16f2008-12-17 15:59:43 +000016#define HEAP_BLOCK_SIZE 4096
17
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000018enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000019 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000020 kNoInitialSave = -1,
21};
22
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000023// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
24static int const kUInt32Size = 4;
25
Florin Malita5f6102d2014-06-30 10:13:28 -040026static const uint32_t kSaveSize = kUInt32Size;
mtklein8e126562014-10-01 09:29:35 -070027#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000028static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
29static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
mtklein8e126562014-10-01 09:29:35 -070030#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000031
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 , fFirstSavedLayerIndex(kNoSavedLayerIndex)
35 , fRecordFlags(flags)
36 , fInitialSaveCount(kNoInitialSave) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000037}
38
39SkPictureRecord::~SkPictureRecord() {
djsollen@google.com21830d92012-08-07 19:49:41 +000040 fPictureRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070041 fTextBlobRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000042}
43
44///////////////////////////////////////////////////////////////////////////////
45
mtklein8e126562014-10-01 09:29:35 -070046#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000047// Return the offset of the paint inside a given op's byte stream. A zero
48// return value means there is no paint (and you really shouldn't be calling
49// this method)
mtklein8e126562014-10-01 09:29:35 -070050static inline size_t get_paint_offset(DrawType op, size_t opSize) {
robertphillips@google.come37ad352013-03-01 19:44:30 +000051 // These offsets are where the paint would be if the op size doesn't overflow
fmalita9f49cfd2014-08-12 12:24:17 -070052 static const uint8_t gPaintOffsets[] = {
robertphillips@google.come37ad352013-03-01 19:44:30 +000053 0, // UNUSED - no paint
54 0, // CLIP_PATH - no paint
55 0, // CLIP_REGION - no paint
56 0, // CLIP_RECT - no paint
57 0, // CLIP_RRECT - no paint
58 0, // CONCAT - no paint
59 1, // DRAW_BITMAP - right after op code
60 1, // DRAW_BITMAP_MATRIX - right after op code
61 1, // DRAW_BITMAP_NINE - right after op code
62 1, // DRAW_BITMAP_RECT_TO_RECT - right after op code
63 0, // DRAW_CLEAR - no paint
64 0, // DRAW_DATA - no paint
65 1, // DRAW_OVAL - right after op code
66 1, // DRAW_PAINT - right after op code
67 1, // DRAW_PATH - right after op code
68 0, // DRAW_PICTURE - no paint
69 1, // DRAW_POINTS - right after op code
70 1, // DRAW_POS_TEXT - right after op code
71 1, // DRAW_POS_TEXT_TOP_BOTTOM - right after op code
72 1, // DRAW_POS_TEXT_H - right after op code
73 1, // DRAW_POS_TEXT_H_TOP_BOTTOM - right after op code
74 1, // DRAW_RECT - right after op code
75 1, // DRAW_RRECT - right after op code
76 1, // DRAW_SPRITE - right after op code
77 1, // DRAW_TEXT - right after op code
78 1, // DRAW_TEXT_ON_PATH - right after op code
79 1, // DRAW_TEXT_TOP_BOTTOM - right after op code
80 1, // DRAW_VERTICES - right after op code
81 0, // RESTORE - no paint
82 0, // ROTATE - no paint
83 0, // SAVE - no paint
skia.committer@gmail.comf140f182013-03-02 07:01:56 +000084 0, // SAVE_LAYER - see below - this paint's location varies
robertphillips@google.come37ad352013-03-01 19:44:30 +000085 0, // SCALE - no paint
86 0, // SET_MATRIX - no paint
87 0, // SKEW - no paint
88 0, // TRANSLATE - no paint
89 0, // NOOP - no paint
robertphillips@google.com0a4805e2013-05-29 13:24:23 +000090 0, // BEGIN_GROUP - no paint
91 0, // COMMENT - no paint
92 0, // END_GROUP - no paint
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +000093 1, // DRAWDRRECT - right after op code
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +000094 0, // PUSH_CULL - no paint
95 0, // POP_CULL - no paint
dandov963137b2014-08-07 07:49:53 -070096 1, // DRAW_PATCH - right after op code
fmalita9f49cfd2014-08-12 12:24:17 -070097 1, // DRAW_PICTURE_MATRIX_PAINT - right after op code
fmalitab7425172014-08-26 07:56:44 -070098 1, // DRAW_TEXT_BLOB- right after op code
skia.committer@gmail.comf140f182013-03-02 07:01:56 +000099 };
robertphillips@google.come37ad352013-03-01 19:44:30 +0000100
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000101 SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
102 need_to_be_in_sync);
robertphillips@google.come37ad352013-03-01 19:44:30 +0000103 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
104
105 int overflow = 0;
106 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
107 // This op's size overflows so an extra uint32_t will be written
108 // after the op code
109 overflow = sizeof(uint32_t);
110 }
111
112 if (SAVE_LAYER == op) {
113 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
114 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
115
116 if (kSaveLayerNoBoundsSize == opSize) {
117 return kSaveLayerNoBoundsPaintOffset + overflow;
118 } else {
119 SkASSERT(kSaveLayerWithBoundsSize == opSize);
120 return kSaveLayerWithBoundsPaintOffset + overflow;
121 }
122 }
123
124 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this method
125 return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
126}
mtklein8e126562014-10-01 09:29:35 -0700127#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +0000128
Florin Malita5f6102d2014-06-30 10:13:28 -0400129void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +0000130 // record the offset to us, making it non-positive to distinguish a save
131 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000132 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -0400133 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000134
Florin Malita5f6102d2014-06-30 10:13:28 -0400135 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000136}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000137
Florin Malita5f6102d2014-06-30 10:13:28 -0400138void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -0700139 fContentInfo.onSave();
140
Florin Malita5f6102d2014-06-30 10:13:28 -0400141 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000142 size_t size = kSaveSize;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000143 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +0000144
robertphillips@google.com8b169312013-10-15 17:47:36 +0000145 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146}
147
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000148SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
149 const SkPaint* paint, SaveFlags flags) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000150 // record the offset to us, making it non-positive to distinguish a save
151 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000152 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000153 this->recordSaveLayer(bounds, paint, flags);
154 if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
155 fFirstSavedLayerIndex = fRestoreOffsetStack.count();
156 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000157
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000158 this->INHERITED::willSaveLayer(bounds, paint, flags);
159 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000160 at this time (and may not be able to afford since during record our
161 clip starts out the size of the picture, which is often much larger
162 than the size of the actual device we'll use during playback).
163 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000164 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000165}
166
167void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000168 SaveFlags flags) {
robertphillipsc019ec42014-08-12 05:35:58 -0700169 fContentInfo.onSaveLayer();
170
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000171 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000172 size_t size = 2 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700173 if (bounds) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000174 size += sizeof(*bounds); // + rect
175 }
176 // + paint index + flags
177 size += 2 * kUInt32Size;
178
robertphillips@google.come37ad352013-03-01 19:44:30 +0000179 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
180
robertphillips@google.com8b169312013-10-15 17:47:36 +0000181 size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000182 this->addRectPtr(bounds);
mtklein8e126562014-10-01 09:29:35 -0700183 SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000184 this->addPaintPtr(paint);
185 this->addInt(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186
robertphillips@google.com8b169312013-10-15 17:47:36 +0000187 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188}
189
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000190bool SkPictureRecord::isDrawingToLayer() const {
191 return fFirstSavedLayerIndex != kNoSavedLayerIndex;
192}
193
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000194#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000195/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000196 * Read the op code from 'offset' in 'writer' and extract the size too.
197 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000198static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000199 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000200
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000201 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000202 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000203 if (MASK_24 == *size) {
204 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000205 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000206 }
207 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000208}
mtklein46616af2014-09-30 14:47:10 -0700209#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000210
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000211void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000212 // FIXME: SkDeferredCanvas needs to be refactored to respect
213 // save/restore balancing so that the following test can be
214 // turned on permanently.
215#if 0
216 SkASSERT(fRestoreOffsetStack.count() > 1);
217#endif
218
reed@android.comb4e22d62009-07-09 15:20:25 +0000219 // check for underflow
220 if (fRestoreOffsetStack.count() == 0) {
221 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000223
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000224 if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) {
225 fFirstSavedLayerIndex = kNoSavedLayerIndex;
226 }
227
mtklein46616af2014-09-30 14:47:10 -0700228 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000229
reed@android.comb4e22d62009-07-09 15:20:25 +0000230 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000231
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000232 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000233}
234
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000235void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700236 fContentInfo.onRestore();
237
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000238 if (fillInSkips) {
239 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
240 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000241 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
242 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000243 this->validate(initialOffset, size);
244}
245
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000246void SkPictureRecord::recordTranslate(const SkMatrix& m) {
247 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
248
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000249 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000250 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000251 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000252 this->addScalar(m.getTranslateX());
253 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000254 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000255}
256
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000257void SkPictureRecord::recordScale(const SkMatrix& m) {
258 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000259
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000260 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000261 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000262 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000263 this->addScalar(m.getScaleX());
264 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000265 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000266}
267
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000268void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000269 switch (matrix.getType()) {
270 case SkMatrix::kTranslate_Mask:
271 this->recordTranslate(matrix);
272 break;
273 case SkMatrix::kScale_Mask:
274 this->recordScale(matrix);
275 break;
276 default:
277 this->recordConcat(matrix);
278 break;
279 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000280 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000281}
282
283void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000284 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000285 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000286 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000287 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000288 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000289 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000290}
291
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000292void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000293 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000294 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000295 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000296 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000297 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000298 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000299 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000300}
301
reed@google.com45482d12011-08-29 19:02:39 +0000302static bool regionOpExpands(SkRegion::Op op) {
303 switch (op) {
304 case SkRegion::kUnion_Op:
305 case SkRegion::kXOR_Op:
306 case SkRegion::kReverseDifference_Op:
307 case SkRegion::kReplace_Op:
308 return true;
309 case SkRegion::kIntersect_Op:
310 case SkRegion::kDifference_Op:
311 return false;
312 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000313 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000314 return false;
315 }
316}
317
robertphillips@google.come37ad352013-03-01 19:44:30 +0000318void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000319 int32_t offset = fRestoreOffsetStack.top();
320 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000321 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
322 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000323 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000324 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000325
reed@google.comffacd3c2012-08-30 15:31:23 +0000326#ifdef SK_DEBUG
327 // assert that the final offset value points to a save verb
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000328 uint32_t opSize;
329 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
reed@google.comffacd3c2012-08-30 15:31:23 +0000330 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
331#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000332}
333
reed@google.comd86e7ab2012-09-27 20:31:31 +0000334void SkPictureRecord::beginRecording() {
335 // we have to call this *after* our constructor, to ensure that it gets
336 // recorded. This is balanced by restoreToCount() call from endRecording,
337 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000338 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000339}
340
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000341void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000342 SkASSERT(kNoInitialSave != fInitialSaveCount);
343 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000344}
345
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000346size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000347 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000348 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000349 }
350
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000351 // The RestoreOffset field is initially filled with a placeholder
352 // value that points to the offset of the previous RestoreOffset
353 // in the current stack level, thus forming a linked list so that
354 // the restore offsets can be filled in when the corresponding
355 // restore command is recorded.
356 int32_t prevOffset = fRestoreOffsetStack.top();
357
reed@google.com45482d12011-08-29 19:02:39 +0000358 if (regionOpExpands(op)) {
359 // Run back through any previous clip ops, and mark their offset to
360 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
361 // they could hide this clips ability to expand the clip (i.e. go from
362 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000363 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000364
365 // Reset the pointer back to the previous clip so that subsequent
366 // restores don't overwrite the offsets we just cleared.
367 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000368 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000369
reed@google.com44699382013-10-31 17:28:30 +0000370 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000371 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000372 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000373 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000374}
375
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000376void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000377 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000378 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000379}
380
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000381size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000382 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000383 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000384 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000385 if (!fRestoreOffsetStack.isEmpty()) {
386 // + restore offset
387 size += kUInt32Size;
388 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000389 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000390 this->addRect(rect);
391 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000392 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000393
robertphillips@google.com8b169312013-10-15 17:47:36 +0000394 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000395 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000396}
397
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000398void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000399 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700400 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000401}
402
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000403size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000404 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000405 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000406 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000407 if (!fRestoreOffsetStack.isEmpty()) {
408 // + restore offset
409 size += kUInt32Size;
410 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000411 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000412 this->addRRect(rrect);
413 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000414 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000415 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000416 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000417}
418
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000419void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000420 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000421 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700422 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000423}
424
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000425size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000426 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000427 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000428 // recordRestoreOffsetPlaceholder doesn't always write an offset
429 if (!fRestoreOffsetStack.isEmpty()) {
430 // + restore offset
431 size += kUInt32Size;
432 }
433 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000434 this->addInt(pathID);
435 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000436 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000437 this->validate(initialOffset, size);
438 return offset;
439}
440
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000441void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000442 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000443 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000444}
445
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000446size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000447 // op + clip params + region
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000448 size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000449 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000450 if (!fRestoreOffsetStack.isEmpty()) {
451 // + restore offset
452 size += kUInt32Size;
453 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000454 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000455 this->addRegion(region);
456 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000457 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000458
robertphillips@google.com8b169312013-10-15 17:47:36 +0000459 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000460 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000461}
462
reed@google.com2a981812011-04-14 18:59:28 +0000463void SkPictureRecord::clear(SkColor color) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000464 // op + color
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000465 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000466 size_t initialOffset = this->addDraw(DRAW_CLEAR, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000467 this->addInt(color);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000468 this->validate(initialOffset, size);
reed@google.com2a981812011-04-14 18:59:28 +0000469}
470
reed@android.com8a1c16f2008-12-17 15:59:43 +0000471void SkPictureRecord::drawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000472 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000473 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000474 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700475 SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000476 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000477 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000478}
479
480void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000481 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700482 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000483
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000484 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000485 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000486 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
mtklein8e126562014-10-01 09:29:35 -0700487 SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000488 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700489
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000490 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000491 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000492 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000493 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000494}
495
reed@google.com4ed0fb72012-12-12 20:48:18 +0000496void SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000497 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000498 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000499 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
mtklein8e126562014-10-01 09:29:35 -0700500 SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000501 this->addPaint(paint);
502 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000503 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000504}
505
bsalomon@google.com7ce564c2013-10-22 16:54:15 +0000506void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000507 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000508 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000509 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700510 SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000511 this->addPaint(paint);
512 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000513 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000514}
515
reed@google.com4ed0fb72012-12-12 20:48:18 +0000516void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700517 // op + paint index + rrect
518 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
519 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700520 SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700521 this->addPaint(paint);
522 this->addRRect(rrect);
523 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000524}
525
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000526void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
527 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000528 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000529 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
530 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700531 SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000532 this->addPaint(paint);
533 this->addRRect(outer);
534 this->addRRect(inner);
535 this->validate(initialOffset, size);
536}
537
bsalomon@google.com7ce564c2013-10-22 16:54:15 +0000538void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700539 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000540
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000541 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000542 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000543 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700544 SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000545 this->addPaint(paint);
546 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000547 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000548}
549
550void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000551 const SkPaint* paint = NULL) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000552 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000553 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000554 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
mtklein8e126562014-10-01 09:29:35 -0700555 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000556 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000557 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000558 this->addScalar(left);
559 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000560 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000561}
562
reed@google.com71121732012-09-18 15:14:33 +0000563void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000564 const SkRect& dst, const SkPaint* paint,
565 DrawBitmapRectFlags flags) {
566 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000567 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700568 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000569 size += sizeof(*src); // + rect
570 }
571 size += sizeof(dst); // + rect
572
robertphillips@google.com8b169312013-10-15 17:47:36 +0000573 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700574 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT_TO_RECT, size)
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000575 == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000576 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000577 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000578 this->addRectPtr(src); // may be null
579 this->addRect(dst);
580 this->addInt(flags);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000581 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000582}
583
584void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
reed@google.comf0b5e112011-09-07 11:57:34 +0000585 const SkPaint* paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000586 // id + paint index + bitmap index + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000587 size_t size = 3 * kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000588 size_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
mtklein8e126562014-10-01 09:29:35 -0700589 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_MATRIX, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000590 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000591 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000592 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000593 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000594}
595
reed@google.comf0b5e112011-09-07 11:57:34 +0000596void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
597 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000598 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000599 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000600 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
mtklein8e126562014-10-01 09:29:35 -0700601 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000602 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000603 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000604 this->addIRect(center);
605 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000606 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000607}
608
reed@android.com8a1c16f2008-12-17 15:59:43 +0000609void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000610 const SkPaint* paint = NULL) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000611 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000612 size_t size = 5 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000613 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
mtklein8e126562014-10-01 09:29:35 -0700614 SkASSERT(initialOffset+get_paint_offset(DRAW_SPRITE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000615 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000616 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000617 this->addInt(left);
618 this->addInt(top);
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::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
623 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000624 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000625 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000626
mtklein46616af2014-09-30 14:47:10 -0700627 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000628 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700629 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700630 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000631 this->addText(text, byteLength);
632 this->addScalar(x);
633 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000634 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000635}
636
reed@google.come0d9ce82014-04-23 04:00:17 +0000637void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
638 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000639 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000640
mtklein46616af2014-09-30 14:47:10 -0700641 // op + paint index + length + 'length' worth of data + num points + x&y point data
642 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000643
mtklein46616af2014-09-30 14:47:10 -0700644 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000645
robertphillips@google.com8b169312013-10-15 17:47:36 +0000646 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700647 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700648 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000649 this->addText(text, byteLength);
650 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700651 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000652 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000653}
654
reed@google.come0d9ce82014-04-23 04:00:17 +0000655void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
656 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000657 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000658
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000659 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000660 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000661 // + y + the actual points
662 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000663
mtklein46616af2014-09-30 14:47:10 -0700664 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
665 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000666 this->addText(text, byteLength);
667 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000668 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000669 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000670 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000671}
672
reed@google.come0d9ce82014-04-23 04:00:17 +0000673void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
674 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000675 // op + paint index + length + 'length' worth of data + path index + matrix
676 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000677 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000678 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700679 SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000680 this->addPaint(paint);
681 this->addText(text, byteLength);
682 this->addPath(path);
683 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000684 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000685}
686
fmalitab7425172014-08-26 07:56:44 -0700687void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
688 const SkPaint& paint) {
689
690 // op + paint index + blob index + x/y
691 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
692 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
mtklein8e126562014-10-01 09:29:35 -0700693 SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
fmalitab7425172014-08-26 07:56:44 -0700694
695 this->addPaint(paint);
696 this->addTextBlob(blob);
697 this->addScalar(x);
698 this->addScalar(y);
699
700 this->validate(initialOffset, size);
701}
702
reedd5fa1a42014-08-09 11:08:05 -0700703void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
704 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000705 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000706 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700707 size_t initialOffset;
708
709 if (NULL == matrix && NULL == paint) {
710 initialOffset = this->addDraw(DRAW_PICTURE, &size);
711 this->addPicture(picture);
712 } else {
713 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
714 size += m.writeToMemory(NULL) + kUInt32Size; // matrix + paint
715 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700716 SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
fmalita9f49cfd2014-08-12 12:24:17 -0700717 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700718 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700719 this->addMatrix(m);
720 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700721 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000722 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000723}
724
725void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
726 const SkPoint vertices[], const SkPoint texs[],
reed@google.com85e143c2013-12-30 15:51:25 +0000727 const SkColor colors[], SkXfermode* xfer,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000728 const uint16_t indices[], int indexCount,
729 const SkPaint& paint) {
730 uint32_t flags = 0;
731 if (texs) {
732 flags |= DRAW_VERTICES_HAS_TEXS;
733 }
734 if (colors) {
735 flags |= DRAW_VERTICES_HAS_COLORS;
736 }
737 if (indexCount > 0) {
738 flags |= DRAW_VERTICES_HAS_INDICES;
739 }
bsalomon49f085d2014-09-05 13:34:00 -0700740 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000741 SkXfermode::Mode mode;
742 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
743 flags |= DRAW_VERTICES_HAS_XFER;
744 }
745 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000746
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000747 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000748 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000749 if (flags & DRAW_VERTICES_HAS_TEXS) {
750 size += vertexCount * sizeof(SkPoint); // + uvs
751 }
752 if (flags & DRAW_VERTICES_HAS_COLORS) {
753 size += vertexCount * sizeof(SkColor); // + vert colors
754 }
755 if (flags & DRAW_VERTICES_HAS_INDICES) {
756 // + num indices + indices
757 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
758 }
reed@google.com85e143c2013-12-30 15:51:25 +0000759 if (flags & DRAW_VERTICES_HAS_XFER) {
760 size += kUInt32Size; // mode enum
761 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000762
robertphillips@google.com8b169312013-10-15 17:47:36 +0000763 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
mtklein8e126562014-10-01 09:29:35 -0700764 SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000765 this->addPaint(paint);
766 this->addInt(flags);
767 this->addInt(vmode);
768 this->addInt(vertexCount);
769 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000770 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000771 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000772 }
773 if (flags & DRAW_VERTICES_HAS_COLORS) {
774 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
775 }
776 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000777 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000778 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
779 }
reed@google.com85e143c2013-12-30 15:51:25 +0000780 if (flags & DRAW_VERTICES_HAS_XFER) {
781 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
782 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000783 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000784 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000785 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000786}
787
dandovb3c9d1c2014-08-12 08:34:29 -0700788void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
789 const SkPoint texCoords[4], SkXfermode* xmode,
790 const SkPaint& paint) {
791 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
792 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
793 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700794 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700795 flag |= DRAW_VERTICES_HAS_COLORS;
796 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
797 }
bsalomon49f085d2014-09-05 13:34:00 -0700798 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700799 flag |= DRAW_VERTICES_HAS_TEXS;
800 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
801 }
bsalomon49f085d2014-09-05 13:34:00 -0700802 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700803 SkXfermode::Mode mode;
804 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
805 flag |= DRAW_VERTICES_HAS_XFER;
806 size += kUInt32Size;
807 }
808 }
mtklein46616af2014-09-30 14:47:10 -0700809
dandov963137b2014-08-07 07:49:53 -0700810 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
mtklein8e126562014-10-01 09:29:35 -0700811 SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
dandov963137b2014-08-07 07:49:53 -0700812 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700813 this->addPatch(cubics);
814 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700815
dandovb3c9d1c2014-08-12 08:34:29 -0700816 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700817 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700818 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
819 }
bsalomon49f085d2014-09-05 13:34:00 -0700820 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700821 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
822 }
823 if (flag & DRAW_VERTICES_HAS_XFER) {
824 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
825 xmode->asMode(&mode);
826 this->addInt(mode);
827 }
dandov963137b2014-08-07 07:49:53 -0700828 this->validate(initialOffset, size);
829}
830
reed@android.comcb608442009-12-04 21:32:27 +0000831void SkPictureRecord::drawData(const void* data, size_t length) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000832 // op + length + 'length' worth of data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000833 size_t size = 2 * kUInt32Size + SkAlign4(length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000834 size_t initialOffset = this->addDraw(DRAW_DATA, &size);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000835 this->addInt(SkToInt(length));
reed@android.comcb608442009-12-04 21:32:27 +0000836 fWriter.writePad(data, length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000837 this->validate(initialOffset, size);
reed@android.comcb608442009-12-04 21:32:27 +0000838}
839
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000840void SkPictureRecord::beginCommentGroup(const char* description) {
841 // op/size + length of string + \0 terminated chars
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000842 size_t length = strlen(description);
843 size_t size = 2 * kUInt32Size + SkAlign4(length + 1);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000844 size_t initialOffset = this->addDraw(BEGIN_COMMENT_GROUP, &size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000845 fWriter.writeString(description, length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000846 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000847}
848
849void SkPictureRecord::addComment(const char* kywd, const char* value) {
850 // op/size + 2x length of string + 2x \0 terminated chars
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000851 size_t kywdLen = strlen(kywd);
852 size_t valueLen = strlen(value);
853 size_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000854 size_t initialOffset = this->addDraw(COMMENT, &size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000855 fWriter.writeString(kywd, kywdLen);
856 fWriter.writeString(value, valueLen);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000857 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000858}
859
860void SkPictureRecord::endCommentGroup() {
861 // op/size
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000862 size_t size = 1 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000863 size_t initialOffset = this->addDraw(END_COMMENT_GROUP, &size);
864 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000865}
866
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000867// [op/size] [rect] [skip offset]
868static const uint32_t kPushCullOpSize = 2 * kUInt32Size + sizeof(SkRect);
869void SkPictureRecord::onPushCull(const SkRect& cullRect) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000870 size_t size = kPushCullOpSize;
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000871 size_t initialOffset = this->addDraw(PUSH_CULL, &size);
872 // PUSH_CULL's size should stay constant (used to rewind).
873 SkASSERT(size == kPushCullOpSize);
874
875 this->addRect(cullRect);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000876 fCullOffsetStack.push(SkToU32(fWriter.bytesWritten()));
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000877 this->addInt(0);
878 this->validate(initialOffset, size);
879}
880
881void SkPictureRecord::onPopCull() {
882 SkASSERT(!fCullOffsetStack.isEmpty());
883
884 uint32_t cullSkipOffset = fCullOffsetStack.top();
885 fCullOffsetStack.pop();
886
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000887 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000888 size_t size = kUInt32Size;
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000889 size_t initialOffset = this->addDraw(POP_CULL, &size);
890
891 // update the cull skip offset to point past this op.
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000892 fWriter.overwriteTAt<uint32_t>(cullSkipOffset, SkToU32(fWriter.bytesWritten()));
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000893
894 this->validate(initialOffset, size);
895}
896
reed@android.com8a1c16f2008-12-17 15:59:43 +0000897///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000898
reed4a8126e2014-09-22 07:29:03 -0700899SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000900 return NULL;
reed@google.com76f10a32014-02-05 15:32:21 +0000901}
902
commit-bot@chromium.org8016f792014-03-07 15:53:01 +0000903int SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
mtklein71a23632014-11-12 10:24:55 -0800904 if (bitmap.isImmutable()) {
905 fBitmaps.push_back(bitmap);
906 } else {
907 SkBitmap copy;
908 bitmap.copyTo(&copy);
909 copy.setImmutable();
910 fBitmaps.push_back(copy);
911 }
912 this->addInt(fBitmaps.count()-1); // Unlike the rest, bitmap indicies are 0-based.
913 return fBitmaps.count();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000914}
915
916void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000917 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000918}
919
mtklein46616af2014-09-30 14:47:10 -0700920void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700921 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000922
mtklein46616af2014-09-30 14:47:10 -0700923 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800924 fPaints.push_back(*paint);
925 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700926 } else {
927 this->addInt(0);
928 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000929}
930
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000931int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtklein71a23632014-11-12 10:24:55 -0800932 fPaths.push_back(path);
933 return fPaths.count();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000934}
935
936void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000937 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000938}
939
dandovb3c9d1c2014-08-12 08:34:29 -0700940void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
941 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700942}
943
robertphillips9b14f262014-06-04 05:40:44 -0700944void SkPictureRecord::addPicture(const SkPicture* picture) {
945 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000946 if (index < 0) { // not found
947 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700948 *fPictureRefs.append() = picture;
949 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000950 }
951 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000952 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000953}
954
955void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000956 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000957}
reed@google.com82065d62011-02-07 15:30:46 +0000958
reed@android.com8a1c16f2008-12-17 15:59:43 +0000959void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
960 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000961}
962
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000963void SkPictureRecord::addNoOp() {
964 size_t size = kUInt32Size; // op
965 this->addDraw(NOOP, &size);
966}
967
reed@android.com8a1c16f2008-12-17 15:59:43 +0000968void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000969 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000970}
971
972void SkPictureRecord::addRectPtr(const SkRect* rect) {
973 if (fWriter.writeBool(rect != NULL)) {
974 fWriter.writeRect(*rect);
975 }
976}
977
reed@google.comf0b5e112011-09-07 11:57:34 +0000978void SkPictureRecord::addIRect(const SkIRect& rect) {
979 fWriter.write(&rect, sizeof(rect));
980}
981
reed@android.com8a1c16f2008-12-17 15:59:43 +0000982void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
983 if (fWriter.writeBool(rect != NULL)) {
984 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
985 }
986}
987
reed@google.com4ed0fb72012-12-12 20:48:18 +0000988void SkPictureRecord::addRRect(const SkRRect& rrect) {
989 fWriter.writeRRect(rrect);
990}
991
reed@android.com8a1c16f2008-12-17 15:59:43 +0000992void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000993 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000994}
995
996void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -0700997 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000998 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000999 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001000}
1001
fmalitab7425172014-08-26 07:56:44 -07001002void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001003 int index = fTextBlobRefs.count();
1004 *fTextBlobRefs.append() = blob;
1005 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001006 // follow the convention of recording a 1-based index
1007 this->addInt(index + 1);
1008}
1009
reed@android.com8a1c16f2008-12-17 15:59:43 +00001010///////////////////////////////////////////////////////////////////////////////
1011