blob: 0383dda3d519fe5ef38586eb2de9190b4782b555 [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"
reed71c3c762015-06-24 10:29:17 -070014#include "SkRSXform.h"
fmalitab7425172014-08-26 07:56:44 -070015#include "SkTextBlob.h"
dandovb3c9d1c2014-08-12 08:34:29 -070016#include "SkTSearch.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017
reed@android.com8a1c16f2008-12-17 15:59:43 +000018#define HEAP_BLOCK_SIZE 4096
19
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000020enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000021 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000022 kNoInitialSave = -1,
23};
24
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000025// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
26static int const kUInt32Size = 4;
27
Florin Malita5f6102d2014-06-30 10:13:28 -040028static const uint32_t kSaveSize = kUInt32Size;
mtklein8e126562014-10-01 09:29:35 -070029#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000030static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
31static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
mtklein8e126562014-10-01 09:29:35 -070032#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000033
robertphillips0bdbea72014-06-11 11:37:55 -070034SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000035 : INHERITED(dimensions.width(), dimensions.height())
mtklein71a23632014-11-12 10:24:55 -080036 , fRecordFlags(flags)
37 , fInitialSaveCount(kNoInitialSave) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000038}
39
40SkPictureRecord::~SkPictureRecord() {
robertphillips5351aad2015-06-23 06:54:56 -070041 fImageRefs.unrefAll();
djsollen@google.com21830d92012-08-07 19:49:41 +000042 fPictureRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070043 fTextBlobRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000044}
45
46///////////////////////////////////////////////////////////////////////////////
47
mtklein8e126562014-10-01 09:29:35 -070048#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000049// Return the offset of the paint inside a given op's byte stream. A zero
50// return value means there is no paint (and you really shouldn't be calling
51// this method)
mtklein8e126562014-10-01 09:29:35 -070052static inline size_t get_paint_offset(DrawType op, size_t opSize) {
robertphillips@google.come37ad352013-03-01 19:44:30 +000053 // These offsets are where the paint would be if the op size doesn't overflow
fmalita9f49cfd2014-08-12 12:24:17 -070054 static const uint8_t gPaintOffsets[] = {
robertphillips@google.come37ad352013-03-01 19:44:30 +000055 0, // UNUSED - no paint
56 0, // CLIP_PATH - no paint
57 0, // CLIP_REGION - no paint
58 0, // CLIP_RECT - no paint
59 0, // CLIP_RRECT - no paint
60 0, // CONCAT - no paint
61 1, // DRAW_BITMAP - right after op code
Florin Malitac54d8db2014-12-10 12:02:16 -050062 1, // DRAW_BITMAP_MATRIX - right after op code, deprecated
robertphillips@google.come37ad352013-03-01 19:44:30 +000063 1, // DRAW_BITMAP_NINE - right after op code
reeda5517e22015-07-14 10:54:12 -070064 1, // DRAW_BITMAP_RECT - right after op code
robertphillips@google.come37ad352013-03-01 19:44:30 +000065 0, // DRAW_CLEAR - no paint
66 0, // DRAW_DATA - no paint
67 1, // DRAW_OVAL - right after op code
68 1, // DRAW_PAINT - right after op code
69 1, // DRAW_PATH - right after op code
70 0, // DRAW_PICTURE - no paint
71 1, // DRAW_POINTS - right after op code
72 1, // DRAW_POS_TEXT - right after op code
73 1, // DRAW_POS_TEXT_TOP_BOTTOM - right after op code
74 1, // DRAW_POS_TEXT_H - right after op code
75 1, // DRAW_POS_TEXT_H_TOP_BOTTOM - right after op code
76 1, // DRAW_RECT - right after op code
77 1, // DRAW_RRECT - right after op code
78 1, // DRAW_SPRITE - right after op code
79 1, // DRAW_TEXT - right after op code
80 1, // DRAW_TEXT_ON_PATH - right after op code
81 1, // DRAW_TEXT_TOP_BOTTOM - right after op code
82 1, // DRAW_VERTICES - right after op code
83 0, // RESTORE - no paint
84 0, // ROTATE - no paint
85 0, // SAVE - no paint
skia.committer@gmail.comf140f182013-03-02 07:01:56 +000086 0, // SAVE_LAYER - see below - this paint's location varies
robertphillips@google.come37ad352013-03-01 19:44:30 +000087 0, // SCALE - no paint
88 0, // SET_MATRIX - no paint
89 0, // SKEW - no paint
90 0, // TRANSLATE - no paint
91 0, // NOOP - no paint
robertphillips@google.com0a4805e2013-05-29 13:24:23 +000092 0, // BEGIN_GROUP - no paint
93 0, // COMMENT - no paint
94 0, // END_GROUP - no paint
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +000095 1, // DRAWDRRECT - right after op code
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +000096 0, // PUSH_CULL - no paint
97 0, // POP_CULL - no paint
dandov963137b2014-08-07 07:49:53 -070098 1, // DRAW_PATCH - right after op code
fmalita9f49cfd2014-08-12 12:24:17 -070099 1, // DRAW_PICTURE_MATRIX_PAINT - right after op code
fmalitab7425172014-08-26 07:56:44 -0700100 1, // DRAW_TEXT_BLOB- right after op code
reed871872f2015-06-22 12:48:26 -0700101 1, // DRAW_IMAGE - right after op code
reeda5517e22015-07-14 10:54:12 -0700102 1, // DRAW_IMAGE_RECT_STRICT - right after op code
reed71c3c762015-06-24 10:29:17 -0700103 1, // DRAW_ATLAS - right after op code
reed4c21dc52015-06-25 12:32:03 -0700104 1, // DRAW_IMAGE_NINE - right after op code
reeda5517e22015-07-14 10:54:12 -0700105 1, // DRAW_IMAGE_RECT - right after op code
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000106 };
robertphillips@google.come37ad352013-03-01 19:44:30 +0000107
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000108 SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
109 need_to_be_in_sync);
robertphillips@google.come37ad352013-03-01 19:44:30 +0000110 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
111
112 int overflow = 0;
113 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
114 // This op's size overflows so an extra uint32_t will be written
115 // after the op code
116 overflow = sizeof(uint32_t);
117 }
118
119 if (SAVE_LAYER == op) {
120 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
121 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
122
123 if (kSaveLayerNoBoundsSize == opSize) {
124 return kSaveLayerNoBoundsPaintOffset + overflow;
125 } else {
126 SkASSERT(kSaveLayerWithBoundsSize == opSize);
127 return kSaveLayerWithBoundsPaintOffset + overflow;
128 }
129 }
130
131 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this method
132 return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
133}
mtklein8e126562014-10-01 09:29:35 -0700134#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +0000135
Florin Malita5f6102d2014-06-30 10:13:28 -0400136void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +0000137 // record the offset to us, making it non-positive to distinguish a save
138 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000139 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -0400140 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000141
Florin Malita5f6102d2014-06-30 10:13:28 -0400142 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000143}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000144
Florin Malita5f6102d2014-06-30 10:13:28 -0400145void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -0700146 fContentInfo.onSave();
147
Florin Malita5f6102d2014-06-30 10:13:28 -0400148 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000149 size_t size = kSaveSize;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000150 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +0000151
robertphillips@google.com8b169312013-10-15 17:47:36 +0000152 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000153}
154
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000155SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
156 const SkPaint* paint, SaveFlags flags) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000157 // record the offset to us, making it non-positive to distinguish a save
158 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000159 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000160 this->recordSaveLayer(bounds, paint, flags);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000161
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000162 this->INHERITED::willSaveLayer(bounds, paint, flags);
163 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000164 at this time (and may not be able to afford since during record our
165 clip starts out the size of the picture, which is often much larger
166 than the size of the actual device we'll use during playback).
167 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000168 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000169}
170
171void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000172 SaveFlags flags) {
robertphillipsc019ec42014-08-12 05:35:58 -0700173 fContentInfo.onSaveLayer();
174
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000175 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000176 size_t size = 2 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700177 if (bounds) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000178 size += sizeof(*bounds); // + rect
179 }
180 // + paint index + flags
181 size += 2 * kUInt32Size;
182
robertphillips@google.come37ad352013-03-01 19:44:30 +0000183 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
184
robertphillips@google.com8b169312013-10-15 17:47:36 +0000185 size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000186 this->addRectPtr(bounds);
mtklein8e126562014-10-01 09:29:35 -0700187 SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000188 this->addPaintPtr(paint);
189 this->addInt(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000190
robertphillips@google.com8b169312013-10-15 17:47:36 +0000191 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192}
193
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000194#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000195/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000196 * Read the op code from 'offset' in 'writer' and extract the size too.
197 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000198static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000199 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000200
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000201 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000202 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000203 if (MASK_24 == *size) {
204 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000205 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000206 }
207 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000208}
mtklein46616af2014-09-30 14:47:10 -0700209#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000210
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000211void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000212 // FIXME: SkDeferredCanvas needs to be refactored to respect
213 // save/restore balancing so that the following test can be
214 // turned on permanently.
215#if 0
216 SkASSERT(fRestoreOffsetStack.count() > 1);
217#endif
218
reed@android.comb4e22d62009-07-09 15:20:25 +0000219 // check for underflow
220 if (fRestoreOffsetStack.count() == 0) {
221 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000223
mtklein46616af2014-09-30 14:47:10 -0700224 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000225
reed@android.comb4e22d62009-07-09 15:20:25 +0000226 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000227
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000228 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000229}
230
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000231void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700232 fContentInfo.onRestore();
233
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000234 if (fillInSkips) {
235 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
236 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000237 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
238 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000239 this->validate(initialOffset, size);
240}
241
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000242void SkPictureRecord::recordTranslate(const SkMatrix& m) {
243 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
244
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000245 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000246 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000247 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000248 this->addScalar(m.getTranslateX());
249 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000250 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251}
252
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000253void SkPictureRecord::recordScale(const SkMatrix& m) {
254 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000255
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000256 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000257 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000258 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000259 this->addScalar(m.getScaleX());
260 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000261 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000262}
263
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000264void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000265 switch (matrix.getType()) {
266 case SkMatrix::kTranslate_Mask:
267 this->recordTranslate(matrix);
268 break;
269 case SkMatrix::kScale_Mask:
270 this->recordScale(matrix);
271 break;
272 default:
273 this->recordConcat(matrix);
274 break;
275 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000276 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000277}
278
279void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000280 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000281 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000282 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000283 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000284 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000285 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000286}
287
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000288void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000289 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000290 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000291 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000292 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000293 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000294 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000295 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000296}
297
reed@google.com45482d12011-08-29 19:02:39 +0000298static bool regionOpExpands(SkRegion::Op op) {
299 switch (op) {
300 case SkRegion::kUnion_Op:
301 case SkRegion::kXOR_Op:
302 case SkRegion::kReverseDifference_Op:
303 case SkRegion::kReplace_Op:
304 return true;
305 case SkRegion::kIntersect_Op:
306 case SkRegion::kDifference_Op:
307 return false;
308 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000309 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000310 return false;
311 }
312}
313
robertphillips@google.come37ad352013-03-01 19:44:30 +0000314void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000315 int32_t offset = fRestoreOffsetStack.top();
316 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000317 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
318 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000319 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000320 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000321
reed@google.comffacd3c2012-08-30 15:31:23 +0000322#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800323 // offset of 0 has been disabled, so we skip it
324 if (offset > 0) {
325 // assert that the final offset value points to a save verb
326 uint32_t opSize;
327 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
328 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
329 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000330#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000331}
332
reed@google.comd86e7ab2012-09-27 20:31:31 +0000333void SkPictureRecord::beginRecording() {
334 // we have to call this *after* our constructor, to ensure that it gets
335 // recorded. This is balanced by restoreToCount() call from endRecording,
336 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000337 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000338}
339
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000340void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000341 SkASSERT(kNoInitialSave != fInitialSaveCount);
342 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000343}
344
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000345size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000346 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000347 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000348 }
349
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000350 // The RestoreOffset field is initially filled with a placeholder
351 // value that points to the offset of the previous RestoreOffset
352 // in the current stack level, thus forming a linked list so that
353 // the restore offsets can be filled in when the corresponding
354 // restore command is recorded.
355 int32_t prevOffset = fRestoreOffsetStack.top();
356
reed@google.com45482d12011-08-29 19:02:39 +0000357 if (regionOpExpands(op)) {
358 // Run back through any previous clip ops, and mark their offset to
359 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
360 // they could hide this clips ability to expand the clip (i.e. go from
361 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000362 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000363
364 // Reset the pointer back to the previous clip so that subsequent
365 // restores don't overwrite the offsets we just cleared.
366 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000367 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000368
reed@google.com44699382013-10-31 17:28:30 +0000369 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000370 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000371 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000372 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000373}
374
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000375void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000376 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000377 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000378}
379
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000380size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000381 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000382 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000383 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000384 if (!fRestoreOffsetStack.isEmpty()) {
385 // + restore offset
386 size += kUInt32Size;
387 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000388 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000389 this->addRect(rect);
390 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000391 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000392
robertphillips@google.com8b169312013-10-15 17:47:36 +0000393 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000394 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000395}
396
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000397void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000398 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700399 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000400}
401
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000402size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000403 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000404 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000405 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000406 if (!fRestoreOffsetStack.isEmpty()) {
407 // + restore offset
408 size += kUInt32Size;
409 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000410 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000411 this->addRRect(rrect);
412 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000413 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000414 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000415 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000416}
417
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000418void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000419 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000420 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700421 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000422}
423
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000424size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000425 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000426 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000427 // recordRestoreOffsetPlaceholder doesn't always write an offset
428 if (!fRestoreOffsetStack.isEmpty()) {
429 // + restore offset
430 size += kUInt32Size;
431 }
432 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000433 this->addInt(pathID);
434 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000435 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000436 this->validate(initialOffset, size);
437 return offset;
438}
439
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000440void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000441 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000442 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000443}
444
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000445size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000446 // op + clip params + region
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000447 size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000448 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000449 if (!fRestoreOffsetStack.isEmpty()) {
450 // + restore offset
451 size += kUInt32Size;
452 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000453 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000454 this->addRegion(region);
455 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000456 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000457
robertphillips@google.com8b169312013-10-15 17:47:36 +0000458 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000459 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000460}
461
reed41af9662015-01-05 07:49:08 -0800462void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000463 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000464 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000465 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700466 SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000467 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000468 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000469}
470
reed41af9662015-01-05 07:49:08 -0800471void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
472 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700473 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000474
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000475 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000476 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000477 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
mtklein8e126562014-10-01 09:29:35 -0700478 SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000479 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700480
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000481 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000482 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000483 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000484 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000485}
486
reed41af9662015-01-05 07:49:08 -0800487void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000488 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000489 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000490 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
mtklein8e126562014-10-01 09:29:35 -0700491 SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000492 this->addPaint(paint);
493 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000494 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000495}
496
reed41af9662015-01-05 07:49:08 -0800497void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000498 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000499 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000500 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700501 SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000502 this->addPaint(paint);
503 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000504 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000505}
506
reed41af9662015-01-05 07:49:08 -0800507void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700508 // op + paint index + rrect
509 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
510 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700511 SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700512 this->addPaint(paint);
513 this->addRRect(rrect);
514 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000515}
516
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000517void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
518 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000519 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000520 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
521 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700522 SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000523 this->addPaint(paint);
524 this->addRRect(outer);
525 this->addRRect(inner);
526 this->validate(initialOffset, size);
527}
528
reed41af9662015-01-05 07:49:08 -0800529void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700530 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000531
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000532 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000533 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000534 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700535 SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000536 this->addPaint(paint);
537 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000538 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000539}
540
reed41af9662015-01-05 07:49:08 -0800541void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
542 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000543 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000544 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000545 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
mtklein8e126562014-10-01 09:29:35 -0700546 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000547 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000548 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000549 this->addScalar(left);
550 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000551 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000552}
553
reed41af9662015-01-05 07:49:08 -0800554void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700555 const SkPaint* paint, SrcRectConstraint constraint) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000556 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000557 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700558 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000559 size += sizeof(*src); // + rect
560 }
561 size += sizeof(dst); // + rect
562
reeda5517e22015-07-14 10:54:12 -0700563 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT, &size);
564 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000565 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000566 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000567 this->addRectPtr(src); // may be null
568 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700569 this->addInt(constraint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000570 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000571}
572
reeda85d4d02015-05-06 12:56:48 -0700573void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
574 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700575 // op + paint_index + image_index + x + y
576 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
577 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
578 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE, size) == fWriter.bytesWritten());
579 this->addPaintPtr(paint);
580 this->addImage(image);
581 this->addScalar(x);
582 this->addScalar(y);
583 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700584}
585
586void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700587 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700588 // id + paint_index + image_index + bool_for_src + constraint
589 size_t size = 5 * kUInt32Size;
reed871872f2015-06-22 12:48:26 -0700590 if (src) {
591 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700592 }
reed871872f2015-06-22 12:48:26 -0700593 size += sizeof(dst); // + rect
594
595 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
596 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE_RECT, size)
597 == fWriter.bytesWritten());
598 this->addPaintPtr(paint);
599 this->addImage(image);
600 this->addRectPtr(src); // may be null
601 this->addRect(dst);
reeda5517e22015-07-14 10:54:12 -0700602 this->addInt(constraint);
reed871872f2015-06-22 12:48:26 -0700603 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700604}
605
reed4c21dc52015-06-25 12:32:03 -0700606void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
607 const SkPaint* paint) {
608 // id + paint_index + image_index + center + dst
609 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
610
611 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
612 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE_NINE, size) == fWriter.bytesWritten());
613 this->addPaintPtr(paint);
614 this->addImage(img);
615 this->addIRect(center);
616 this->addRect(dst);
617 this->validate(initialOffset, size);
618}
619
reed41af9662015-01-05 07:49:08 -0800620void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
621 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000622 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000623 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000624 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
mtklein8e126562014-10-01 09:29:35 -0700625 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000626 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000627 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000628 this->addIRect(center);
629 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000630 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000631}
632
reed41af9662015-01-05 07:49:08 -0800633void SkPictureRecord::onDrawSprite(const SkBitmap& bitmap, int left, int top,
634 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000635 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000636 size_t size = 5 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000637 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
mtklein8e126562014-10-01 09:29:35 -0700638 SkASSERT(initialOffset+get_paint_offset(DRAW_SPRITE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000639 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000640 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000641 this->addInt(left);
642 this->addInt(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000643 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000644}
645
reed@google.come0d9ce82014-04-23 04:00:17 +0000646void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
647 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000648 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000649 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000650
mtklein46616af2014-09-30 14:47:10 -0700651 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000652 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700653 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700654 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000655 this->addText(text, byteLength);
656 this->addScalar(x);
657 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000658 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000659}
660
reed@google.come0d9ce82014-04-23 04:00:17 +0000661void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
662 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000663 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000664
mtklein46616af2014-09-30 14:47:10 -0700665 // op + paint index + length + 'length' worth of data + num points + x&y point data
666 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000667
mtklein46616af2014-09-30 14:47:10 -0700668 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000669
robertphillips@google.com8b169312013-10-15 17:47:36 +0000670 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700671 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700672 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000673 this->addText(text, byteLength);
674 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700675 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000676 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000677}
678
reed@google.come0d9ce82014-04-23 04:00:17 +0000679void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
680 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000681 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000682
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000683 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000684 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000685 // + y + the actual points
686 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000687
mtklein46616af2014-09-30 14:47:10 -0700688 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
689 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000690 this->addText(text, byteLength);
691 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000692 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000693 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000694 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000695}
696
reed@google.come0d9ce82014-04-23 04:00:17 +0000697void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
698 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000699 // op + paint index + length + 'length' worth of data + path index + matrix
700 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000701 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000702 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700703 SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000704 this->addPaint(paint);
705 this->addText(text, byteLength);
706 this->addPath(path);
707 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000708 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000709}
710
fmalitab7425172014-08-26 07:56:44 -0700711void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
712 const SkPaint& paint) {
713
714 // op + paint index + blob index + x/y
715 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
716 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
mtklein8e126562014-10-01 09:29:35 -0700717 SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
fmalitab7425172014-08-26 07:56:44 -0700718
719 this->addPaint(paint);
720 this->addTextBlob(blob);
721 this->addScalar(x);
722 this->addScalar(y);
723
724 this->validate(initialOffset, size);
725}
726
reedd5fa1a42014-08-09 11:08:05 -0700727void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
728 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000729 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000730 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700731 size_t initialOffset;
732
733 if (NULL == matrix && NULL == paint) {
734 initialOffset = this->addDraw(DRAW_PICTURE, &size);
735 this->addPicture(picture);
736 } else {
737 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
738 size += m.writeToMemory(NULL) + kUInt32Size; // matrix + paint
739 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700740 SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
fmalita9f49cfd2014-08-12 12:24:17 -0700741 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700742 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700743 this->addMatrix(m);
744 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700745 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000746 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000747}
748
reed41af9662015-01-05 07:49:08 -0800749void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
750 const SkPoint vertices[], const SkPoint texs[],
751 const SkColor colors[], SkXfermode* xfer,
752 const uint16_t indices[], int indexCount,
753 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000754 uint32_t flags = 0;
755 if (texs) {
756 flags |= DRAW_VERTICES_HAS_TEXS;
757 }
758 if (colors) {
759 flags |= DRAW_VERTICES_HAS_COLORS;
760 }
761 if (indexCount > 0) {
762 flags |= DRAW_VERTICES_HAS_INDICES;
763 }
bsalomon49f085d2014-09-05 13:34:00 -0700764 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000765 SkXfermode::Mode mode;
766 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
767 flags |= DRAW_VERTICES_HAS_XFER;
768 }
769 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000770
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000771 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000772 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000773 if (flags & DRAW_VERTICES_HAS_TEXS) {
774 size += vertexCount * sizeof(SkPoint); // + uvs
775 }
776 if (flags & DRAW_VERTICES_HAS_COLORS) {
777 size += vertexCount * sizeof(SkColor); // + vert colors
778 }
779 if (flags & DRAW_VERTICES_HAS_INDICES) {
780 // + num indices + indices
781 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
782 }
reed@google.com85e143c2013-12-30 15:51:25 +0000783 if (flags & DRAW_VERTICES_HAS_XFER) {
784 size += kUInt32Size; // mode enum
785 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000786
robertphillips@google.com8b169312013-10-15 17:47:36 +0000787 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
mtklein8e126562014-10-01 09:29:35 -0700788 SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000789 this->addPaint(paint);
790 this->addInt(flags);
791 this->addInt(vmode);
792 this->addInt(vertexCount);
793 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000794 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000795 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000796 }
797 if (flags & DRAW_VERTICES_HAS_COLORS) {
798 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
799 }
800 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000801 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000802 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
803 }
reed@google.com85e143c2013-12-30 15:51:25 +0000804 if (flags & DRAW_VERTICES_HAS_XFER) {
805 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
806 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000807 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000808 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000809 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000810}
811
dandovb3c9d1c2014-08-12 08:34:29 -0700812void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
813 const SkPoint texCoords[4], SkXfermode* xmode,
814 const SkPaint& paint) {
815 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
816 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
817 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700818 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700819 flag |= DRAW_VERTICES_HAS_COLORS;
820 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
821 }
bsalomon49f085d2014-09-05 13:34:00 -0700822 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700823 flag |= DRAW_VERTICES_HAS_TEXS;
824 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
825 }
bsalomon49f085d2014-09-05 13:34:00 -0700826 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700827 SkXfermode::Mode mode;
828 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
829 flag |= DRAW_VERTICES_HAS_XFER;
830 size += kUInt32Size;
831 }
832 }
mtklein46616af2014-09-30 14:47:10 -0700833
dandov963137b2014-08-07 07:49:53 -0700834 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
mtklein8e126562014-10-01 09:29:35 -0700835 SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
dandov963137b2014-08-07 07:49:53 -0700836 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700837 this->addPatch(cubics);
838 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700839
dandovb3c9d1c2014-08-12 08:34:29 -0700840 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700841 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700842 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
843 }
bsalomon49f085d2014-09-05 13:34:00 -0700844 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700845 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
846 }
847 if (flag & DRAW_VERTICES_HAS_XFER) {
848 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
849 xmode->asMode(&mode);
850 this->addInt(mode);
851 }
dandov963137b2014-08-07 07:49:53 -0700852 this->validate(initialOffset, size);
853}
854
reed71c3c762015-06-24 10:29:17 -0700855void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
856 const SkColor colors[], int count, SkXfermode::Mode mode,
857 const SkRect* cull, const SkPaint* paint) {
858 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
859 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
860 uint32_t flags = 0;
861 if (colors) {
862 flags |= DRAW_ATLAS_HAS_COLORS;
863 size += count * sizeof(SkColor);
864 size += sizeof(uint32_t); // xfermode::mode
865 }
866 if (cull) {
867 flags |= DRAW_ATLAS_HAS_CULL;
868 size += sizeof(SkRect);
869 }
870
871 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
872 SkASSERT(initialOffset+get_paint_offset(DRAW_ATLAS, size) == fWriter.bytesWritten());
873 this->addPaintPtr(paint);
874 this->addImage(atlas);
875 this->addInt(flags);
876 this->addInt(count);
877 fWriter.write(xform, count * sizeof(SkRSXform));
878 fWriter.write(tex, count * sizeof(SkRect));
879
880 // write optional parameters
881 if (colors) {
882 fWriter.write(colors, count * sizeof(SkColor));
883 this->addInt(mode);
884 }
885 if (cull) {
886 fWriter.write(cull, sizeof(SkRect));
887 }
888 this->validate(initialOffset, size);
889}
890
reed@android.com8a1c16f2008-12-17 15:59:43 +0000891///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000892
reed4a8126e2014-09-22 07:29:03 -0700893SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000894 return NULL;
reed@google.com76f10a32014-02-05 15:32:21 +0000895}
896
mtkleine0694002014-11-12 12:49:47 -0800897// If we already have a stored, can we reuse it instead of also storing b?
898static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
899 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
900 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
901 // but it sure makes things easier to reason about below.
902 return false;
903 }
904 if (a.pixelRef() == b.pixelRef()) {
905 return true; // Same shape and same pixels -> same bitmap.
906 }
907
908 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
909 if (!a.pixelRef() || !b.pixelRef()) {
910 return false;
911 }
912
913 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
914 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
915 encB(b.pixelRef()->refEncodedData());
916 if (encA && encB) {
917 return encA->equals(encB);
918 } else if (encA || encB) {
919 return false; // One has encoded data but the other does not.
920 }
921
922 // As a last resort, we have to look at the pixels. This will read back textures.
923 SkAutoLockPixels al(a), bl(b);
924 const char* ap = (const char*)a.getPixels();
925 const char* bp = (const char*)b.getPixels();
926 if (ap && bp) {
927 // We check row by row; row bytes might differ.
928 SkASSERT(a.info() == b.info()); // We checked this above.
929 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
930 const SkImageInfo info = a.info();
931 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
932 for (int row = 0; row < info.height(); row++) {
933 if (0 != memcmp(ap, bp, bytesToCompare)) {
934 return false;
935 }
936 ap += a.rowBytes();
937 bp += b.rowBytes();
938 }
939 return true;
940 }
941 return false; // Couldn't get pixels for both bitmaps.
942}
943
944void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
945 // First see if we already have this bitmap. This deduplication should really
946 // only be important for our tests, where bitmaps tend not to be tagged immutable.
947 // In Chrome (and hopefully Android?) they're typically immutable.
948 for (int i = 0; i < fBitmaps.count(); i++) {
949 if (equivalent(fBitmaps[i], bitmap)) {
950 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
951 return;
952 }
953 }
954 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800955 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800956 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800957 fBitmaps.push_back(bitmap);
958 } else {
mtkleine0694002014-11-12 12:49:47 -0800959 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800960 SkBitmap copy;
961 bitmap.copyTo(&copy);
962 copy.setImmutable();
963 fBitmaps.push_back(copy);
964 }
mtkleine0694002014-11-12 12:49:47 -0800965 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000966}
967
reed871872f2015-06-22 12:48:26 -0700968void SkPictureRecord::addImage(const SkImage* image) {
969 int index = fImageRefs.find(image);
970 if (index >= 0) {
971 this->addInt(index);
972 } else {
973 *fImageRefs.append() = SkRef(image);
974 this->addInt(fImageRefs.count()-1);
975 }
976}
977
reed@android.com8a1c16f2008-12-17 15:59:43 +0000978void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000979 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000980}
981
mtklein46616af2014-09-30 14:47:10 -0700982void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700983 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000984
mtklein46616af2014-09-30 14:47:10 -0700985 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800986 fPaints.push_back(*paint);
987 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700988 } else {
989 this->addInt(0);
990 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000991}
992
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000993int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtklein71a23632014-11-12 10:24:55 -0800994 fPaths.push_back(path);
995 return fPaths.count();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000996}
997
998void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000999 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001000}
1001
dandovb3c9d1c2014-08-12 08:34:29 -07001002void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
1003 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -07001004}
1005
robertphillips9b14f262014-06-04 05:40:44 -07001006void SkPictureRecord::addPicture(const SkPicture* picture) {
1007 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001008 if (index < 0) { // not found
1009 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -07001010 *fPictureRefs.append() = picture;
1011 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001012 }
1013 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +00001014 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001015}
1016
1017void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001018 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001019}
reed@google.com82065d62011-02-07 15:30:46 +00001020
reed@android.com8a1c16f2008-12-17 15:59:43 +00001021void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
1022 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001023}
1024
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001025void SkPictureRecord::addNoOp() {
1026 size_t size = kUInt32Size; // op
1027 this->addDraw(NOOP, &size);
1028}
1029
reed@android.com8a1c16f2008-12-17 15:59:43 +00001030void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001031 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001032}
1033
1034void SkPictureRecord::addRectPtr(const SkRect* rect) {
1035 if (fWriter.writeBool(rect != NULL)) {
1036 fWriter.writeRect(*rect);
1037 }
1038}
1039
reed@google.comf0b5e112011-09-07 11:57:34 +00001040void SkPictureRecord::addIRect(const SkIRect& rect) {
1041 fWriter.write(&rect, sizeof(rect));
1042}
1043
reed@android.com8a1c16f2008-12-17 15:59:43 +00001044void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
1045 if (fWriter.writeBool(rect != NULL)) {
1046 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
1047 }
1048}
1049
reed@google.com4ed0fb72012-12-12 20:48:18 +00001050void SkPictureRecord::addRRect(const SkRRect& rrect) {
1051 fWriter.writeRRect(rrect);
1052}
1053
reed@android.com8a1c16f2008-12-17 15:59:43 +00001054void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001055 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001056}
1057
1058void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001059 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001060 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001061 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001062}
1063
fmalitab7425172014-08-26 07:56:44 -07001064void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001065 int index = fTextBlobRefs.count();
1066 *fTextBlobRefs.append() = blob;
1067 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001068 // follow the convention of recording a 1-based index
1069 this->addInt(index + 1);
1070}
1071
reed@android.com8a1c16f2008-12-17 15:59:43 +00001072///////////////////////////////////////////////////////////////////////////////
1073