blob: 07811fb1280513e597669f71c2de7b66ad2370ed [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
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);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000154
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000155 this->INHERITED::willSaveLayer(bounds, paint, flags);
156 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000157 at this time (and may not be able to afford since during record our
158 clip starts out the size of the picture, which is often much larger
159 than the size of the actual device we'll use during playback).
160 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000161 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000162}
163
164void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000165 SaveFlags flags) {
robertphillipsc019ec42014-08-12 05:35:58 -0700166 fContentInfo.onSaveLayer();
167
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000168 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000169 size_t size = 2 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700170 if (bounds) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000171 size += sizeof(*bounds); // + rect
172 }
173 // + paint index + flags
174 size += 2 * kUInt32Size;
175
robertphillips@google.come37ad352013-03-01 19:44:30 +0000176 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
177
robertphillips@google.com8b169312013-10-15 17:47:36 +0000178 size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000179 this->addRectPtr(bounds);
mtklein8e126562014-10-01 09:29:35 -0700180 SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000181 this->addPaintPtr(paint);
182 this->addInt(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000183
robertphillips@google.com8b169312013-10-15 17:47:36 +0000184 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185}
186
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000187#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000188/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000189 * Read the op code from 'offset' in 'writer' and extract the size too.
190 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000191static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000192 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000193
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000194 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000195 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000196 if (MASK_24 == *size) {
197 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000198 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000199 }
200 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000201}
mtklein46616af2014-09-30 14:47:10 -0700202#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000203
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000204void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000205 // FIXME: SkDeferredCanvas needs to be refactored to respect
206 // save/restore balancing so that the following test can be
207 // turned on permanently.
208#if 0
209 SkASSERT(fRestoreOffsetStack.count() > 1);
210#endif
211
reed@android.comb4e22d62009-07-09 15:20:25 +0000212 // check for underflow
213 if (fRestoreOffsetStack.count() == 0) {
214 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000215 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000216
mtklein46616af2014-09-30 14:47:10 -0700217 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000218
reed@android.comb4e22d62009-07-09 15:20:25 +0000219 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000220
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000221 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222}
223
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000224void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700225 fContentInfo.onRestore();
226
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000227 if (fillInSkips) {
228 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
229 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000230 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
231 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000232 this->validate(initialOffset, size);
233}
234
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000235void SkPictureRecord::recordTranslate(const SkMatrix& m) {
236 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
237
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000238 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000239 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000240 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000241 this->addScalar(m.getTranslateX());
242 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000243 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244}
245
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000246void SkPictureRecord::recordScale(const SkMatrix& m) {
247 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000248
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000249 // op + sx + sy
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(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000252 this->addScalar(m.getScaleX());
253 this->addScalar(m.getScaleY());
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.org44c48d02014-03-13 20:03:58 +0000257void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000258 switch (matrix.getType()) {
259 case SkMatrix::kTranslate_Mask:
260 this->recordTranslate(matrix);
261 break;
262 case SkMatrix::kScale_Mask:
263 this->recordScale(matrix);
264 break;
265 default:
266 this->recordConcat(matrix);
267 break;
268 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000269 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000270}
271
272void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000273 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000274 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000275 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000276 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000277 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000278 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000279}
280
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000281void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000282 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000283 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000284 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000285 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000286 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000287 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000288 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000289}
290
reed@google.com45482d12011-08-29 19:02:39 +0000291static bool regionOpExpands(SkRegion::Op op) {
292 switch (op) {
293 case SkRegion::kUnion_Op:
294 case SkRegion::kXOR_Op:
295 case SkRegion::kReverseDifference_Op:
296 case SkRegion::kReplace_Op:
297 return true;
298 case SkRegion::kIntersect_Op:
299 case SkRegion::kDifference_Op:
300 return false;
301 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000302 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000303 return false;
304 }
305}
306
robertphillips@google.come37ad352013-03-01 19:44:30 +0000307void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000308 int32_t offset = fRestoreOffsetStack.top();
309 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000310 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
311 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000312 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000313 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000314
reed@google.comffacd3c2012-08-30 15:31:23 +0000315#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800316 // offset of 0 has been disabled, so we skip it
317 if (offset > 0) {
318 // assert that the final offset value points to a save verb
319 uint32_t opSize;
320 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
321 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
322 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000323#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000324}
325
reed@google.comd86e7ab2012-09-27 20:31:31 +0000326void SkPictureRecord::beginRecording() {
327 // we have to call this *after* our constructor, to ensure that it gets
328 // recorded. This is balanced by restoreToCount() call from endRecording,
329 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000330 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000331}
332
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000333void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000334 SkASSERT(kNoInitialSave != fInitialSaveCount);
335 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000336}
337
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000338size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000339 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000340 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000341 }
342
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000343 // The RestoreOffset field is initially filled with a placeholder
344 // value that points to the offset of the previous RestoreOffset
345 // in the current stack level, thus forming a linked list so that
346 // the restore offsets can be filled in when the corresponding
347 // restore command is recorded.
348 int32_t prevOffset = fRestoreOffsetStack.top();
349
reed@google.com45482d12011-08-29 19:02:39 +0000350 if (regionOpExpands(op)) {
351 // Run back through any previous clip ops, and mark their offset to
352 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
353 // they could hide this clips ability to expand the clip (i.e. go from
354 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000355 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000356
357 // Reset the pointer back to the previous clip so that subsequent
358 // restores don't overwrite the offsets we just cleared.
359 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000360 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000361
reed@google.com44699382013-10-31 17:28:30 +0000362 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000363 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000364 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000365 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000366}
367
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000368void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000369 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000370 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000371}
372
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000373size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000374 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000375 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000376 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000377 if (!fRestoreOffsetStack.isEmpty()) {
378 // + restore offset
379 size += kUInt32Size;
380 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000381 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000382 this->addRect(rect);
383 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000384 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000385
robertphillips@google.com8b169312013-10-15 17:47:36 +0000386 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000387 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000388}
389
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000390void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000391 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700392 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000393}
394
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000395size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000396 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000397 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000398 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000399 if (!fRestoreOffsetStack.isEmpty()) {
400 // + restore offset
401 size += kUInt32Size;
402 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000403 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000404 this->addRRect(rrect);
405 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000406 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000407 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000408 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000409}
410
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000411void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000412 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000413 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700414 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000415}
416
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000417size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000418 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000419 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000420 // recordRestoreOffsetPlaceholder doesn't always write an offset
421 if (!fRestoreOffsetStack.isEmpty()) {
422 // + restore offset
423 size += kUInt32Size;
424 }
425 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000426 this->addInt(pathID);
427 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000428 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000429 this->validate(initialOffset, size);
430 return offset;
431}
432
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000433void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000434 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000435 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000436}
437
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000438size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000439 // op + clip params + region
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000440 size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000441 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000442 if (!fRestoreOffsetStack.isEmpty()) {
443 // + restore offset
444 size += kUInt32Size;
445 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000446 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000447 this->addRegion(region);
448 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000449 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000450
robertphillips@google.com8b169312013-10-15 17:47:36 +0000451 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000452 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000453}
454
reed41af9662015-01-05 07:49:08 -0800455void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000456 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000457 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000458 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700459 SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000460 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000461 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000462}
463
reed41af9662015-01-05 07:49:08 -0800464void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
465 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700466 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000467
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000468 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000469 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000470 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
mtklein8e126562014-10-01 09:29:35 -0700471 SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000472 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700473
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000474 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000475 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000476 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000477 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000478}
479
reed41af9662015-01-05 07:49:08 -0800480void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000481 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000482 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000483 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
mtklein8e126562014-10-01 09:29:35 -0700484 SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000485 this->addPaint(paint);
486 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000487 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000488}
489
reed41af9662015-01-05 07:49:08 -0800490void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000491 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000492 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000493 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700494 SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000495 this->addPaint(paint);
496 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000497 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000498}
499
reed41af9662015-01-05 07:49:08 -0800500void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700501 // op + paint index + rrect
502 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
503 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700504 SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700505 this->addPaint(paint);
506 this->addRRect(rrect);
507 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000508}
509
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000510void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
511 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000512 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000513 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
514 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700515 SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000516 this->addPaint(paint);
517 this->addRRect(outer);
518 this->addRRect(inner);
519 this->validate(initialOffset, size);
520}
521
reed41af9662015-01-05 07:49:08 -0800522void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700523 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000524
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000525 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000526 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000527 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700528 SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000529 this->addPaint(paint);
530 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000531 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000532}
533
reed41af9662015-01-05 07:49:08 -0800534void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
535 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000536 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000537 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000538 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
mtklein8e126562014-10-01 09:29:35 -0700539 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000540 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000541 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000542 this->addScalar(left);
543 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000544 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000545}
546
reed41af9662015-01-05 07:49:08 -0800547void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
548 const SkPaint* paint, DrawBitmapRectFlags flags) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000549 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000550 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700551 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000552 size += sizeof(*src); // + rect
553 }
554 size += sizeof(dst); // + rect
555
robertphillips@google.com8b169312013-10-15 17:47:36 +0000556 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700557 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT_TO_RECT, size)
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000558 == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000559 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000560 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000561 this->addRectPtr(src); // may be null
562 this->addRect(dst);
563 this->addInt(flags);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000564 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000565}
566
reeda85d4d02015-05-06 12:56:48 -0700567void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
568 const SkPaint* paint) {
569 SkBitmap bm;
570 if (as_IB(image)->getROPixels(&bm)) {
571 this->SkPictureRecord::onDrawBitmap(bm, x, y, paint);
572 }
573}
574
575void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
576 const SkPaint* paint) {
577 SkBitmap bm;
578 if (as_IB(image)->getROPixels(&bm)) {
579 this->SkPictureRecord::onDrawBitmapRect(bm, src, dst, paint, kNone_DrawBitmapRectFlag);
580 }
581}
582
reed41af9662015-01-05 07:49:08 -0800583void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
584 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000585 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000586 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000587 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
mtklein8e126562014-10-01 09:29:35 -0700588 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000589 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000590 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000591 this->addIRect(center);
592 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000593 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000594}
595
reed41af9662015-01-05 07:49:08 -0800596void SkPictureRecord::onDrawSprite(const SkBitmap& bitmap, int left, int top,
597 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000598 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000599 size_t size = 5 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000600 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
mtklein8e126562014-10-01 09:29:35 -0700601 SkASSERT(initialOffset+get_paint_offset(DRAW_SPRITE, 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->addInt(left);
605 this->addInt(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000606 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000607}
608
reed@google.come0d9ce82014-04-23 04:00:17 +0000609void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
610 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000611 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000612 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000613
mtklein46616af2014-09-30 14:47:10 -0700614 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000615 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700616 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700617 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000618 this->addText(text, byteLength);
619 this->addScalar(x);
620 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000621 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000622}
623
reed@google.come0d9ce82014-04-23 04:00:17 +0000624void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
625 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000626 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000627
mtklein46616af2014-09-30 14:47:10 -0700628 // op + paint index + length + 'length' worth of data + num points + x&y point data
629 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000630
mtklein46616af2014-09-30 14:47:10 -0700631 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000632
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->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700638 fWriter.writeMul4(pos, points * sizeof(SkPoint));
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::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
643 SkScalar constY, 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
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000646 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000647 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000648 // + y + the actual points
649 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000650
mtklein46616af2014-09-30 14:47:10 -0700651 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
652 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000653 this->addText(text, byteLength);
654 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000655 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000656 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
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::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
661 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000662 // op + paint index + length + 'length' worth of data + path index + matrix
663 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000664 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000665 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700666 SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000667 this->addPaint(paint);
668 this->addText(text, byteLength);
669 this->addPath(path);
670 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000671 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000672}
673
fmalitab7425172014-08-26 07:56:44 -0700674void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
675 const SkPaint& paint) {
676
677 // op + paint index + blob index + x/y
678 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
679 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
mtklein8e126562014-10-01 09:29:35 -0700680 SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
fmalitab7425172014-08-26 07:56:44 -0700681
682 this->addPaint(paint);
683 this->addTextBlob(blob);
684 this->addScalar(x);
685 this->addScalar(y);
686
687 this->validate(initialOffset, size);
688}
689
reedd5fa1a42014-08-09 11:08:05 -0700690void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
691 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000692 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000693 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700694 size_t initialOffset;
695
696 if (NULL == matrix && NULL == paint) {
697 initialOffset = this->addDraw(DRAW_PICTURE, &size);
698 this->addPicture(picture);
699 } else {
700 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
701 size += m.writeToMemory(NULL) + kUInt32Size; // matrix + paint
702 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700703 SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
fmalita9f49cfd2014-08-12 12:24:17 -0700704 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700705 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700706 this->addMatrix(m);
707 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700708 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000709 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000710}
711
reed41af9662015-01-05 07:49:08 -0800712void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
713 const SkPoint vertices[], const SkPoint texs[],
714 const SkColor colors[], SkXfermode* xfer,
715 const uint16_t indices[], int indexCount,
716 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000717 uint32_t flags = 0;
718 if (texs) {
719 flags |= DRAW_VERTICES_HAS_TEXS;
720 }
721 if (colors) {
722 flags |= DRAW_VERTICES_HAS_COLORS;
723 }
724 if (indexCount > 0) {
725 flags |= DRAW_VERTICES_HAS_INDICES;
726 }
bsalomon49f085d2014-09-05 13:34:00 -0700727 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000728 SkXfermode::Mode mode;
729 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
730 flags |= DRAW_VERTICES_HAS_XFER;
731 }
732 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000733
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000734 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000735 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000736 if (flags & DRAW_VERTICES_HAS_TEXS) {
737 size += vertexCount * sizeof(SkPoint); // + uvs
738 }
739 if (flags & DRAW_VERTICES_HAS_COLORS) {
740 size += vertexCount * sizeof(SkColor); // + vert colors
741 }
742 if (flags & DRAW_VERTICES_HAS_INDICES) {
743 // + num indices + indices
744 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
745 }
reed@google.com85e143c2013-12-30 15:51:25 +0000746 if (flags & DRAW_VERTICES_HAS_XFER) {
747 size += kUInt32Size; // mode enum
748 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000749
robertphillips@google.com8b169312013-10-15 17:47:36 +0000750 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
mtklein8e126562014-10-01 09:29:35 -0700751 SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000752 this->addPaint(paint);
753 this->addInt(flags);
754 this->addInt(vmode);
755 this->addInt(vertexCount);
756 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000757 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000758 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000759 }
760 if (flags & DRAW_VERTICES_HAS_COLORS) {
761 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
762 }
763 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000764 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000765 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
766 }
reed@google.com85e143c2013-12-30 15:51:25 +0000767 if (flags & DRAW_VERTICES_HAS_XFER) {
768 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
769 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000770 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000771 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000772 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000773}
774
dandovb3c9d1c2014-08-12 08:34:29 -0700775void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
776 const SkPoint texCoords[4], SkXfermode* xmode,
777 const SkPaint& paint) {
778 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
779 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
780 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700781 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700782 flag |= DRAW_VERTICES_HAS_COLORS;
783 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
784 }
bsalomon49f085d2014-09-05 13:34:00 -0700785 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700786 flag |= DRAW_VERTICES_HAS_TEXS;
787 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
788 }
bsalomon49f085d2014-09-05 13:34:00 -0700789 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700790 SkXfermode::Mode mode;
791 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
792 flag |= DRAW_VERTICES_HAS_XFER;
793 size += kUInt32Size;
794 }
795 }
mtklein46616af2014-09-30 14:47:10 -0700796
dandov963137b2014-08-07 07:49:53 -0700797 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
mtklein8e126562014-10-01 09:29:35 -0700798 SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
dandov963137b2014-08-07 07:49:53 -0700799 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700800 this->addPatch(cubics);
801 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700802
dandovb3c9d1c2014-08-12 08:34:29 -0700803 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700804 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700805 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
806 }
bsalomon49f085d2014-09-05 13:34:00 -0700807 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700808 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
809 }
810 if (flag & DRAW_VERTICES_HAS_XFER) {
811 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
812 xmode->asMode(&mode);
813 this->addInt(mode);
814 }
dandov963137b2014-08-07 07:49:53 -0700815 this->validate(initialOffset, size);
816}
817
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000818void SkPictureRecord::beginCommentGroup(const char* description) {
819 // op/size + length of string + \0 terminated chars
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000820 size_t length = strlen(description);
821 size_t size = 2 * kUInt32Size + SkAlign4(length + 1);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000822 size_t initialOffset = this->addDraw(BEGIN_COMMENT_GROUP, &size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000823 fWriter.writeString(description, length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000824 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000825}
826
827void SkPictureRecord::addComment(const char* kywd, const char* value) {
828 // op/size + 2x length of string + 2x \0 terminated chars
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000829 size_t kywdLen = strlen(kywd);
830 size_t valueLen = strlen(value);
831 size_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000832 size_t initialOffset = this->addDraw(COMMENT, &size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000833 fWriter.writeString(kywd, kywdLen);
834 fWriter.writeString(value, valueLen);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000835 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000836}
837
838void SkPictureRecord::endCommentGroup() {
839 // op/size
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000840 size_t size = 1 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000841 size_t initialOffset = this->addDraw(END_COMMENT_GROUP, &size);
842 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000843}
844
reed@android.com8a1c16f2008-12-17 15:59:43 +0000845///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000846
reed4a8126e2014-09-22 07:29:03 -0700847SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000848 return NULL;
reed@google.com76f10a32014-02-05 15:32:21 +0000849}
850
mtkleine0694002014-11-12 12:49:47 -0800851// If we already have a stored, can we reuse it instead of also storing b?
852static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
853 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
854 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
855 // but it sure makes things easier to reason about below.
856 return false;
857 }
858 if (a.pixelRef() == b.pixelRef()) {
859 return true; // Same shape and same pixels -> same bitmap.
860 }
861
862 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
863 if (!a.pixelRef() || !b.pixelRef()) {
864 return false;
865 }
866
867 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
868 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
869 encB(b.pixelRef()->refEncodedData());
870 if (encA && encB) {
871 return encA->equals(encB);
872 } else if (encA || encB) {
873 return false; // One has encoded data but the other does not.
874 }
875
876 // As a last resort, we have to look at the pixels. This will read back textures.
877 SkAutoLockPixels al(a), bl(b);
878 const char* ap = (const char*)a.getPixels();
879 const char* bp = (const char*)b.getPixels();
880 if (ap && bp) {
881 // We check row by row; row bytes might differ.
882 SkASSERT(a.info() == b.info()); // We checked this above.
883 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
884 const SkImageInfo info = a.info();
885 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
886 for (int row = 0; row < info.height(); row++) {
887 if (0 != memcmp(ap, bp, bytesToCompare)) {
888 return false;
889 }
890 ap += a.rowBytes();
891 bp += b.rowBytes();
892 }
893 return true;
894 }
895 return false; // Couldn't get pixels for both bitmaps.
896}
897
898void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
899 // First see if we already have this bitmap. This deduplication should really
900 // only be important for our tests, where bitmaps tend not to be tagged immutable.
901 // In Chrome (and hopefully Android?) they're typically immutable.
902 for (int i = 0; i < fBitmaps.count(); i++) {
903 if (equivalent(fBitmaps[i], bitmap)) {
904 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
905 return;
906 }
907 }
908 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800909 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800910 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800911 fBitmaps.push_back(bitmap);
912 } else {
mtkleine0694002014-11-12 12:49:47 -0800913 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800914 SkBitmap copy;
915 bitmap.copyTo(&copy);
916 copy.setImmutable();
917 fBitmaps.push_back(copy);
918 }
mtkleine0694002014-11-12 12:49:47 -0800919 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000920}
921
922void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000923 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000924}
925
mtklein46616af2014-09-30 14:47:10 -0700926void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700927 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000928
mtklein46616af2014-09-30 14:47:10 -0700929 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800930 fPaints.push_back(*paint);
931 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700932 } else {
933 this->addInt(0);
934 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000935}
936
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000937int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtklein71a23632014-11-12 10:24:55 -0800938 fPaths.push_back(path);
939 return fPaths.count();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000940}
941
942void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000943 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000944}
945
dandovb3c9d1c2014-08-12 08:34:29 -0700946void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
947 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700948}
949
robertphillips9b14f262014-06-04 05:40:44 -0700950void SkPictureRecord::addPicture(const SkPicture* picture) {
951 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000952 if (index < 0) { // not found
953 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700954 *fPictureRefs.append() = picture;
955 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000956 }
957 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000958 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000959}
960
961void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000962 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000963}
reed@google.com82065d62011-02-07 15:30:46 +0000964
reed@android.com8a1c16f2008-12-17 15:59:43 +0000965void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
966 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000967}
968
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000969void SkPictureRecord::addNoOp() {
970 size_t size = kUInt32Size; // op
971 this->addDraw(NOOP, &size);
972}
973
reed@android.com8a1c16f2008-12-17 15:59:43 +0000974void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000975 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000976}
977
978void SkPictureRecord::addRectPtr(const SkRect* rect) {
979 if (fWriter.writeBool(rect != NULL)) {
980 fWriter.writeRect(*rect);
981 }
982}
983
reed@google.comf0b5e112011-09-07 11:57:34 +0000984void SkPictureRecord::addIRect(const SkIRect& rect) {
985 fWriter.write(&rect, sizeof(rect));
986}
987
reed@android.com8a1c16f2008-12-17 15:59:43 +0000988void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
989 if (fWriter.writeBool(rect != NULL)) {
990 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
991 }
992}
993
reed@google.com4ed0fb72012-12-12 20:48:18 +0000994void SkPictureRecord::addRRect(const SkRRect& rrect) {
995 fWriter.writeRRect(rrect);
996}
997
reed@android.com8a1c16f2008-12-17 15:59:43 +0000998void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000999 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001000}
1001
1002void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001003 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001004 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001005 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001006}
1007
fmalitab7425172014-08-26 07:56:44 -07001008void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001009 int index = fTextBlobRefs.count();
1010 *fTextBlobRefs.append() = blob;
1011 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001012 // follow the convention of recording a 1-based index
1013 this->addInt(index + 1);
1014}
1015
reed@android.com8a1c16f2008-12-17 15:59:43 +00001016///////////////////////////////////////////////////////////////////////////////
1017