blob: 5f85b47aac27cb6558506c75e3893d8809f50cb0 [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
64 1, // DRAW_BITMAP_RECT_TO_RECT - right after op code
65 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
102 1, // DRAW_IMAGE_RECT - 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
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000105 };
robertphillips@google.come37ad352013-03-01 19:44:30 +0000106
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000107 SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
108 need_to_be_in_sync);
robertphillips@google.come37ad352013-03-01 19:44:30 +0000109 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
110
111 int overflow = 0;
112 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
113 // This op's size overflows so an extra uint32_t will be written
114 // after the op code
115 overflow = sizeof(uint32_t);
116 }
117
118 if (SAVE_LAYER == op) {
119 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
120 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
121
122 if (kSaveLayerNoBoundsSize == opSize) {
123 return kSaveLayerNoBoundsPaintOffset + overflow;
124 } else {
125 SkASSERT(kSaveLayerWithBoundsSize == opSize);
126 return kSaveLayerWithBoundsPaintOffset + overflow;
127 }
128 }
129
130 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this method
131 return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
132}
mtklein8e126562014-10-01 09:29:35 -0700133#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +0000134
Florin Malita5f6102d2014-06-30 10:13:28 -0400135void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +0000136 // record the offset to us, making it non-positive to distinguish a save
137 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000138 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -0400139 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000140
Florin Malita5f6102d2014-06-30 10:13:28 -0400141 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000142}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000143
Florin Malita5f6102d2014-06-30 10:13:28 -0400144void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -0700145 fContentInfo.onSave();
146
Florin Malita5f6102d2014-06-30 10:13:28 -0400147 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000148 size_t size = kSaveSize;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000149 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +0000150
robertphillips@google.com8b169312013-10-15 17:47:36 +0000151 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152}
153
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000154SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
155 const SkPaint* paint, SaveFlags flags) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000156 // record the offset to us, making it non-positive to distinguish a save
157 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000158 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000159 this->recordSaveLayer(bounds, paint, flags);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000160
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000161 this->INHERITED::willSaveLayer(bounds, paint, flags);
162 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000163 at this time (and may not be able to afford since during record our
164 clip starts out the size of the picture, which is often much larger
165 than the size of the actual device we'll use during playback).
166 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000167 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000168}
169
170void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000171 SaveFlags flags) {
robertphillipsc019ec42014-08-12 05:35:58 -0700172 fContentInfo.onSaveLayer();
173
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000174 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000175 size_t size = 2 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700176 if (bounds) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000177 size += sizeof(*bounds); // + rect
178 }
179 // + paint index + flags
180 size += 2 * kUInt32Size;
181
robertphillips@google.come37ad352013-03-01 19:44:30 +0000182 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
183
robertphillips@google.com8b169312013-10-15 17:47:36 +0000184 size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000185 this->addRectPtr(bounds);
mtklein8e126562014-10-01 09:29:35 -0700186 SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000187 this->addPaintPtr(paint);
188 this->addInt(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189
robertphillips@google.com8b169312013-10-15 17:47:36 +0000190 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000191}
192
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000193#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000194/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000195 * Read the op code from 'offset' in 'writer' and extract the size too.
196 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000197static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000198 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000199
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000200 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000201 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000202 if (MASK_24 == *size) {
203 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000204 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000205 }
206 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000207}
mtklein46616af2014-09-30 14:47:10 -0700208#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000209
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000210void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000211 // FIXME: SkDeferredCanvas needs to be refactored to respect
212 // save/restore balancing so that the following test can be
213 // turned on permanently.
214#if 0
215 SkASSERT(fRestoreOffsetStack.count() > 1);
216#endif
217
reed@android.comb4e22d62009-07-09 15:20:25 +0000218 // check for underflow
219 if (fRestoreOffsetStack.count() == 0) {
220 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000221 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000222
mtklein46616af2014-09-30 14:47:10 -0700223 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000224
reed@android.comb4e22d62009-07-09 15:20:25 +0000225 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000226
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000227 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000228}
229
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000230void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700231 fContentInfo.onRestore();
232
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000233 if (fillInSkips) {
234 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
235 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000236 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
237 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000238 this->validate(initialOffset, size);
239}
240
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000241void SkPictureRecord::recordTranslate(const SkMatrix& m) {
242 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
243
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000244 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000245 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000246 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000247 this->addScalar(m.getTranslateX());
248 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000249 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000250}
251
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000252void SkPictureRecord::recordScale(const SkMatrix& m) {
253 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000254
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000255 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000256 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000257 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000258 this->addScalar(m.getScaleX());
259 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000260 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000261}
262
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000263void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000264 switch (matrix.getType()) {
265 case SkMatrix::kTranslate_Mask:
266 this->recordTranslate(matrix);
267 break;
268 case SkMatrix::kScale_Mask:
269 this->recordScale(matrix);
270 break;
271 default:
272 this->recordConcat(matrix);
273 break;
274 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000275 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000276}
277
278void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000279 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000280 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000281 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000282 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000283 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000284 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285}
286
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000287void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000288 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000289 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000290 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000291 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000292 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000293 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000294 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000295}
296
reed@google.com45482d12011-08-29 19:02:39 +0000297static bool regionOpExpands(SkRegion::Op op) {
298 switch (op) {
299 case SkRegion::kUnion_Op:
300 case SkRegion::kXOR_Op:
301 case SkRegion::kReverseDifference_Op:
302 case SkRegion::kReplace_Op:
303 return true;
304 case SkRegion::kIntersect_Op:
305 case SkRegion::kDifference_Op:
306 return false;
307 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000308 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000309 return false;
310 }
311}
312
robertphillips@google.come37ad352013-03-01 19:44:30 +0000313void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000314 int32_t offset = fRestoreOffsetStack.top();
315 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000316 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
317 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000318 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000319 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000320
reed@google.comffacd3c2012-08-30 15:31:23 +0000321#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800322 // offset of 0 has been disabled, so we skip it
323 if (offset > 0) {
324 // assert that the final offset value points to a save verb
325 uint32_t opSize;
326 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
327 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
328 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000329#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000330}
331
reed@google.comd86e7ab2012-09-27 20:31:31 +0000332void SkPictureRecord::beginRecording() {
333 // we have to call this *after* our constructor, to ensure that it gets
334 // recorded. This is balanced by restoreToCount() call from endRecording,
335 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000336 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000337}
338
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000339void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000340 SkASSERT(kNoInitialSave != fInitialSaveCount);
341 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000342}
343
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000344size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000345 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000346 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000347 }
348
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000349 // The RestoreOffset field is initially filled with a placeholder
350 // value that points to the offset of the previous RestoreOffset
351 // in the current stack level, thus forming a linked list so that
352 // the restore offsets can be filled in when the corresponding
353 // restore command is recorded.
354 int32_t prevOffset = fRestoreOffsetStack.top();
355
reed@google.com45482d12011-08-29 19:02:39 +0000356 if (regionOpExpands(op)) {
357 // Run back through any previous clip ops, and mark their offset to
358 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
359 // they could hide this clips ability to expand the clip (i.e. go from
360 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000361 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000362
363 // Reset the pointer back to the previous clip so that subsequent
364 // restores don't overwrite the offsets we just cleared.
365 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000366 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000367
reed@google.com44699382013-10-31 17:28:30 +0000368 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000369 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000370 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000371 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000372}
373
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000374void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000375 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000376 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000377}
378
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000379size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000380 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000381 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000382 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000383 if (!fRestoreOffsetStack.isEmpty()) {
384 // + restore offset
385 size += kUInt32Size;
386 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000387 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000388 this->addRect(rect);
389 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000390 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000391
robertphillips@google.com8b169312013-10-15 17:47:36 +0000392 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000393 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000394}
395
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000396void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000397 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700398 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000399}
400
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000401size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000402 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000403 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000404 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000405 if (!fRestoreOffsetStack.isEmpty()) {
406 // + restore offset
407 size += kUInt32Size;
408 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000409 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000410 this->addRRect(rrect);
411 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000412 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000413 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000414 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000415}
416
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000417void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000418 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000419 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700420 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000421}
422
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000423size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000424 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000425 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000426 // recordRestoreOffsetPlaceholder doesn't always write an offset
427 if (!fRestoreOffsetStack.isEmpty()) {
428 // + restore offset
429 size += kUInt32Size;
430 }
431 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000432 this->addInt(pathID);
433 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000434 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000435 this->validate(initialOffset, size);
436 return offset;
437}
438
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000439void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000440 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000441 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000442}
443
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000444size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000445 // op + clip params + region
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000446 size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000447 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000448 if (!fRestoreOffsetStack.isEmpty()) {
449 // + restore offset
450 size += kUInt32Size;
451 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000452 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000453 this->addRegion(region);
454 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000455 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000456
robertphillips@google.com8b169312013-10-15 17:47:36 +0000457 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000458 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000459}
460
reed41af9662015-01-05 07:49:08 -0800461void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000462 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000463 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000464 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700465 SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000466 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000467 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000468}
469
reed41af9662015-01-05 07:49:08 -0800470void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
471 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700472 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000473
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000474 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000475 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000476 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
mtklein8e126562014-10-01 09:29:35 -0700477 SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000478 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700479
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000480 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000481 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000482 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000483 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000484}
485
reed41af9662015-01-05 07:49:08 -0800486void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000487 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000488 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000489 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
mtklein8e126562014-10-01 09:29:35 -0700490 SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000491 this->addPaint(paint);
492 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000493 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000494}
495
reed41af9662015-01-05 07:49:08 -0800496void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000497 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000498 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000499 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700500 SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000501 this->addPaint(paint);
502 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000503 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000504}
505
reed41af9662015-01-05 07:49:08 -0800506void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700507 // op + paint index + rrect
508 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
509 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700510 SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700511 this->addPaint(paint);
512 this->addRRect(rrect);
513 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000514}
515
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000516void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
517 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000518 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000519 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
520 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700521 SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000522 this->addPaint(paint);
523 this->addRRect(outer);
524 this->addRRect(inner);
525 this->validate(initialOffset, size);
526}
527
reed41af9662015-01-05 07:49:08 -0800528void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700529 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000530
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000531 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000532 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000533 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700534 SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000535 this->addPaint(paint);
536 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000537 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000538}
539
reed41af9662015-01-05 07:49:08 -0800540void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
541 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000542 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000543 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000544 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
mtklein8e126562014-10-01 09:29:35 -0700545 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000546 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000547 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000548 this->addScalar(left);
549 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000550 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000551}
552
reed41af9662015-01-05 07:49:08 -0800553void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
554 const SkPaint* paint, DrawBitmapRectFlags flags) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000555 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000556 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700557 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000558 size += sizeof(*src); // + rect
559 }
560 size += sizeof(dst); // + rect
561
robertphillips@google.com8b169312013-10-15 17:47:36 +0000562 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700563 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT_TO_RECT, size)
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000564 == 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);
569 this->addInt(flags);
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,
587 const SkPaint* paint) {
reed4c21dc52015-06-25 12:32:03 -0700588 // id + paint_index + image_index + bool_for_src
reed871872f2015-06-22 12:48:26 -0700589 size_t size = 4 * kUInt32Size;
590 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);
602 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700603}
604
reed4c21dc52015-06-25 12:32:03 -0700605void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
606 const SkPaint* paint) {
607 // id + paint_index + image_index + center + dst
608 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
609
610 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
611 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE_NINE, size) == fWriter.bytesWritten());
612 this->addPaintPtr(paint);
613 this->addImage(img);
614 this->addIRect(center);
615 this->addRect(dst);
616 this->validate(initialOffset, size);
617}
618
reed41af9662015-01-05 07:49:08 -0800619void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
620 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000621 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000622 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000623 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
mtklein8e126562014-10-01 09:29:35 -0700624 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000625 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000626 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000627 this->addIRect(center);
628 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000629 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000630}
631
reed41af9662015-01-05 07:49:08 -0800632void SkPictureRecord::onDrawSprite(const SkBitmap& bitmap, int left, int top,
633 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000634 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000635 size_t size = 5 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000636 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
mtklein8e126562014-10-01 09:29:35 -0700637 SkASSERT(initialOffset+get_paint_offset(DRAW_SPRITE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000638 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000639 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000640 this->addInt(left);
641 this->addInt(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000642 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000643}
644
reed@google.come0d9ce82014-04-23 04:00:17 +0000645void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
646 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000647 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000648 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000649
mtklein46616af2014-09-30 14:47:10 -0700650 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000651 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700652 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700653 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000654 this->addText(text, byteLength);
655 this->addScalar(x);
656 this->addScalar(y);
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::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
661 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000662 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000663
mtklein46616af2014-09-30 14:47:10 -0700664 // op + paint index + length + 'length' worth of data + num points + x&y point data
665 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000666
mtklein46616af2014-09-30 14:47:10 -0700667 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000668
robertphillips@google.com8b169312013-10-15 17:47:36 +0000669 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700670 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700671 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000672 this->addText(text, byteLength);
673 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700674 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000675 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000676}
677
reed@google.come0d9ce82014-04-23 04:00:17 +0000678void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
679 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000680 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000681
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000682 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000683 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000684 // + y + the actual points
685 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000686
mtklein46616af2014-09-30 14:47:10 -0700687 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
688 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000689 this->addText(text, byteLength);
690 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000691 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000692 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000693 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000694}
695
reed@google.come0d9ce82014-04-23 04:00:17 +0000696void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
697 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000698 // op + paint index + length + 'length' worth of data + path index + matrix
699 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000700 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000701 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700702 SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000703 this->addPaint(paint);
704 this->addText(text, byteLength);
705 this->addPath(path);
706 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000707 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000708}
709
fmalitab7425172014-08-26 07:56:44 -0700710void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
711 const SkPaint& paint) {
712
713 // op + paint index + blob index + x/y
714 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
715 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
mtklein8e126562014-10-01 09:29:35 -0700716 SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
fmalitab7425172014-08-26 07:56:44 -0700717
718 this->addPaint(paint);
719 this->addTextBlob(blob);
720 this->addScalar(x);
721 this->addScalar(y);
722
723 this->validate(initialOffset, size);
724}
725
reedd5fa1a42014-08-09 11:08:05 -0700726void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
727 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000728 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000729 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700730 size_t initialOffset;
731
732 if (NULL == matrix && NULL == paint) {
733 initialOffset = this->addDraw(DRAW_PICTURE, &size);
734 this->addPicture(picture);
735 } else {
736 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
737 size += m.writeToMemory(NULL) + kUInt32Size; // matrix + paint
738 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700739 SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
fmalita9f49cfd2014-08-12 12:24:17 -0700740 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700741 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700742 this->addMatrix(m);
743 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700744 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000745 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000746}
747
reed41af9662015-01-05 07:49:08 -0800748void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
749 const SkPoint vertices[], const SkPoint texs[],
750 const SkColor colors[], SkXfermode* xfer,
751 const uint16_t indices[], int indexCount,
752 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000753 uint32_t flags = 0;
754 if (texs) {
755 flags |= DRAW_VERTICES_HAS_TEXS;
756 }
757 if (colors) {
758 flags |= DRAW_VERTICES_HAS_COLORS;
759 }
760 if (indexCount > 0) {
761 flags |= DRAW_VERTICES_HAS_INDICES;
762 }
bsalomon49f085d2014-09-05 13:34:00 -0700763 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000764 SkXfermode::Mode mode;
765 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
766 flags |= DRAW_VERTICES_HAS_XFER;
767 }
768 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000769
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000770 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000771 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000772 if (flags & DRAW_VERTICES_HAS_TEXS) {
773 size += vertexCount * sizeof(SkPoint); // + uvs
774 }
775 if (flags & DRAW_VERTICES_HAS_COLORS) {
776 size += vertexCount * sizeof(SkColor); // + vert colors
777 }
778 if (flags & DRAW_VERTICES_HAS_INDICES) {
779 // + num indices + indices
780 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
781 }
reed@google.com85e143c2013-12-30 15:51:25 +0000782 if (flags & DRAW_VERTICES_HAS_XFER) {
783 size += kUInt32Size; // mode enum
784 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000785
robertphillips@google.com8b169312013-10-15 17:47:36 +0000786 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
mtklein8e126562014-10-01 09:29:35 -0700787 SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000788 this->addPaint(paint);
789 this->addInt(flags);
790 this->addInt(vmode);
791 this->addInt(vertexCount);
792 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000793 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000794 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000795 }
796 if (flags & DRAW_VERTICES_HAS_COLORS) {
797 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
798 }
799 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000800 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000801 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
802 }
reed@google.com85e143c2013-12-30 15:51:25 +0000803 if (flags & DRAW_VERTICES_HAS_XFER) {
804 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
805 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000806 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000807 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000808 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000809}
810
dandovb3c9d1c2014-08-12 08:34:29 -0700811void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
812 const SkPoint texCoords[4], SkXfermode* xmode,
813 const SkPaint& paint) {
814 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
815 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
816 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700817 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700818 flag |= DRAW_VERTICES_HAS_COLORS;
819 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
820 }
bsalomon49f085d2014-09-05 13:34:00 -0700821 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700822 flag |= DRAW_VERTICES_HAS_TEXS;
823 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
824 }
bsalomon49f085d2014-09-05 13:34:00 -0700825 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700826 SkXfermode::Mode mode;
827 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
828 flag |= DRAW_VERTICES_HAS_XFER;
829 size += kUInt32Size;
830 }
831 }
mtklein46616af2014-09-30 14:47:10 -0700832
dandov963137b2014-08-07 07:49:53 -0700833 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
mtklein8e126562014-10-01 09:29:35 -0700834 SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
dandov963137b2014-08-07 07:49:53 -0700835 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700836 this->addPatch(cubics);
837 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700838
dandovb3c9d1c2014-08-12 08:34:29 -0700839 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700840 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700841 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
842 }
bsalomon49f085d2014-09-05 13:34:00 -0700843 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700844 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
845 }
846 if (flag & DRAW_VERTICES_HAS_XFER) {
847 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
848 xmode->asMode(&mode);
849 this->addInt(mode);
850 }
dandov963137b2014-08-07 07:49:53 -0700851 this->validate(initialOffset, size);
852}
853
reed71c3c762015-06-24 10:29:17 -0700854void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
855 const SkColor colors[], int count, SkXfermode::Mode mode,
856 const SkRect* cull, const SkPaint* paint) {
857 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
858 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
859 uint32_t flags = 0;
860 if (colors) {
861 flags |= DRAW_ATLAS_HAS_COLORS;
862 size += count * sizeof(SkColor);
863 size += sizeof(uint32_t); // xfermode::mode
864 }
865 if (cull) {
866 flags |= DRAW_ATLAS_HAS_CULL;
867 size += sizeof(SkRect);
868 }
869
870 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
871 SkASSERT(initialOffset+get_paint_offset(DRAW_ATLAS, size) == fWriter.bytesWritten());
872 this->addPaintPtr(paint);
873 this->addImage(atlas);
874 this->addInt(flags);
875 this->addInt(count);
876 fWriter.write(xform, count * sizeof(SkRSXform));
877 fWriter.write(tex, count * sizeof(SkRect));
878
879 // write optional parameters
880 if (colors) {
881 fWriter.write(colors, count * sizeof(SkColor));
882 this->addInt(mode);
883 }
884 if (cull) {
885 fWriter.write(cull, sizeof(SkRect));
886 }
887 this->validate(initialOffset, size);
888}
889
reed@android.com8a1c16f2008-12-17 15:59:43 +0000890///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000891
reed4a8126e2014-09-22 07:29:03 -0700892SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000893 return NULL;
reed@google.com76f10a32014-02-05 15:32:21 +0000894}
895
mtkleine0694002014-11-12 12:49:47 -0800896// If we already have a stored, can we reuse it instead of also storing b?
897static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
898 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
899 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
900 // but it sure makes things easier to reason about below.
901 return false;
902 }
903 if (a.pixelRef() == b.pixelRef()) {
904 return true; // Same shape and same pixels -> same bitmap.
905 }
906
907 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
908 if (!a.pixelRef() || !b.pixelRef()) {
909 return false;
910 }
911
912 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
913 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
914 encB(b.pixelRef()->refEncodedData());
915 if (encA && encB) {
916 return encA->equals(encB);
917 } else if (encA || encB) {
918 return false; // One has encoded data but the other does not.
919 }
920
921 // As a last resort, we have to look at the pixels. This will read back textures.
922 SkAutoLockPixels al(a), bl(b);
923 const char* ap = (const char*)a.getPixels();
924 const char* bp = (const char*)b.getPixels();
925 if (ap && bp) {
926 // We check row by row; row bytes might differ.
927 SkASSERT(a.info() == b.info()); // We checked this above.
928 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
929 const SkImageInfo info = a.info();
930 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
931 for (int row = 0; row < info.height(); row++) {
932 if (0 != memcmp(ap, bp, bytesToCompare)) {
933 return false;
934 }
935 ap += a.rowBytes();
936 bp += b.rowBytes();
937 }
938 return true;
939 }
940 return false; // Couldn't get pixels for both bitmaps.
941}
942
943void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
944 // First see if we already have this bitmap. This deduplication should really
945 // only be important for our tests, where bitmaps tend not to be tagged immutable.
946 // In Chrome (and hopefully Android?) they're typically immutable.
947 for (int i = 0; i < fBitmaps.count(); i++) {
948 if (equivalent(fBitmaps[i], bitmap)) {
949 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
950 return;
951 }
952 }
953 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800954 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800955 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800956 fBitmaps.push_back(bitmap);
957 } else {
mtkleine0694002014-11-12 12:49:47 -0800958 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800959 SkBitmap copy;
960 bitmap.copyTo(&copy);
961 copy.setImmutable();
962 fBitmaps.push_back(copy);
963 }
mtkleine0694002014-11-12 12:49:47 -0800964 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000965}
966
reed871872f2015-06-22 12:48:26 -0700967void SkPictureRecord::addImage(const SkImage* image) {
968 int index = fImageRefs.find(image);
969 if (index >= 0) {
970 this->addInt(index);
971 } else {
972 *fImageRefs.append() = SkRef(image);
973 this->addInt(fImageRefs.count()-1);
974 }
975}
976
reed@android.com8a1c16f2008-12-17 15:59:43 +0000977void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000978 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000979}
980
mtklein46616af2014-09-30 14:47:10 -0700981void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700982 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000983
mtklein46616af2014-09-30 14:47:10 -0700984 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800985 fPaints.push_back(*paint);
986 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700987 } else {
988 this->addInt(0);
989 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000990}
991
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000992int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtklein71a23632014-11-12 10:24:55 -0800993 fPaths.push_back(path);
994 return fPaths.count();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000995}
996
997void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000998 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000999}
1000
dandovb3c9d1c2014-08-12 08:34:29 -07001001void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
1002 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -07001003}
1004
robertphillips9b14f262014-06-04 05:40:44 -07001005void SkPictureRecord::addPicture(const SkPicture* picture) {
1006 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001007 if (index < 0) { // not found
1008 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -07001009 *fPictureRefs.append() = picture;
1010 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001011 }
1012 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +00001013 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001014}
1015
1016void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001017 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001018}
reed@google.com82065d62011-02-07 15:30:46 +00001019
reed@android.com8a1c16f2008-12-17 15:59:43 +00001020void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
1021 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001022}
1023
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001024void SkPictureRecord::addNoOp() {
1025 size_t size = kUInt32Size; // op
1026 this->addDraw(NOOP, &size);
1027}
1028
reed@android.com8a1c16f2008-12-17 15:59:43 +00001029void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001030 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001031}
1032
1033void SkPictureRecord::addRectPtr(const SkRect* rect) {
1034 if (fWriter.writeBool(rect != NULL)) {
1035 fWriter.writeRect(*rect);
1036 }
1037}
1038
reed@google.comf0b5e112011-09-07 11:57:34 +00001039void SkPictureRecord::addIRect(const SkIRect& rect) {
1040 fWriter.write(&rect, sizeof(rect));
1041}
1042
reed@android.com8a1c16f2008-12-17 15:59:43 +00001043void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
1044 if (fWriter.writeBool(rect != NULL)) {
1045 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
1046 }
1047}
1048
reed@google.com4ed0fb72012-12-12 20:48:18 +00001049void SkPictureRecord::addRRect(const SkRRect& rrect) {
1050 fWriter.writeRRect(rrect);
1051}
1052
reed@android.com8a1c16f2008-12-17 15:59:43 +00001053void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001054 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001055}
1056
1057void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001058 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001059 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001060 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001061}
1062
fmalitab7425172014-08-26 07:56:44 -07001063void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001064 int index = fTextBlobRefs.count();
1065 *fTextBlobRefs.append() = blob;
1066 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001067 // follow the convention of recording a 1-based index
1068 this->addInt(index + 1);
1069}
1070
reed@android.com8a1c16f2008-12-17 15:59:43 +00001071///////////////////////////////////////////////////////////////////////////////
1072