blob: 00c51ac3051c873e3ab453fa52d34d6c485e4188 [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"
dandovb3c9d1c2014-08-12 08:34:29 -070010#include "SkPatchUtils.h"
dandovb3c9d1c2014-08-12 08:34:29 -070011#include "SkPixelRef.h"
12#include "SkRRect.h"
fmalitab7425172014-08-26 07:56:44 -070013#include "SkTextBlob.h"
dandovb3c9d1c2014-08-12 08:34:29 -070014#include "SkTSearch.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015
reed@android.com8a1c16f2008-12-17 15:59:43 +000016#define HEAP_BLOCK_SIZE 4096
17
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000018enum {
reed@google.comd86e7ab2012-09-27 20:31:31 +000019 // just need a value that save or getSaveCount would never return
junov@chromium.org4e6dfa52012-07-16 14:04:59 +000020 kNoInitialSave = -1,
21};
22
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +000023// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
24static int const kUInt32Size = 4;
25
Florin Malita5f6102d2014-06-30 10:13:28 -040026static const uint32_t kSaveSize = kUInt32Size;
mtklein8e126562014-10-01 09:29:35 -070027#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000028static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
29static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
mtklein8e126562014-10-01 09:29:35 -070030#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000031
robertphillips0bdbea72014-06-11 11:37:55 -070032SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
commit-bot@chromium.org19fafef2014-02-17 15:28:00 +000033 : INHERITED(dimensions.width(), dimensions.height())
mtklein46616af2014-09-30 14:47:10 -070034 , fRecordFlags(flags) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000035
djsollen@google.comc9ab9872012-08-29 18:52:07 +000036 fBitmapHeap = SkNEW(SkBitmapHeap);
commit-bot@chromium.org8016f792014-03-07 15:53:01 +000037
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +000038 fFirstSavedLayerIndex = kNoSavedLayerIndex;
reed@google.comd86e7ab2012-09-27 20:31:31 +000039 fInitialSaveCount = kNoInitialSave;
reed@android.com8a1c16f2008-12-17 15:59:43 +000040}
41
42SkPictureRecord::~SkPictureRecord() {
djsollen@google.comc9ab9872012-08-29 18:52:07 +000043 SkSafeUnref(fBitmapHeap);
djsollen@google.com21830d92012-08-07 19:49:41 +000044 fPictureRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070045 fTextBlobRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000046}
47
48///////////////////////////////////////////////////////////////////////////////
49
mtklein8e126562014-10-01 09:29:35 -070050#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000051// Return the offset of the paint inside a given op's byte stream. A zero
52// return value means there is no paint (and you really shouldn't be calling
53// this method)
mtklein8e126562014-10-01 09:29:35 -070054static inline size_t get_paint_offset(DrawType op, size_t opSize) {
robertphillips@google.come37ad352013-03-01 19:44:30 +000055 // These offsets are where the paint would be if the op size doesn't overflow
fmalita9f49cfd2014-08-12 12:24:17 -070056 static const uint8_t gPaintOffsets[] = {
robertphillips@google.come37ad352013-03-01 19:44:30 +000057 0, // UNUSED - no paint
58 0, // CLIP_PATH - no paint
59 0, // CLIP_REGION - no paint
60 0, // CLIP_RECT - no paint
61 0, // CLIP_RRECT - no paint
62 0, // CONCAT - no paint
63 1, // DRAW_BITMAP - right after op code
64 1, // DRAW_BITMAP_MATRIX - right after op code
65 1, // DRAW_BITMAP_NINE - right after op code
66 1, // DRAW_BITMAP_RECT_TO_RECT - right after op code
67 0, // DRAW_CLEAR - no paint
68 0, // DRAW_DATA - no paint
69 1, // DRAW_OVAL - right after op code
70 1, // DRAW_PAINT - right after op code
71 1, // DRAW_PATH - right after op code
72 0, // DRAW_PICTURE - no paint
73 1, // DRAW_POINTS - right after op code
74 1, // DRAW_POS_TEXT - right after op code
75 1, // DRAW_POS_TEXT_TOP_BOTTOM - right after op code
76 1, // DRAW_POS_TEXT_H - right after op code
77 1, // DRAW_POS_TEXT_H_TOP_BOTTOM - right after op code
78 1, // DRAW_RECT - right after op code
79 1, // DRAW_RRECT - right after op code
80 1, // DRAW_SPRITE - right after op code
81 1, // DRAW_TEXT - right after op code
82 1, // DRAW_TEXT_ON_PATH - right after op code
83 1, // DRAW_TEXT_TOP_BOTTOM - right after op code
84 1, // DRAW_VERTICES - right after op code
85 0, // RESTORE - no paint
86 0, // ROTATE - no paint
87 0, // SAVE - no paint
skia.committer@gmail.comf140f182013-03-02 07:01:56 +000088 0, // SAVE_LAYER - see below - this paint's location varies
robertphillips@google.come37ad352013-03-01 19:44:30 +000089 0, // SCALE - no paint
90 0, // SET_MATRIX - no paint
91 0, // SKEW - no paint
92 0, // TRANSLATE - no paint
93 0, // NOOP - no paint
robertphillips@google.com0a4805e2013-05-29 13:24:23 +000094 0, // BEGIN_GROUP - no paint
95 0, // COMMENT - no paint
96 0, // END_GROUP - no paint
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +000097 1, // DRAWDRRECT - right after op code
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +000098 0, // PUSH_CULL - no paint
99 0, // POP_CULL - no paint
dandov963137b2014-08-07 07:49:53 -0700100 1, // DRAW_PATCH - right after op code
fmalita9f49cfd2014-08-12 12:24:17 -0700101 1, // DRAW_PICTURE_MATRIX_PAINT - right after op code
fmalitab7425172014-08-26 07:56:44 -0700102 1, // DRAW_TEXT_BLOB- right after op code
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000103 };
robertphillips@google.come37ad352013-03-01 19:44:30 +0000104
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000105 SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
106 need_to_be_in_sync);
robertphillips@google.come37ad352013-03-01 19:44:30 +0000107 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
108
109 int overflow = 0;
110 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
111 // This op's size overflows so an extra uint32_t will be written
112 // after the op code
113 overflow = sizeof(uint32_t);
114 }
115
116 if (SAVE_LAYER == op) {
117 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
118 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
119
120 if (kSaveLayerNoBoundsSize == opSize) {
121 return kSaveLayerNoBoundsPaintOffset + overflow;
122 } else {
123 SkASSERT(kSaveLayerWithBoundsSize == opSize);
124 return kSaveLayerWithBoundsPaintOffset + overflow;
125 }
126 }
127
128 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this method
129 return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
130}
mtklein8e126562014-10-01 09:29:35 -0700131#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +0000132
Florin Malita5f6102d2014-06-30 10:13:28 -0400133void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +0000134 // record the offset to us, making it non-positive to distinguish a save
135 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000136 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -0400137 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000138
Florin Malita5f6102d2014-06-30 10:13:28 -0400139 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000140}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000141
Florin Malita5f6102d2014-06-30 10:13:28 -0400142void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -0700143 fContentInfo.onSave();
144
Florin Malita5f6102d2014-06-30 10:13:28 -0400145 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000146 size_t size = kSaveSize;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000147 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +0000148
robertphillips@google.com8b169312013-10-15 17:47:36 +0000149 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150}
151
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000152SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
153 const SkPaint* paint, SaveFlags flags) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000154 // record the offset to us, making it non-positive to distinguish a save
155 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000156 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000157 this->recordSaveLayer(bounds, paint, flags);
158 if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
159 fFirstSavedLayerIndex = fRestoreOffsetStack.count();
160 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000161
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000162 this->INHERITED::willSaveLayer(bounds, paint, flags);
163 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000164 at this time (and may not be able to afford since during record our
165 clip starts out the size of the picture, which is often much larger
166 than the size of the actual device we'll use during playback).
167 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000168 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000169}
170
171void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000172 SaveFlags flags) {
robertphillipsc019ec42014-08-12 05:35:58 -0700173 fContentInfo.onSaveLayer();
174
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000175 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000176 size_t size = 2 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700177 if (bounds) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000178 size += sizeof(*bounds); // + rect
179 }
180 // + paint index + flags
181 size += 2 * kUInt32Size;
182
robertphillips@google.come37ad352013-03-01 19:44:30 +0000183 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
184
robertphillips@google.com8b169312013-10-15 17:47:36 +0000185 size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000186 this->addRectPtr(bounds);
mtklein8e126562014-10-01 09:29:35 -0700187 SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000188 this->addPaintPtr(paint);
189 this->addInt(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000190
robertphillips@google.com8b169312013-10-15 17:47:36 +0000191 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192}
193
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000194bool SkPictureRecord::isDrawingToLayer() const {
195 return fFirstSavedLayerIndex != kNoSavedLayerIndex;
196}
197
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000198#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000199/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000200 * Read the op code from 'offset' in 'writer' and extract the size too.
201 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000202static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000203 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000204
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000205 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000206 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000207 if (MASK_24 == *size) {
208 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000209 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000210 }
211 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000212}
mtklein46616af2014-09-30 14:47:10 -0700213#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000214
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000215void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000216 // FIXME: SkDeferredCanvas needs to be refactored to respect
217 // save/restore balancing so that the following test can be
218 // turned on permanently.
219#if 0
220 SkASSERT(fRestoreOffsetStack.count() > 1);
221#endif
222
reed@android.comb4e22d62009-07-09 15:20:25 +0000223 // check for underflow
224 if (fRestoreOffsetStack.count() == 0) {
225 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000227
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000228 if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) {
229 fFirstSavedLayerIndex = kNoSavedLayerIndex;
230 }
231
mtklein46616af2014-09-30 14:47:10 -0700232 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000233
reed@android.comb4e22d62009-07-09 15:20:25 +0000234 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000235
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000236 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000237}
238
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000239void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700240 fContentInfo.onRestore();
241
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000242 if (fillInSkips) {
243 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
244 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000245 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
246 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000247 this->validate(initialOffset, size);
248}
249
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000250void SkPictureRecord::recordTranslate(const SkMatrix& m) {
251 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
252
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000253 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000254 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000255 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000256 this->addScalar(m.getTranslateX());
257 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000258 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259}
260
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000261void SkPictureRecord::recordScale(const SkMatrix& m) {
262 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000263
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000264 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000265 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000266 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000267 this->addScalar(m.getScaleX());
268 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000269 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270}
271
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000272void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000273 switch (matrix.getType()) {
274 case SkMatrix::kTranslate_Mask:
275 this->recordTranslate(matrix);
276 break;
277 case SkMatrix::kScale_Mask:
278 this->recordScale(matrix);
279 break;
280 default:
281 this->recordConcat(matrix);
282 break;
283 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000284 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000285}
286
287void SkPictureRecord::recordConcat(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(CONCAT, &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);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294}
295
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000296void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000297 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000298 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000299 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000300 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000301 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000302 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000303 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000304}
305
reed@google.com45482d12011-08-29 19:02:39 +0000306static bool regionOpExpands(SkRegion::Op op) {
307 switch (op) {
308 case SkRegion::kUnion_Op:
309 case SkRegion::kXOR_Op:
310 case SkRegion::kReverseDifference_Op:
311 case SkRegion::kReplace_Op:
312 return true;
313 case SkRegion::kIntersect_Op:
314 case SkRegion::kDifference_Op:
315 return false;
316 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000317 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000318 return false;
319 }
320}
321
robertphillips@google.come37ad352013-03-01 19:44:30 +0000322void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000323 int32_t offset = fRestoreOffsetStack.top();
324 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000325 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
326 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000327 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000328 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000329
reed@google.comffacd3c2012-08-30 15:31:23 +0000330#ifdef SK_DEBUG
331 // assert that the final offset value points to a save verb
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000332 uint32_t opSize;
333 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
reed@google.comffacd3c2012-08-30 15:31:23 +0000334 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
335#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000336}
337
reed@google.comd86e7ab2012-09-27 20:31:31 +0000338void SkPictureRecord::beginRecording() {
339 // we have to call this *after* our constructor, to ensure that it gets
340 // recorded. This is balanced by restoreToCount() call from endRecording,
341 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000342 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000343}
344
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000345void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000346 SkASSERT(kNoInitialSave != fInitialSaveCount);
347 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000348}
349
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000350size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000351 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000352 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000353 }
354
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000355 // The RestoreOffset field is initially filled with a placeholder
356 // value that points to the offset of the previous RestoreOffset
357 // in the current stack level, thus forming a linked list so that
358 // the restore offsets can be filled in when the corresponding
359 // restore command is recorded.
360 int32_t prevOffset = fRestoreOffsetStack.top();
361
reed@google.com45482d12011-08-29 19:02:39 +0000362 if (regionOpExpands(op)) {
363 // Run back through any previous clip ops, and mark their offset to
364 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
365 // they could hide this clips ability to expand the clip (i.e. go from
366 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000367 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000368
369 // Reset the pointer back to the previous clip so that subsequent
370 // restores don't overwrite the offsets we just cleared.
371 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000372 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000373
reed@google.com44699382013-10-31 17:28:30 +0000374 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000375 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000376 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000377 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000378}
379
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000380void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000381 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000382 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000383}
384
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000385size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000386 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000387 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000388 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000389 if (!fRestoreOffsetStack.isEmpty()) {
390 // + restore offset
391 size += kUInt32Size;
392 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000393 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000394 this->addRect(rect);
395 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000396 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000397
robertphillips@google.com8b169312013-10-15 17:47:36 +0000398 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000399 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000400}
401
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000402void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000403 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700404 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000405}
406
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000407size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000408 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000409 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000410 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000411 if (!fRestoreOffsetStack.isEmpty()) {
412 // + restore offset
413 size += kUInt32Size;
414 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000415 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000416 this->addRRect(rrect);
417 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000418 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000419 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000420 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000421}
422
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000423void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000424 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000425 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700426 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000427}
428
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000429size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000430 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000431 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000432 // recordRestoreOffsetPlaceholder doesn't always write an offset
433 if (!fRestoreOffsetStack.isEmpty()) {
434 // + restore offset
435 size += kUInt32Size;
436 }
437 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000438 this->addInt(pathID);
439 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000440 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000441 this->validate(initialOffset, size);
442 return offset;
443}
444
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000445void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000446 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000447 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000448}
449
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000450size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000451 // op + clip params + region
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000452 size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000453 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000454 if (!fRestoreOffsetStack.isEmpty()) {
455 // + restore offset
456 size += kUInt32Size;
457 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000458 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000459 this->addRegion(region);
460 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000461 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000462
robertphillips@google.com8b169312013-10-15 17:47:36 +0000463 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000464 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000465}
466
reed@google.com2a981812011-04-14 18:59:28 +0000467void SkPictureRecord::clear(SkColor color) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000468 // op + color
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000469 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000470 size_t initialOffset = this->addDraw(DRAW_CLEAR, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000471 this->addInt(color);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000472 this->validate(initialOffset, size);
reed@google.com2a981812011-04-14 18:59:28 +0000473}
474
reed@android.com8a1c16f2008-12-17 15:59:43 +0000475void SkPictureRecord::drawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000476 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000477 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000478 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700479 SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000480 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000481 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000482}
483
484void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000485 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700486 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000487
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000488 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000489 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000490 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
mtklein8e126562014-10-01 09:29:35 -0700491 SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000492 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700493
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000494 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000495 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000496 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000497 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000498}
499
reed@google.com4ed0fb72012-12-12 20:48:18 +0000500void SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000501 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000502 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000503 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
mtklein8e126562014-10-01 09:29:35 -0700504 SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000505 this->addPaint(paint);
506 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000507 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000508}
509
bsalomon@google.com7ce564c2013-10-22 16:54:15 +0000510void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000511 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000512 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000513 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700514 SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000515 this->addPaint(paint);
516 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000517 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000518}
519
reed@google.com4ed0fb72012-12-12 20:48:18 +0000520void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700521 // op + paint index + rrect
522 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
523 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700524 SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700525 this->addPaint(paint);
526 this->addRRect(rrect);
527 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000528}
529
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000530void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
531 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000532 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000533 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
534 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700535 SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000536 this->addPaint(paint);
537 this->addRRect(outer);
538 this->addRRect(inner);
539 this->validate(initialOffset, size);
540}
541
bsalomon@google.com7ce564c2013-10-22 16:54:15 +0000542void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700543 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000544
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000545 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000546 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000547 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700548 SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000549 this->addPaint(paint);
550 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000551 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000552}
553
554void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000555 const SkPaint* paint = NULL) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000556 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000557 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000558 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
mtklein8e126562014-10-01 09:29:35 -0700559 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000560 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000561 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000562 this->addScalar(left);
563 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000564 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000565}
566
reed@google.com71121732012-09-18 15:14:33 +0000567void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000568 const SkRect& dst, const SkPaint* paint,
569 DrawBitmapRectFlags flags) {
570 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000571 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700572 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000573 size += sizeof(*src); // + rect
574 }
575 size += sizeof(dst); // + rect
576
robertphillips@google.com8b169312013-10-15 17:47:36 +0000577 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700578 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT_TO_RECT, size)
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000579 == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000580 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000581 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000582 this->addRectPtr(src); // may be null
583 this->addRect(dst);
584 this->addInt(flags);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000585 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000586}
587
588void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
reed@google.comf0b5e112011-09-07 11:57:34 +0000589 const SkPaint* paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000590 // id + paint index + bitmap index + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000591 size_t size = 3 * kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000592 size_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
mtklein8e126562014-10-01 09:29:35 -0700593 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_MATRIX, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000594 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000595 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000596 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000597 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000598}
599
reed@google.comf0b5e112011-09-07 11:57:34 +0000600void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
601 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000602 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000603 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000604 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
mtklein8e126562014-10-01 09:29:35 -0700605 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000606 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000607 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000608 this->addIRect(center);
609 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000610 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000611}
612
reed@android.com8a1c16f2008-12-17 15:59:43 +0000613void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000614 const SkPaint* paint = NULL) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000615 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000616 size_t size = 5 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000617 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
mtklein8e126562014-10-01 09:29:35 -0700618 SkASSERT(initialOffset+get_paint_offset(DRAW_SPRITE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000619 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000620 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000621 this->addInt(left);
622 this->addInt(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000623 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000624}
625
reed@google.come0d9ce82014-04-23 04:00:17 +0000626void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
627 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000628 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000629 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000630
mtklein46616af2014-09-30 14:47:10 -0700631 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000632 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700633 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700634 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000635 this->addText(text, byteLength);
636 this->addScalar(x);
637 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000638 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000639}
640
reed@google.come0d9ce82014-04-23 04:00:17 +0000641void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
642 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000643 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000644
mtklein46616af2014-09-30 14:47:10 -0700645 // op + paint index + length + 'length' worth of data + num points + x&y point data
646 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000647
mtklein46616af2014-09-30 14:47:10 -0700648 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000649
robertphillips@google.com8b169312013-10-15 17:47:36 +0000650 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700651 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700652 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000653 this->addText(text, byteLength);
654 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700655 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000656 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000657}
658
reed@google.come0d9ce82014-04-23 04:00:17 +0000659void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
660 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000661 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000662
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000663 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000664 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000665 // + y + the actual points
666 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000667
mtklein46616af2014-09-30 14:47:10 -0700668 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
669 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000670 this->addText(text, byteLength);
671 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000672 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000673 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000674 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000675}
676
reed@google.come0d9ce82014-04-23 04:00:17 +0000677void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
678 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000679 // op + paint index + length + 'length' worth of data + path index + matrix
680 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000681 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000682 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700683 SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000684 this->addPaint(paint);
685 this->addText(text, byteLength);
686 this->addPath(path);
687 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000688 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000689}
690
fmalitab7425172014-08-26 07:56:44 -0700691void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
692 const SkPaint& paint) {
693
694 // op + paint index + blob index + x/y
695 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
696 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
mtklein8e126562014-10-01 09:29:35 -0700697 SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
fmalitab7425172014-08-26 07:56:44 -0700698
699 this->addPaint(paint);
700 this->addTextBlob(blob);
701 this->addScalar(x);
702 this->addScalar(y);
703
704 this->validate(initialOffset, size);
705}
706
reedd5fa1a42014-08-09 11:08:05 -0700707void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
708 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000709 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000710 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700711 size_t initialOffset;
712
713 if (NULL == matrix && NULL == paint) {
714 initialOffset = this->addDraw(DRAW_PICTURE, &size);
715 this->addPicture(picture);
716 } else {
717 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
718 size += m.writeToMemory(NULL) + kUInt32Size; // matrix + paint
719 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700720 SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
fmalita9f49cfd2014-08-12 12:24:17 -0700721 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700722 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700723 this->addMatrix(m);
724 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700725 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000726 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000727}
728
729void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
730 const SkPoint vertices[], const SkPoint texs[],
reed@google.com85e143c2013-12-30 15:51:25 +0000731 const SkColor colors[], SkXfermode* xfer,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000732 const uint16_t indices[], int indexCount,
733 const SkPaint& paint) {
734 uint32_t flags = 0;
735 if (texs) {
736 flags |= DRAW_VERTICES_HAS_TEXS;
737 }
738 if (colors) {
739 flags |= DRAW_VERTICES_HAS_COLORS;
740 }
741 if (indexCount > 0) {
742 flags |= DRAW_VERTICES_HAS_INDICES;
743 }
bsalomon49f085d2014-09-05 13:34:00 -0700744 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000745 SkXfermode::Mode mode;
746 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
747 flags |= DRAW_VERTICES_HAS_XFER;
748 }
749 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000750
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000751 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000752 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000753 if (flags & DRAW_VERTICES_HAS_TEXS) {
754 size += vertexCount * sizeof(SkPoint); // + uvs
755 }
756 if (flags & DRAW_VERTICES_HAS_COLORS) {
757 size += vertexCount * sizeof(SkColor); // + vert colors
758 }
759 if (flags & DRAW_VERTICES_HAS_INDICES) {
760 // + num indices + indices
761 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
762 }
reed@google.com85e143c2013-12-30 15:51:25 +0000763 if (flags & DRAW_VERTICES_HAS_XFER) {
764 size += kUInt32Size; // mode enum
765 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000766
robertphillips@google.com8b169312013-10-15 17:47:36 +0000767 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
mtklein8e126562014-10-01 09:29:35 -0700768 SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000769 this->addPaint(paint);
770 this->addInt(flags);
771 this->addInt(vmode);
772 this->addInt(vertexCount);
773 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000774 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000775 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000776 }
777 if (flags & DRAW_VERTICES_HAS_COLORS) {
778 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
779 }
780 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000781 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000782 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
783 }
reed@google.com85e143c2013-12-30 15:51:25 +0000784 if (flags & DRAW_VERTICES_HAS_XFER) {
785 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
786 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000787 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000788 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000789 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000790}
791
dandovb3c9d1c2014-08-12 08:34:29 -0700792void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
793 const SkPoint texCoords[4], SkXfermode* xmode,
794 const SkPaint& paint) {
795 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
796 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
797 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700798 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700799 flag |= DRAW_VERTICES_HAS_COLORS;
800 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
801 }
bsalomon49f085d2014-09-05 13:34:00 -0700802 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700803 flag |= DRAW_VERTICES_HAS_TEXS;
804 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
805 }
bsalomon49f085d2014-09-05 13:34:00 -0700806 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700807 SkXfermode::Mode mode;
808 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
809 flag |= DRAW_VERTICES_HAS_XFER;
810 size += kUInt32Size;
811 }
812 }
mtklein46616af2014-09-30 14:47:10 -0700813
dandov963137b2014-08-07 07:49:53 -0700814 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
mtklein8e126562014-10-01 09:29:35 -0700815 SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
dandov963137b2014-08-07 07:49:53 -0700816 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700817 this->addPatch(cubics);
818 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700819
dandovb3c9d1c2014-08-12 08:34:29 -0700820 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700821 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700822 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
823 }
bsalomon49f085d2014-09-05 13:34:00 -0700824 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700825 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
826 }
827 if (flag & DRAW_VERTICES_HAS_XFER) {
828 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
829 xmode->asMode(&mode);
830 this->addInt(mode);
831 }
dandov963137b2014-08-07 07:49:53 -0700832 this->validate(initialOffset, size);
833}
834
reed@android.comcb608442009-12-04 21:32:27 +0000835void SkPictureRecord::drawData(const void* data, size_t length) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000836 // op + length + 'length' worth of data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000837 size_t size = 2 * kUInt32Size + SkAlign4(length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000838 size_t initialOffset = this->addDraw(DRAW_DATA, &size);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000839 this->addInt(SkToInt(length));
reed@android.comcb608442009-12-04 21:32:27 +0000840 fWriter.writePad(data, length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000841 this->validate(initialOffset, size);
reed@android.comcb608442009-12-04 21:32:27 +0000842}
843
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000844void SkPictureRecord::beginCommentGroup(const char* description) {
845 // op/size + length of string + \0 terminated chars
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000846 size_t length = strlen(description);
847 size_t size = 2 * kUInt32Size + SkAlign4(length + 1);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000848 size_t initialOffset = this->addDraw(BEGIN_COMMENT_GROUP, &size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000849 fWriter.writeString(description, length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000850 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000851}
852
853void SkPictureRecord::addComment(const char* kywd, const char* value) {
854 // op/size + 2x length of string + 2x \0 terminated chars
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000855 size_t kywdLen = strlen(kywd);
856 size_t valueLen = strlen(value);
857 size_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000858 size_t initialOffset = this->addDraw(COMMENT, &size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000859 fWriter.writeString(kywd, kywdLen);
860 fWriter.writeString(value, valueLen);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000861 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000862}
863
864void SkPictureRecord::endCommentGroup() {
865 // op/size
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000866 size_t size = 1 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000867 size_t initialOffset = this->addDraw(END_COMMENT_GROUP, &size);
868 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000869}
870
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000871// [op/size] [rect] [skip offset]
872static const uint32_t kPushCullOpSize = 2 * kUInt32Size + sizeof(SkRect);
873void SkPictureRecord::onPushCull(const SkRect& cullRect) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000874 size_t size = kPushCullOpSize;
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000875 size_t initialOffset = this->addDraw(PUSH_CULL, &size);
876 // PUSH_CULL's size should stay constant (used to rewind).
877 SkASSERT(size == kPushCullOpSize);
878
879 this->addRect(cullRect);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000880 fCullOffsetStack.push(SkToU32(fWriter.bytesWritten()));
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000881 this->addInt(0);
882 this->validate(initialOffset, size);
883}
884
885void SkPictureRecord::onPopCull() {
886 SkASSERT(!fCullOffsetStack.isEmpty());
887
888 uint32_t cullSkipOffset = fCullOffsetStack.top();
889 fCullOffsetStack.pop();
890
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000891 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000892 size_t size = kUInt32Size;
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000893 size_t initialOffset = this->addDraw(POP_CULL, &size);
894
895 // update the cull skip offset to point past this op.
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000896 fWriter.overwriteTAt<uint32_t>(cullSkipOffset, SkToU32(fWriter.bytesWritten()));
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000897
898 this->validate(initialOffset, size);
899}
900
reed@android.com8a1c16f2008-12-17 15:59:43 +0000901///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000902
reed4a8126e2014-09-22 07:29:03 -0700903SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000904 return NULL;
reed@google.com76f10a32014-02-05 15:32:21 +0000905}
906
commit-bot@chromium.org8016f792014-03-07 15:53:01 +0000907int SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
scroggo@google.com4b90b112012-12-04 15:08:56 +0000908 const int index = fBitmapHeap->insert(bitmap);
909 // In debug builds, a bad return value from insert() will crash, allowing for debugging. In
910 // release builds, the invalid value will be recorded so that the reader will know that there
911 // was a problem.
912 SkASSERT(index != SkBitmapHeap::INVALID_SLOT);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000913 this->addInt(index);
commit-bot@chromium.org8016f792014-03-07 15:53:01 +0000914 return index;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000915}
916
917void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000918 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000919}
920
mtklein46616af2014-09-30 14:47:10 -0700921void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700922 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000923
mtklein46616af2014-09-30 14:47:10 -0700924 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800925 fPaints.push_back(*paint);
926 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700927 } else {
928 this->addInt(0);
929 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000930}
931
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000932int SkPictureRecord::addPathToHeap(const SkPath& path) {
robertphillips0bdbea72014-06-11 11:37:55 -0700933 if (NULL == fPathHeap) {
934 fPathHeap.reset(SkNEW(SkPathHeap));
935 }
936#ifdef SK_DEDUP_PICTURE_PATHS
937 return fPathHeap->insert(path);
938#else
939 return fPathHeap->append(path);
940#endif
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000941}
942
943void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000944 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000945}
946
dandovb3c9d1c2014-08-12 08:34:29 -0700947void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
948 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700949}
950
robertphillips9b14f262014-06-04 05:40:44 -0700951void SkPictureRecord::addPicture(const SkPicture* picture) {
952 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000953 if (index < 0) { // not found
954 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700955 *fPictureRefs.append() = picture;
956 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000957 }
958 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000959 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000960}
961
962void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000963 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000964}
reed@google.com82065d62011-02-07 15:30:46 +0000965
reed@android.com8a1c16f2008-12-17 15:59:43 +0000966void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
967 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000968}
969
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000970void SkPictureRecord::addNoOp() {
971 size_t size = kUInt32Size; // op
972 this->addDraw(NOOP, &size);
973}
974
reed@android.com8a1c16f2008-12-17 15:59:43 +0000975void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000976 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000977}
978
979void SkPictureRecord::addRectPtr(const SkRect* rect) {
980 if (fWriter.writeBool(rect != NULL)) {
981 fWriter.writeRect(*rect);
982 }
983}
984
reed@google.comf0b5e112011-09-07 11:57:34 +0000985void SkPictureRecord::addIRect(const SkIRect& rect) {
986 fWriter.write(&rect, sizeof(rect));
987}
988
reed@android.com8a1c16f2008-12-17 15:59:43 +0000989void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
990 if (fWriter.writeBool(rect != NULL)) {
991 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
992 }
993}
994
reed@google.com4ed0fb72012-12-12 20:48:18 +0000995void SkPictureRecord::addRRect(const SkRRect& rrect) {
996 fWriter.writeRRect(rrect);
997}
998
reed@android.com8a1c16f2008-12-17 15:59:43 +0000999void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +00001000 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001001}
1002
1003void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -07001004 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +00001005 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +00001006 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001007}
1008
fmalitab7425172014-08-26 07:56:44 -07001009void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -07001010 int index = fTextBlobRefs.count();
1011 *fTextBlobRefs.append() = blob;
1012 blob->ref();
fmalitab7425172014-08-26 07:56:44 -07001013 // follow the convention of recording a 1-based index
1014 this->addInt(index + 1);
1015}
1016
reed@android.com8a1c16f2008-12-17 15:59:43 +00001017///////////////////////////////////////////////////////////////////////////////
1018