blob: 018da0bb48951084aea018de501bf535af12bc90 [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"
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"
fmalitab7425172014-08-26 07:56:44 -070014#include "SkTextBlob.h"
dandovb3c9d1c2014-08-12 08:34:29 -070015#include "SkTSearch.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000016
reed@android.com8a1c16f2008-12-17 15:59:43 +000017#define HEAP_BLOCK_SIZE 4096
18
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000019enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000020 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000021 kNoInitialSave = -1,
22};
23
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000024// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
25static int const kUInt32Size = 4;
26
Florin Malita5f6102d2014-06-30 10:13:28 -040027static const uint32_t kSaveSize = kUInt32Size;
mtklein8e126562014-10-01 09:29:35 -070028#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000029static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
30static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
mtklein8e126562014-10-01 09:29:35 -070031#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000032
robertphillips0bdbea72014-06-11 11:37:55 -070033SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000034 : INHERITED(dimensions.width(), dimensions.height())
mtklein71a23632014-11-12 10:24:55 -080035 , 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
Florin Malitac54d8db2014-12-10 12:02:16 -050060 1, // DRAW_BITMAP_MATRIX - right after op code, deprecated
robertphillips@google.come37ad352013-03-01 19:44:30 +000061 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
reed871872f2015-06-22 12:48:26 -070099 1, // DRAW_IMAGE - right after op code
100 1, // DRAW_IMAGE_RECT - right after op code
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000101 };
robertphillips@google.come37ad352013-03-01 19:44:30 +0000102
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000103 SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
104 need_to_be_in_sync);
robertphillips@google.come37ad352013-03-01 19:44:30 +0000105 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
106
107 int overflow = 0;
108 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
109 // This op's size overflows so an extra uint32_t will be written
110 // after the op code
111 overflow = sizeof(uint32_t);
112 }
113
114 if (SAVE_LAYER == op) {
115 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
116 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
117
118 if (kSaveLayerNoBoundsSize == opSize) {
119 return kSaveLayerNoBoundsPaintOffset + overflow;
120 } else {
121 SkASSERT(kSaveLayerWithBoundsSize == opSize);
122 return kSaveLayerWithBoundsPaintOffset + overflow;
123 }
124 }
125
126 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this method
127 return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
128}
mtklein8e126562014-10-01 09:29:35 -0700129#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +0000130
Florin Malita5f6102d2014-06-30 10:13:28 -0400131void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +0000132 // record the offset to us, making it non-positive to distinguish a save
133 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000134 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -0400135 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000136
Florin Malita5f6102d2014-06-30 10:13:28 -0400137 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000138}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000139
Florin Malita5f6102d2014-06-30 10:13:28 -0400140void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -0700141 fContentInfo.onSave();
142
Florin Malita5f6102d2014-06-30 10:13:28 -0400143 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000144 size_t size = kSaveSize;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000145 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +0000146
robertphillips@google.com8b169312013-10-15 17:47:36 +0000147 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000148}
149
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000150SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
151 const SkPaint* paint, SaveFlags flags) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000152 // record the offset to us, making it non-positive to distinguish a save
153 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000154 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000155 this->recordSaveLayer(bounds, paint, flags);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000156
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000157 this->INHERITED::willSaveLayer(bounds, paint, flags);
158 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000159 at this time (and may not be able to afford since during record our
160 clip starts out the size of the picture, which is often much larger
161 than the size of the actual device we'll use during playback).
162 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000163 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000164}
165
166void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000167 SaveFlags flags) {
robertphillipsc019ec42014-08-12 05:35:58 -0700168 fContentInfo.onSaveLayer();
169
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000170 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000171 size_t size = 2 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700172 if (bounds) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000173 size += sizeof(*bounds); // + rect
174 }
175 // + paint index + flags
176 size += 2 * kUInt32Size;
177
robertphillips@google.come37ad352013-03-01 19:44:30 +0000178 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
179
robertphillips@google.com8b169312013-10-15 17:47:36 +0000180 size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000181 this->addRectPtr(bounds);
mtklein8e126562014-10-01 09:29:35 -0700182 SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000183 this->addPaintPtr(paint);
184 this->addInt(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185
robertphillips@google.com8b169312013-10-15 17:47:36 +0000186 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000187}
188
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000189#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000190/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000191 * Read the op code from 'offset' in 'writer' and extract the size too.
192 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000193static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000194 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000195
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000196 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000197 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000198 if (MASK_24 == *size) {
199 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000200 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000201 }
202 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000203}
mtklein46616af2014-09-30 14:47:10 -0700204#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000205
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000206void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000207 // FIXME: SkDeferredCanvas needs to be refactored to respect
208 // save/restore balancing so that the following test can be
209 // turned on permanently.
210#if 0
211 SkASSERT(fRestoreOffsetStack.count() > 1);
212#endif
213
reed@android.comb4e22d62009-07-09 15:20:25 +0000214 // check for underflow
215 if (fRestoreOffsetStack.count() == 0) {
216 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000217 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000218
mtklein46616af2014-09-30 14:47:10 -0700219 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000220
reed@android.comb4e22d62009-07-09 15:20:25 +0000221 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000222
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000223 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000224}
225
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000226void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700227 fContentInfo.onRestore();
228
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000229 if (fillInSkips) {
230 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
231 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000232 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
233 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000234 this->validate(initialOffset, size);
235}
236
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000237void SkPictureRecord::recordTranslate(const SkMatrix& m) {
238 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
239
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000240 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000241 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000242 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000243 this->addScalar(m.getTranslateX());
244 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000245 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000246}
247
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000248void SkPictureRecord::recordScale(const SkMatrix& m) {
249 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000250
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000251 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000252 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000253 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000254 this->addScalar(m.getScaleX());
255 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000256 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000257}
258
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000259void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000260 switch (matrix.getType()) {
261 case SkMatrix::kTranslate_Mask:
262 this->recordTranslate(matrix);
263 break;
264 case SkMatrix::kScale_Mask:
265 this->recordScale(matrix);
266 break;
267 default:
268 this->recordConcat(matrix);
269 break;
270 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000271 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000272}
273
274void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000275 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000276 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000277 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000278 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000279 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000280 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000281}
282
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000283void SkPictureRecord::didSetMatrix(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(SET_MATRIX, &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);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000290 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000291}
292
reed@google.com45482d12011-08-29 19:02:39 +0000293static bool regionOpExpands(SkRegion::Op op) {
294 switch (op) {
295 case SkRegion::kUnion_Op:
296 case SkRegion::kXOR_Op:
297 case SkRegion::kReverseDifference_Op:
298 case SkRegion::kReplace_Op:
299 return true;
300 case SkRegion::kIntersect_Op:
301 case SkRegion::kDifference_Op:
302 return false;
303 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000304 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000305 return false;
306 }
307}
308
robertphillips@google.come37ad352013-03-01 19:44:30 +0000309void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000310 int32_t offset = fRestoreOffsetStack.top();
311 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000312 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
313 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000314 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000315 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000316
reed@google.comffacd3c2012-08-30 15:31:23 +0000317#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800318 // offset of 0 has been disabled, so we skip it
319 if (offset > 0) {
320 // assert that the final offset value points to a save verb
321 uint32_t opSize;
322 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
323 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
324 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000325#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000326}
327
reed@google.comd86e7ab2012-09-27 20:31:31 +0000328void SkPictureRecord::beginRecording() {
329 // we have to call this *after* our constructor, to ensure that it gets
330 // recorded. This is balanced by restoreToCount() call from endRecording,
331 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000332 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000333}
334
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000335void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000336 SkASSERT(kNoInitialSave != fInitialSaveCount);
337 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000338}
339
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000340size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000341 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000342 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000343 }
344
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000345 // The RestoreOffset field is initially filled with a placeholder
346 // value that points to the offset of the previous RestoreOffset
347 // in the current stack level, thus forming a linked list so that
348 // the restore offsets can be filled in when the corresponding
349 // restore command is recorded.
350 int32_t prevOffset = fRestoreOffsetStack.top();
351
reed@google.com45482d12011-08-29 19:02:39 +0000352 if (regionOpExpands(op)) {
353 // Run back through any previous clip ops, and mark their offset to
354 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
355 // they could hide this clips ability to expand the clip (i.e. go from
356 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000357 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000358
359 // Reset the pointer back to the previous clip so that subsequent
360 // restores don't overwrite the offsets we just cleared.
361 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000362 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000363
reed@google.com44699382013-10-31 17:28:30 +0000364 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000365 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000366 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000367 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000368}
369
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000370void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000371 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000372 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000373}
374
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000375size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000376 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000377 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000378 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000379 if (!fRestoreOffsetStack.isEmpty()) {
380 // + restore offset
381 size += kUInt32Size;
382 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000383 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000384 this->addRect(rect);
385 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000386 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000387
robertphillips@google.com8b169312013-10-15 17:47:36 +0000388 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000389 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000390}
391
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000392void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000393 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700394 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000395}
396
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000397size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000398 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000399 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000400 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000401 if (!fRestoreOffsetStack.isEmpty()) {
402 // + restore offset
403 size += kUInt32Size;
404 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000405 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000406 this->addRRect(rrect);
407 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000408 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000409 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000410 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000411}
412
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000413void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000414 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000415 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700416 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000417}
418
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000419size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000420 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000421 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000422 // recordRestoreOffsetPlaceholder doesn't always write an offset
423 if (!fRestoreOffsetStack.isEmpty()) {
424 // + restore offset
425 size += kUInt32Size;
426 }
427 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000428 this->addInt(pathID);
429 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000430 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000431 this->validate(initialOffset, size);
432 return offset;
433}
434
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000435void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000436 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000437 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000438}
439
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000440size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000441 // op + clip params + region
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000442 size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000443 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000444 if (!fRestoreOffsetStack.isEmpty()) {
445 // + restore offset
446 size += kUInt32Size;
447 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000448 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000449 this->addRegion(region);
450 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000451 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000452
robertphillips@google.com8b169312013-10-15 17:47:36 +0000453 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000454 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000455}
456
reed41af9662015-01-05 07:49:08 -0800457void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000458 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000459 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000460 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700461 SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000462 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000463 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000464}
465
reed41af9662015-01-05 07:49:08 -0800466void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
467 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700468 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000469
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000470 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000471 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000472 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
mtklein8e126562014-10-01 09:29:35 -0700473 SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000474 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700475
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000476 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000477 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000478 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000479 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000480}
481
reed41af9662015-01-05 07:49:08 -0800482void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000483 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000484 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000485 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
mtklein8e126562014-10-01 09:29:35 -0700486 SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000487 this->addPaint(paint);
488 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000489 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000490}
491
reed41af9662015-01-05 07:49:08 -0800492void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000493 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000494 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000495 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700496 SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000497 this->addPaint(paint);
498 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000499 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000500}
501
reed41af9662015-01-05 07:49:08 -0800502void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700503 // op + paint index + rrect
504 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
505 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700506 SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700507 this->addPaint(paint);
508 this->addRRect(rrect);
509 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000510}
511
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000512void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
513 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000514 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000515 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
516 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700517 SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000518 this->addPaint(paint);
519 this->addRRect(outer);
520 this->addRRect(inner);
521 this->validate(initialOffset, size);
522}
523
reed41af9662015-01-05 07:49:08 -0800524void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700525 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000526
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000527 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000528 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000529 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700530 SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000531 this->addPaint(paint);
532 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000533 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000534}
535
reed41af9662015-01-05 07:49:08 -0800536void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
537 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000538 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000539 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000540 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
mtklein8e126562014-10-01 09:29:35 -0700541 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000542 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000543 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000544 this->addScalar(left);
545 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000546 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000547}
548
reed41af9662015-01-05 07:49:08 -0800549void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
550 const SkPaint* paint, DrawBitmapRectFlags flags) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000551 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000552 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700553 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000554 size += sizeof(*src); // + rect
555 }
556 size += sizeof(dst); // + rect
557
robertphillips@google.com8b169312013-10-15 17:47:36 +0000558 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700559 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT_TO_RECT, size)
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000560 == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000561 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000562 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000563 this->addRectPtr(src); // may be null
564 this->addRect(dst);
565 this->addInt(flags);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000566 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000567}
568
reeda85d4d02015-05-06 12:56:48 -0700569void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
570 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700571 // op + paint_index + image_index + x + y
572 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
573 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
574 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE, size) == fWriter.bytesWritten());
575 this->addPaintPtr(paint);
576 this->addImage(image);
577 this->addScalar(x);
578 this->addScalar(y);
579 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700580}
581
582void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
583 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700584 // id + paint_index + bitmap_index + bool_for_src
585 size_t size = 4 * kUInt32Size;
586 if (src) {
587 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700588 }
reed871872f2015-06-22 12:48:26 -0700589 size += sizeof(dst); // + rect
590
591 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
592 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE_RECT, size)
593 == fWriter.bytesWritten());
594 this->addPaintPtr(paint);
595 this->addImage(image);
596 this->addRectPtr(src); // may be null
597 this->addRect(dst);
598 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700599}
600
reed41af9662015-01-05 07:49:08 -0800601void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
602 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000603 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000604 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000605 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
mtklein8e126562014-10-01 09:29:35 -0700606 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000607 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000608 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000609 this->addIRect(center);
610 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000611 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000612}
613
reed41af9662015-01-05 07:49:08 -0800614void SkPictureRecord::onDrawSprite(const SkBitmap& bitmap, int left, int top,
615 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000616 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000617 size_t size = 5 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000618 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
mtklein8e126562014-10-01 09:29:35 -0700619 SkASSERT(initialOffset+get_paint_offset(DRAW_SPRITE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000620 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000621 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000622 this->addInt(left);
623 this->addInt(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000624 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000625}
626
reed@google.come0d9ce82014-04-23 04:00:17 +0000627void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
628 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000629 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000630 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000631
mtklein46616af2014-09-30 14:47:10 -0700632 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000633 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700634 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700635 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000636 this->addText(text, byteLength);
637 this->addScalar(x);
638 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000639 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000640}
641
reed@google.come0d9ce82014-04-23 04:00:17 +0000642void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
643 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000644 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000645
mtklein46616af2014-09-30 14:47:10 -0700646 // op + paint index + length + 'length' worth of data + num points + x&y point data
647 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000648
mtklein46616af2014-09-30 14:47:10 -0700649 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000650
robertphillips@google.com8b169312013-10-15 17:47:36 +0000651 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700652 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700653 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000654 this->addText(text, byteLength);
655 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700656 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000657 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000658}
659
reed@google.come0d9ce82014-04-23 04:00:17 +0000660void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
661 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000662 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000663
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000664 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000665 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000666 // + y + the actual points
667 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000668
mtklein46616af2014-09-30 14:47:10 -0700669 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
670 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000671 this->addText(text, byteLength);
672 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000673 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000674 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000675 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000676}
677
reed@google.come0d9ce82014-04-23 04:00:17 +0000678void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
679 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000680 // op + paint index + length + 'length' worth of data + path index + matrix
681 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000682 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000683 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700684 SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000685 this->addPaint(paint);
686 this->addText(text, byteLength);
687 this->addPath(path);
688 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000689 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000690}
691
fmalitab7425172014-08-26 07:56:44 -0700692void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
693 const SkPaint& paint) {
694
695 // op + paint index + blob index + x/y
696 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
697 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
mtklein8e126562014-10-01 09:29:35 -0700698 SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
fmalitab7425172014-08-26 07:56:44 -0700699
700 this->addPaint(paint);
701 this->addTextBlob(blob);
702 this->addScalar(x);
703 this->addScalar(y);
704
705 this->validate(initialOffset, size);
706}
707
reedd5fa1a42014-08-09 11:08:05 -0700708void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
709 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000710 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000711 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700712 size_t initialOffset;
713
714 if (NULL == matrix && NULL == paint) {
715 initialOffset = this->addDraw(DRAW_PICTURE, &size);
716 this->addPicture(picture);
717 } else {
718 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
719 size += m.writeToMemory(NULL) + kUInt32Size; // matrix + paint
720 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700721 SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
fmalita9f49cfd2014-08-12 12:24:17 -0700722 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700723 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700724 this->addMatrix(m);
725 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700726 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000727 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000728}
729
reed41af9662015-01-05 07:49:08 -0800730void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
731 const SkPoint vertices[], const SkPoint texs[],
732 const SkColor colors[], SkXfermode* xfer,
733 const uint16_t indices[], int indexCount,
734 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000735 uint32_t flags = 0;
736 if (texs) {
737 flags |= DRAW_VERTICES_HAS_TEXS;
738 }
739 if (colors) {
740 flags |= DRAW_VERTICES_HAS_COLORS;
741 }
742 if (indexCount > 0) {
743 flags |= DRAW_VERTICES_HAS_INDICES;
744 }
bsalomon49f085d2014-09-05 13:34:00 -0700745 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000746 SkXfermode::Mode mode;
747 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
748 flags |= DRAW_VERTICES_HAS_XFER;
749 }
750 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000751
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000752 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000753 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000754 if (flags & DRAW_VERTICES_HAS_TEXS) {
755 size += vertexCount * sizeof(SkPoint); // + uvs
756 }
757 if (flags & DRAW_VERTICES_HAS_COLORS) {
758 size += vertexCount * sizeof(SkColor); // + vert colors
759 }
760 if (flags & DRAW_VERTICES_HAS_INDICES) {
761 // + num indices + indices
762 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
763 }
reed@google.com85e143c2013-12-30 15:51:25 +0000764 if (flags & DRAW_VERTICES_HAS_XFER) {
765 size += kUInt32Size; // mode enum
766 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000767
robertphillips@google.com8b169312013-10-15 17:47:36 +0000768 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
mtklein8e126562014-10-01 09:29:35 -0700769 SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000770 this->addPaint(paint);
771 this->addInt(flags);
772 this->addInt(vmode);
773 this->addInt(vertexCount);
774 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000775 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000776 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000777 }
778 if (flags & DRAW_VERTICES_HAS_COLORS) {
779 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
780 }
781 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000782 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000783 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
784 }
reed@google.com85e143c2013-12-30 15:51:25 +0000785 if (flags & DRAW_VERTICES_HAS_XFER) {
786 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
787 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000788 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000789 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000790 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000791}
792
dandovb3c9d1c2014-08-12 08:34:29 -0700793void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
794 const SkPoint texCoords[4], SkXfermode* xmode,
795 const SkPaint& paint) {
796 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
797 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
798 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700799 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700800 flag |= DRAW_VERTICES_HAS_COLORS;
801 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
802 }
bsalomon49f085d2014-09-05 13:34:00 -0700803 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700804 flag |= DRAW_VERTICES_HAS_TEXS;
805 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
806 }
bsalomon49f085d2014-09-05 13:34:00 -0700807 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700808 SkXfermode::Mode mode;
809 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
810 flag |= DRAW_VERTICES_HAS_XFER;
811 size += kUInt32Size;
812 }
813 }
mtklein46616af2014-09-30 14:47:10 -0700814
dandov963137b2014-08-07 07:49:53 -0700815 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
mtklein8e126562014-10-01 09:29:35 -0700816 SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
dandov963137b2014-08-07 07:49:53 -0700817 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700818 this->addPatch(cubics);
819 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700820
dandovb3c9d1c2014-08-12 08:34:29 -0700821 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700822 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700823 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
824 }
bsalomon49f085d2014-09-05 13:34:00 -0700825 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700826 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
827 }
828 if (flag & DRAW_VERTICES_HAS_XFER) {
829 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
830 xmode->asMode(&mode);
831 this->addInt(mode);
832 }
dandov963137b2014-08-07 07:49:53 -0700833 this->validate(initialOffset, size);
834}
835
reed@android.com8a1c16f2008-12-17 15:59:43 +0000836///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000837
reed4a8126e2014-09-22 07:29:03 -0700838SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000839 return NULL;
reed@google.com76f10a32014-02-05 15:32:21 +0000840}
841
mtkleine0694002014-11-12 12:49:47 -0800842// If we already have a stored, can we reuse it instead of also storing b?
843static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
844 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
845 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
846 // but it sure makes things easier to reason about below.
847 return false;
848 }
849 if (a.pixelRef() == b.pixelRef()) {
850 return true; // Same shape and same pixels -> same bitmap.
851 }
852
853 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
854 if (!a.pixelRef() || !b.pixelRef()) {
855 return false;
856 }
857
858 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
859 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
860 encB(b.pixelRef()->refEncodedData());
861 if (encA && encB) {
862 return encA->equals(encB);
863 } else if (encA || encB) {
864 return false; // One has encoded data but the other does not.
865 }
866
867 // As a last resort, we have to look at the pixels. This will read back textures.
868 SkAutoLockPixels al(a), bl(b);
869 const char* ap = (const char*)a.getPixels();
870 const char* bp = (const char*)b.getPixels();
871 if (ap && bp) {
872 // We check row by row; row bytes might differ.
873 SkASSERT(a.info() == b.info()); // We checked this above.
874 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
875 const SkImageInfo info = a.info();
876 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
877 for (int row = 0; row < info.height(); row++) {
878 if (0 != memcmp(ap, bp, bytesToCompare)) {
879 return false;
880 }
881 ap += a.rowBytes();
882 bp += b.rowBytes();
883 }
884 return true;
885 }
886 return false; // Couldn't get pixels for both bitmaps.
887}
888
889void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
890 // First see if we already have this bitmap. This deduplication should really
891 // only be important for our tests, where bitmaps tend not to be tagged immutable.
892 // In Chrome (and hopefully Android?) they're typically immutable.
893 for (int i = 0; i < fBitmaps.count(); i++) {
894 if (equivalent(fBitmaps[i], bitmap)) {
895 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
896 return;
897 }
898 }
899 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800900 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800901 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800902 fBitmaps.push_back(bitmap);
903 } else {
mtkleine0694002014-11-12 12:49:47 -0800904 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800905 SkBitmap copy;
906 bitmap.copyTo(&copy);
907 copy.setImmutable();
908 fBitmaps.push_back(copy);
909 }
mtkleine0694002014-11-12 12:49:47 -0800910 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000911}
912
reed871872f2015-06-22 12:48:26 -0700913void SkPictureRecord::addImage(const SkImage* image) {
914 int index = fImageRefs.find(image);
915 if (index >= 0) {
916 this->addInt(index);
917 } else {
918 *fImageRefs.append() = SkRef(image);
919 this->addInt(fImageRefs.count()-1);
920 }
921}
922
reed@android.com8a1c16f2008-12-17 15:59:43 +0000923void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000924 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000925}
926
mtklein46616af2014-09-30 14:47:10 -0700927void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700928 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000929
mtklein46616af2014-09-30 14:47:10 -0700930 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800931 fPaints.push_back(*paint);
932 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700933 } else {
934 this->addInt(0);
935 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000936}
937
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000938int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtklein71a23632014-11-12 10:24:55 -0800939 fPaths.push_back(path);
940 return fPaths.count();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000941}
942
943void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000944 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000945}
946
dandovb3c9d1c2014-08-12 08:34:29 -0700947void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
948 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700949}
950
robertphillips9b14f262014-06-04 05:40:44 -0700951void SkPictureRecord::addPicture(const SkPicture* picture) {
952 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000953 if (index < 0) { // not found
954 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700955 *fPictureRefs.append() = picture;
956 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000957 }
958 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000959 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000960}
961
962void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000963 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000964}
reed@google.com82065d62011-02-07 15:30:46 +0000965
reed@android.com8a1c16f2008-12-17 15:59:43 +0000966void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
967 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000968}
969
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000970void SkPictureRecord::addNoOp() {
971 size_t size = kUInt32Size; // op
972 this->addDraw(NOOP, &size);
973}
974
reed@android.com8a1c16f2008-12-17 15:59:43 +0000975void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000976 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000977}
978
979void SkPictureRecord::addRectPtr(const SkRect* rect) {
980 if (fWriter.writeBool(rect != NULL)) {
981 fWriter.writeRect(*rect);
982 }
983}
984
reed@google.comf0b5e112011-09-07 11:57:34 +0000985void SkPictureRecord::addIRect(const SkIRect& rect) {
986 fWriter.write(&rect, sizeof(rect));
987}
988
reed@android.com8a1c16f2008-12-17 15:59:43 +0000989void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
990 if (fWriter.writeBool(rect != NULL)) {
991 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
992 }
993}
994
reed@google.com4ed0fb72012-12-12 20:48:18 +0000995void SkPictureRecord::addRRect(const SkRRect& rrect) {
996 fWriter.writeRRect(rrect);
997}
998
reed@android.com8a1c16f2008-12-17 15:59:43 +0000999void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001000 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001001}
1002
1003void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001004 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001005 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001006 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001007}
1008
fmalitab7425172014-08-26 07:56:44 -07001009void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001010 int index = fTextBlobRefs.count();
1011 *fTextBlobRefs.append() = blob;
1012 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001013 // follow the convention of recording a 1-based index
1014 this->addInt(index + 1);
1015}
1016
reed@android.com8a1c16f2008-12-17 15:59:43 +00001017///////////////////////////////////////////////////////////////////////////////
1018