blob: 0fbf98089adec1556d36911dcdfd3bf2fab4497b [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
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000104 };
robertphillips@google.come37ad352013-03-01 19:44:30 +0000105
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000106 SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
107 need_to_be_in_sync);
robertphillips@google.come37ad352013-03-01 19:44:30 +0000108 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
109
110 int overflow = 0;
111 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
112 // This op's size overflows so an extra uint32_t will be written
113 // after the op code
114 overflow = sizeof(uint32_t);
115 }
116
117 if (SAVE_LAYER == op) {
118 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
119 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
120
121 if (kSaveLayerNoBoundsSize == opSize) {
122 return kSaveLayerNoBoundsPaintOffset + overflow;
123 } else {
124 SkASSERT(kSaveLayerWithBoundsSize == opSize);
125 return kSaveLayerWithBoundsPaintOffset + overflow;
126 }
127 }
128
129 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this method
130 return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
131}
mtklein8e126562014-10-01 09:29:35 -0700132#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +0000133
Florin Malita5f6102d2014-06-30 10:13:28 -0400134void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +0000135 // record the offset to us, making it non-positive to distinguish a save
136 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000137 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -0400138 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000139
Florin Malita5f6102d2014-06-30 10:13:28 -0400140 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000141}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000142
Florin Malita5f6102d2014-06-30 10:13:28 -0400143void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -0700144 fContentInfo.onSave();
145
Florin Malita5f6102d2014-06-30 10:13:28 -0400146 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000147 size_t size = kSaveSize;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000148 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +0000149
robertphillips@google.com8b169312013-10-15 17:47:36 +0000150 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000151}
152
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000153SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
154 const SkPaint* paint, SaveFlags flags) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000155 // record the offset to us, making it non-positive to distinguish a save
156 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000157 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000158 this->recordSaveLayer(bounds, paint, flags);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000159
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000160 this->INHERITED::willSaveLayer(bounds, paint, flags);
161 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000162 at this time (and may not be able to afford since during record our
163 clip starts out the size of the picture, which is often much larger
164 than the size of the actual device we'll use during playback).
165 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000166 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000167}
168
169void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000170 SaveFlags flags) {
robertphillipsc019ec42014-08-12 05:35:58 -0700171 fContentInfo.onSaveLayer();
172
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000173 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000174 size_t size = 2 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700175 if (bounds) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000176 size += sizeof(*bounds); // + rect
177 }
178 // + paint index + flags
179 size += 2 * kUInt32Size;
180
robertphillips@google.come37ad352013-03-01 19:44:30 +0000181 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
182
robertphillips@google.com8b169312013-10-15 17:47:36 +0000183 size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000184 this->addRectPtr(bounds);
mtklein8e126562014-10-01 09:29:35 -0700185 SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000186 this->addPaintPtr(paint);
187 this->addInt(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188
robertphillips@google.com8b169312013-10-15 17:47:36 +0000189 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000190}
191
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000192#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000193/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000194 * Read the op code from 'offset' in 'writer' and extract the size too.
195 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000196static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000197 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000198
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000199 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000200 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000201 if (MASK_24 == *size) {
202 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000203 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000204 }
205 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000206}
mtklein46616af2014-09-30 14:47:10 -0700207#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000208
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000209void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000210 // FIXME: SkDeferredCanvas needs to be refactored to respect
211 // save/restore balancing so that the following test can be
212 // turned on permanently.
213#if 0
214 SkASSERT(fRestoreOffsetStack.count() > 1);
215#endif
216
reed@android.comb4e22d62009-07-09 15:20:25 +0000217 // check for underflow
218 if (fRestoreOffsetStack.count() == 0) {
219 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000221
mtklein46616af2014-09-30 14:47:10 -0700222 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000223
reed@android.comb4e22d62009-07-09 15:20:25 +0000224 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000225
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000226 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000227}
228
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000229void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700230 fContentInfo.onRestore();
231
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000232 if (fillInSkips) {
233 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
234 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000235 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
236 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000237 this->validate(initialOffset, size);
238}
239
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000240void SkPictureRecord::recordTranslate(const SkMatrix& m) {
241 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
242
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000243 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000244 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000245 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000246 this->addScalar(m.getTranslateX());
247 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000248 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000249}
250
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000251void SkPictureRecord::recordScale(const SkMatrix& m) {
252 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000253
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000254 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000255 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000256 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000257 this->addScalar(m.getScaleX());
258 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000259 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000260}
261
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000262void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000263 switch (matrix.getType()) {
264 case SkMatrix::kTranslate_Mask:
265 this->recordTranslate(matrix);
266 break;
267 case SkMatrix::kScale_Mask:
268 this->recordScale(matrix);
269 break;
270 default:
271 this->recordConcat(matrix);
272 break;
273 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000274 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000275}
276
277void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000278 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000279 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000280 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000281 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000282 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000283 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000284}
285
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000286void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000287 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000288 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000289 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000290 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000291 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000292 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000293 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000294}
295
reed@google.com45482d12011-08-29 19:02:39 +0000296static bool regionOpExpands(SkRegion::Op op) {
297 switch (op) {
298 case SkRegion::kUnion_Op:
299 case SkRegion::kXOR_Op:
300 case SkRegion::kReverseDifference_Op:
301 case SkRegion::kReplace_Op:
302 return true;
303 case SkRegion::kIntersect_Op:
304 case SkRegion::kDifference_Op:
305 return false;
306 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000307 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000308 return false;
309 }
310}
311
robertphillips@google.come37ad352013-03-01 19:44:30 +0000312void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000313 int32_t offset = fRestoreOffsetStack.top();
314 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000315 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
316 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000317 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000318 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000319
reed@google.comffacd3c2012-08-30 15:31:23 +0000320#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800321 // offset of 0 has been disabled, so we skip it
322 if (offset > 0) {
323 // assert that the final offset value points to a save verb
324 uint32_t opSize;
325 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
326 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
327 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000328#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000329}
330
reed@google.comd86e7ab2012-09-27 20:31:31 +0000331void SkPictureRecord::beginRecording() {
332 // we have to call this *after* our constructor, to ensure that it gets
333 // recorded. This is balanced by restoreToCount() call from endRecording,
334 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000335 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000336}
337
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000338void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000339 SkASSERT(kNoInitialSave != fInitialSaveCount);
340 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000341}
342
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000343size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000344 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000345 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000346 }
347
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000348 // The RestoreOffset field is initially filled with a placeholder
349 // value that points to the offset of the previous RestoreOffset
350 // in the current stack level, thus forming a linked list so that
351 // the restore offsets can be filled in when the corresponding
352 // restore command is recorded.
353 int32_t prevOffset = fRestoreOffsetStack.top();
354
reed@google.com45482d12011-08-29 19:02:39 +0000355 if (regionOpExpands(op)) {
356 // Run back through any previous clip ops, and mark their offset to
357 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
358 // they could hide this clips ability to expand the clip (i.e. go from
359 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000360 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000361
362 // Reset the pointer back to the previous clip so that subsequent
363 // restores don't overwrite the offsets we just cleared.
364 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000365 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000366
reed@google.com44699382013-10-31 17:28:30 +0000367 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000368 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000369 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000370 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000371}
372
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000373void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000374 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000375 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000376}
377
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000378size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000379 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000380 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000381 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000382 if (!fRestoreOffsetStack.isEmpty()) {
383 // + restore offset
384 size += kUInt32Size;
385 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000386 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000387 this->addRect(rect);
388 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000389 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000390
robertphillips@google.com8b169312013-10-15 17:47:36 +0000391 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000392 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000393}
394
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000395void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000396 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700397 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000398}
399
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000400size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000401 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000402 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000403 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000404 if (!fRestoreOffsetStack.isEmpty()) {
405 // + restore offset
406 size += kUInt32Size;
407 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000408 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000409 this->addRRect(rrect);
410 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000411 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000412 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000413 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000414}
415
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000416void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000417 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000418 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700419 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000420}
421
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000422size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000423 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000424 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000425 // recordRestoreOffsetPlaceholder doesn't always write an offset
426 if (!fRestoreOffsetStack.isEmpty()) {
427 // + restore offset
428 size += kUInt32Size;
429 }
430 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000431 this->addInt(pathID);
432 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000433 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000434 this->validate(initialOffset, size);
435 return offset;
436}
437
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000438void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000439 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000440 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000441}
442
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000443size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000444 // op + clip params + region
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000445 size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000446 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000447 if (!fRestoreOffsetStack.isEmpty()) {
448 // + restore offset
449 size += kUInt32Size;
450 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000451 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000452 this->addRegion(region);
453 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000454 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000455
robertphillips@google.com8b169312013-10-15 17:47:36 +0000456 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000457 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000458}
459
reed41af9662015-01-05 07:49:08 -0800460void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000461 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000462 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000463 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700464 SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000465 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000466 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000467}
468
reed41af9662015-01-05 07:49:08 -0800469void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
470 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700471 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000472
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000473 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000474 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000475 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
mtklein8e126562014-10-01 09:29:35 -0700476 SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000477 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700478
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000479 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000480 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000481 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000482 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000483}
484
reed41af9662015-01-05 07:49:08 -0800485void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000486 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000487 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000488 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
mtklein8e126562014-10-01 09:29:35 -0700489 SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000490 this->addPaint(paint);
491 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000492 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000493}
494
reed41af9662015-01-05 07:49:08 -0800495void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000496 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000497 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000498 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700499 SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000500 this->addPaint(paint);
501 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000502 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000503}
504
reed41af9662015-01-05 07:49:08 -0800505void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700506 // op + paint index + rrect
507 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
508 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700509 SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700510 this->addPaint(paint);
511 this->addRRect(rrect);
512 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000513}
514
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000515void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
516 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000517 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000518 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
519 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700520 SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000521 this->addPaint(paint);
522 this->addRRect(outer);
523 this->addRRect(inner);
524 this->validate(initialOffset, size);
525}
526
reed41af9662015-01-05 07:49:08 -0800527void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700528 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000529
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000530 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000531 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000532 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700533 SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000534 this->addPaint(paint);
535 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000536 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000537}
538
reed41af9662015-01-05 07:49:08 -0800539void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
540 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000541 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000542 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000543 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
mtklein8e126562014-10-01 09:29:35 -0700544 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000545 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000546 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000547 this->addScalar(left);
548 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000549 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000550}
551
reed41af9662015-01-05 07:49:08 -0800552void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
553 const SkPaint* paint, DrawBitmapRectFlags flags) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000554 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000555 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700556 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000557 size += sizeof(*src); // + rect
558 }
559 size += sizeof(dst); // + rect
560
robertphillips@google.com8b169312013-10-15 17:47:36 +0000561 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700562 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT_TO_RECT, size)
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000563 == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000564 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000565 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000566 this->addRectPtr(src); // may be null
567 this->addRect(dst);
568 this->addInt(flags);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000569 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000570}
571
reeda85d4d02015-05-06 12:56:48 -0700572void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
573 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700574 // op + paint_index + image_index + x + y
575 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
576 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
577 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE, size) == fWriter.bytesWritten());
578 this->addPaintPtr(paint);
579 this->addImage(image);
580 this->addScalar(x);
581 this->addScalar(y);
582 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700583}
584
585void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
586 const SkPaint* paint) {
reed871872f2015-06-22 12:48:26 -0700587 // id + paint_index + bitmap_index + bool_for_src
588 size_t size = 4 * kUInt32Size;
589 if (src) {
590 size += sizeof(*src); // + rect
reeda85d4d02015-05-06 12:56:48 -0700591 }
reed871872f2015-06-22 12:48:26 -0700592 size += sizeof(dst); // + rect
593
594 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
595 SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE_RECT, size)
596 == fWriter.bytesWritten());
597 this->addPaintPtr(paint);
598 this->addImage(image);
599 this->addRectPtr(src); // may be null
600 this->addRect(dst);
601 this->validate(initialOffset, size);
reeda85d4d02015-05-06 12:56:48 -0700602}
603
reed41af9662015-01-05 07:49:08 -0800604void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
605 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000606 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000607 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000608 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
mtklein8e126562014-10-01 09:29:35 -0700609 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000610 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000611 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000612 this->addIRect(center);
613 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000614 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000615}
616
reed41af9662015-01-05 07:49:08 -0800617void SkPictureRecord::onDrawSprite(const SkBitmap& bitmap, int left, int top,
618 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000619 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000620 size_t size = 5 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000621 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
mtklein8e126562014-10-01 09:29:35 -0700622 SkASSERT(initialOffset+get_paint_offset(DRAW_SPRITE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000623 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000624 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000625 this->addInt(left);
626 this->addInt(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000627 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000628}
629
reed@google.come0d9ce82014-04-23 04:00:17 +0000630void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
631 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000632 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000633 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000634
mtklein46616af2014-09-30 14:47:10 -0700635 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000636 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700637 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700638 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000639 this->addText(text, byteLength);
640 this->addScalar(x);
641 this->addScalar(y);
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::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
646 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000647 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000648
mtklein46616af2014-09-30 14:47:10 -0700649 // op + paint index + length + 'length' worth of data + num points + x&y point data
650 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000651
mtklein46616af2014-09-30 14:47:10 -0700652 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000653
robertphillips@google.com8b169312013-10-15 17:47:36 +0000654 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700655 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700656 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000657 this->addText(text, byteLength);
658 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700659 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000660 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000661}
662
reed@google.come0d9ce82014-04-23 04:00:17 +0000663void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
664 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000665 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000666
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000667 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000668 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000669 // + y + the actual points
670 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000671
mtklein46616af2014-09-30 14:47:10 -0700672 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
673 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000674 this->addText(text, byteLength);
675 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000676 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000677 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000678 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000679}
680
reed@google.come0d9ce82014-04-23 04:00:17 +0000681void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
682 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000683 // op + paint index + length + 'length' worth of data + path index + matrix
684 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000685 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000686 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700687 SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000688 this->addPaint(paint);
689 this->addText(text, byteLength);
690 this->addPath(path);
691 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000692 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000693}
694
fmalitab7425172014-08-26 07:56:44 -0700695void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
696 const SkPaint& paint) {
697
698 // op + paint index + blob index + x/y
699 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
700 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
mtklein8e126562014-10-01 09:29:35 -0700701 SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
fmalitab7425172014-08-26 07:56:44 -0700702
703 this->addPaint(paint);
704 this->addTextBlob(blob);
705 this->addScalar(x);
706 this->addScalar(y);
707
708 this->validate(initialOffset, size);
709}
710
reedd5fa1a42014-08-09 11:08:05 -0700711void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
712 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000713 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000714 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700715 size_t initialOffset;
716
717 if (NULL == matrix && NULL == paint) {
718 initialOffset = this->addDraw(DRAW_PICTURE, &size);
719 this->addPicture(picture);
720 } else {
721 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
722 size += m.writeToMemory(NULL) + kUInt32Size; // matrix + paint
723 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700724 SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
fmalita9f49cfd2014-08-12 12:24:17 -0700725 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700726 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700727 this->addMatrix(m);
728 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700729 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000730 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000731}
732
reed41af9662015-01-05 07:49:08 -0800733void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
734 const SkPoint vertices[], const SkPoint texs[],
735 const SkColor colors[], SkXfermode* xfer,
736 const uint16_t indices[], int indexCount,
737 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000738 uint32_t flags = 0;
739 if (texs) {
740 flags |= DRAW_VERTICES_HAS_TEXS;
741 }
742 if (colors) {
743 flags |= DRAW_VERTICES_HAS_COLORS;
744 }
745 if (indexCount > 0) {
746 flags |= DRAW_VERTICES_HAS_INDICES;
747 }
bsalomon49f085d2014-09-05 13:34:00 -0700748 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000749 SkXfermode::Mode mode;
750 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
751 flags |= DRAW_VERTICES_HAS_XFER;
752 }
753 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000754
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000755 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000756 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000757 if (flags & DRAW_VERTICES_HAS_TEXS) {
758 size += vertexCount * sizeof(SkPoint); // + uvs
759 }
760 if (flags & DRAW_VERTICES_HAS_COLORS) {
761 size += vertexCount * sizeof(SkColor); // + vert colors
762 }
763 if (flags & DRAW_VERTICES_HAS_INDICES) {
764 // + num indices + indices
765 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
766 }
reed@google.com85e143c2013-12-30 15:51:25 +0000767 if (flags & DRAW_VERTICES_HAS_XFER) {
768 size += kUInt32Size; // mode enum
769 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000770
robertphillips@google.com8b169312013-10-15 17:47:36 +0000771 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
mtklein8e126562014-10-01 09:29:35 -0700772 SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000773 this->addPaint(paint);
774 this->addInt(flags);
775 this->addInt(vmode);
776 this->addInt(vertexCount);
777 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000778 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000779 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000780 }
781 if (flags & DRAW_VERTICES_HAS_COLORS) {
782 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
783 }
784 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000785 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000786 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
787 }
reed@google.com85e143c2013-12-30 15:51:25 +0000788 if (flags & DRAW_VERTICES_HAS_XFER) {
789 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
790 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000791 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000792 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000793 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000794}
795
dandovb3c9d1c2014-08-12 08:34:29 -0700796void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
797 const SkPoint texCoords[4], SkXfermode* xmode,
798 const SkPaint& paint) {
799 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
800 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
801 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700802 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700803 flag |= DRAW_VERTICES_HAS_COLORS;
804 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
805 }
bsalomon49f085d2014-09-05 13:34:00 -0700806 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700807 flag |= DRAW_VERTICES_HAS_TEXS;
808 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
809 }
bsalomon49f085d2014-09-05 13:34:00 -0700810 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700811 SkXfermode::Mode mode;
812 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
813 flag |= DRAW_VERTICES_HAS_XFER;
814 size += kUInt32Size;
815 }
816 }
mtklein46616af2014-09-30 14:47:10 -0700817
dandov963137b2014-08-07 07:49:53 -0700818 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
mtklein8e126562014-10-01 09:29:35 -0700819 SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
dandov963137b2014-08-07 07:49:53 -0700820 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700821 this->addPatch(cubics);
822 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700823
dandovb3c9d1c2014-08-12 08:34:29 -0700824 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700825 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700826 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
827 }
bsalomon49f085d2014-09-05 13:34:00 -0700828 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700829 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
830 }
831 if (flag & DRAW_VERTICES_HAS_XFER) {
832 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
833 xmode->asMode(&mode);
834 this->addInt(mode);
835 }
dandov963137b2014-08-07 07:49:53 -0700836 this->validate(initialOffset, size);
837}
838
reed71c3c762015-06-24 10:29:17 -0700839void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
840 const SkColor colors[], int count, SkXfermode::Mode mode,
841 const SkRect* cull, const SkPaint* paint) {
842 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
843 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
844 uint32_t flags = 0;
845 if (colors) {
846 flags |= DRAW_ATLAS_HAS_COLORS;
847 size += count * sizeof(SkColor);
848 size += sizeof(uint32_t); // xfermode::mode
849 }
850 if (cull) {
851 flags |= DRAW_ATLAS_HAS_CULL;
852 size += sizeof(SkRect);
853 }
854
855 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
856 SkASSERT(initialOffset+get_paint_offset(DRAW_ATLAS, size) == fWriter.bytesWritten());
857 this->addPaintPtr(paint);
858 this->addImage(atlas);
859 this->addInt(flags);
860 this->addInt(count);
861 fWriter.write(xform, count * sizeof(SkRSXform));
862 fWriter.write(tex, count * sizeof(SkRect));
863
864 // write optional parameters
865 if (colors) {
866 fWriter.write(colors, count * sizeof(SkColor));
867 this->addInt(mode);
868 }
869 if (cull) {
870 fWriter.write(cull, sizeof(SkRect));
871 }
872 this->validate(initialOffset, size);
873}
874
reed@android.com8a1c16f2008-12-17 15:59:43 +0000875///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000876
reed4a8126e2014-09-22 07:29:03 -0700877SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000878 return NULL;
reed@google.com76f10a32014-02-05 15:32:21 +0000879}
880
mtkleine0694002014-11-12 12:49:47 -0800881// If we already have a stored, can we reuse it instead of also storing b?
882static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
883 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
884 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
885 // but it sure makes things easier to reason about below.
886 return false;
887 }
888 if (a.pixelRef() == b.pixelRef()) {
889 return true; // Same shape and same pixels -> same bitmap.
890 }
891
892 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
893 if (!a.pixelRef() || !b.pixelRef()) {
894 return false;
895 }
896
897 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
898 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
899 encB(b.pixelRef()->refEncodedData());
900 if (encA && encB) {
901 return encA->equals(encB);
902 } else if (encA || encB) {
903 return false; // One has encoded data but the other does not.
904 }
905
906 // As a last resort, we have to look at the pixels. This will read back textures.
907 SkAutoLockPixels al(a), bl(b);
908 const char* ap = (const char*)a.getPixels();
909 const char* bp = (const char*)b.getPixels();
910 if (ap && bp) {
911 // We check row by row; row bytes might differ.
912 SkASSERT(a.info() == b.info()); // We checked this above.
913 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
914 const SkImageInfo info = a.info();
915 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
916 for (int row = 0; row < info.height(); row++) {
917 if (0 != memcmp(ap, bp, bytesToCompare)) {
918 return false;
919 }
920 ap += a.rowBytes();
921 bp += b.rowBytes();
922 }
923 return true;
924 }
925 return false; // Couldn't get pixels for both bitmaps.
926}
927
928void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
929 // First see if we already have this bitmap. This deduplication should really
930 // only be important for our tests, where bitmaps tend not to be tagged immutable.
931 // In Chrome (and hopefully Android?) they're typically immutable.
932 for (int i = 0; i < fBitmaps.count(); i++) {
933 if (equivalent(fBitmaps[i], bitmap)) {
934 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
935 return;
936 }
937 }
938 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800939 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800940 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800941 fBitmaps.push_back(bitmap);
942 } else {
mtkleine0694002014-11-12 12:49:47 -0800943 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800944 SkBitmap copy;
945 bitmap.copyTo(&copy);
946 copy.setImmutable();
947 fBitmaps.push_back(copy);
948 }
mtkleine0694002014-11-12 12:49:47 -0800949 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000950}
951
reed871872f2015-06-22 12:48:26 -0700952void SkPictureRecord::addImage(const SkImage* image) {
953 int index = fImageRefs.find(image);
954 if (index >= 0) {
955 this->addInt(index);
956 } else {
957 *fImageRefs.append() = SkRef(image);
958 this->addInt(fImageRefs.count()-1);
959 }
960}
961
reed@android.com8a1c16f2008-12-17 15:59:43 +0000962void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000963 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000964}
965
mtklein46616af2014-09-30 14:47:10 -0700966void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700967 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000968
mtklein46616af2014-09-30 14:47:10 -0700969 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800970 fPaints.push_back(*paint);
971 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700972 } else {
973 this->addInt(0);
974 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000975}
976
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000977int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtklein71a23632014-11-12 10:24:55 -0800978 fPaths.push_back(path);
979 return fPaths.count();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000980}
981
982void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000983 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000984}
985
dandovb3c9d1c2014-08-12 08:34:29 -0700986void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
987 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700988}
989
robertphillips9b14f262014-06-04 05:40:44 -0700990void SkPictureRecord::addPicture(const SkPicture* picture) {
991 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000992 if (index < 0) { // not found
993 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700994 *fPictureRefs.append() = picture;
995 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000996 }
997 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000998 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000999}
1000
1001void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001002 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001003}
reed@google.com82065d62011-02-07 15:30:46 +00001004
reed@android.com8a1c16f2008-12-17 15:59:43 +00001005void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
1006 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001007}
1008
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001009void SkPictureRecord::addNoOp() {
1010 size_t size = kUInt32Size; // op
1011 this->addDraw(NOOP, &size);
1012}
1013
reed@android.com8a1c16f2008-12-17 15:59:43 +00001014void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001015 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001016}
1017
1018void SkPictureRecord::addRectPtr(const SkRect* rect) {
1019 if (fWriter.writeBool(rect != NULL)) {
1020 fWriter.writeRect(*rect);
1021 }
1022}
1023
reed@google.comf0b5e112011-09-07 11:57:34 +00001024void SkPictureRecord::addIRect(const SkIRect& rect) {
1025 fWriter.write(&rect, sizeof(rect));
1026}
1027
reed@android.com8a1c16f2008-12-17 15:59:43 +00001028void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
1029 if (fWriter.writeBool(rect != NULL)) {
1030 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
1031 }
1032}
1033
reed@google.com4ed0fb72012-12-12 20:48:18 +00001034void SkPictureRecord::addRRect(const SkRRect& rrect) {
1035 fWriter.writeRRect(rrect);
1036}
1037
reed@android.com8a1c16f2008-12-17 15:59:43 +00001038void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001039 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001040}
1041
1042void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001043 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001044 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001045 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001046}
1047
fmalitab7425172014-08-26 07:56:44 -07001048void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001049 int index = fTextBlobRefs.count();
1050 *fTextBlobRefs.append() = blob;
1051 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001052 // follow the convention of recording a 1-based index
1053 this->addInt(index + 1);
1054}
1055
reed@android.com8a1c16f2008-12-17 15:59:43 +00001056///////////////////////////////////////////////////////////////////////////////
1057