blob: 53ecdd0be68c08e332c93cc8598d92b32b76b264 [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())
mtklein71a23632014-11-12 10:24:55 -080034 , fRecordFlags(flags)
35 , fInitialSaveCount(kNoInitialSave) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000036}
37
38SkPictureRecord::~SkPictureRecord() {
djsollen@google.com21830d92012-08-07 19:49:41 +000039 fPictureRefs.unrefAll();
fmalitab7425172014-08-26 07:56:44 -070040 fTextBlobRefs.unrefAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000041}
42
43///////////////////////////////////////////////////////////////////////////////
44
mtklein8e126562014-10-01 09:29:35 -070045#ifdef SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +000046// Return the offset of the paint inside a given op's byte stream. A zero
47// return value means there is no paint (and you really shouldn't be calling
48// this method)
mtklein8e126562014-10-01 09:29:35 -070049static inline size_t get_paint_offset(DrawType op, size_t opSize) {
robertphillips@google.come37ad352013-03-01 19:44:30 +000050 // These offsets are where the paint would be if the op size doesn't overflow
fmalita9f49cfd2014-08-12 12:24:17 -070051 static const uint8_t gPaintOffsets[] = {
robertphillips@google.come37ad352013-03-01 19:44:30 +000052 0, // UNUSED - no paint
53 0, // CLIP_PATH - no paint
54 0, // CLIP_REGION - no paint
55 0, // CLIP_RECT - no paint
56 0, // CLIP_RRECT - no paint
57 0, // CONCAT - no paint
58 1, // DRAW_BITMAP - right after op code
Florin Malitac54d8db2014-12-10 12:02:16 -050059 1, // DRAW_BITMAP_MATRIX - right after op code, deprecated
robertphillips@google.come37ad352013-03-01 19:44:30 +000060 1, // DRAW_BITMAP_NINE - right after op code
61 1, // DRAW_BITMAP_RECT_TO_RECT - right after op code
62 0, // DRAW_CLEAR - no paint
63 0, // DRAW_DATA - no paint
64 1, // DRAW_OVAL - right after op code
65 1, // DRAW_PAINT - right after op code
66 1, // DRAW_PATH - right after op code
67 0, // DRAW_PICTURE - no paint
68 1, // DRAW_POINTS - right after op code
69 1, // DRAW_POS_TEXT - right after op code
70 1, // DRAW_POS_TEXT_TOP_BOTTOM - right after op code
71 1, // DRAW_POS_TEXT_H - right after op code
72 1, // DRAW_POS_TEXT_H_TOP_BOTTOM - right after op code
73 1, // DRAW_RECT - right after op code
74 1, // DRAW_RRECT - right after op code
75 1, // DRAW_SPRITE - right after op code
76 1, // DRAW_TEXT - right after op code
77 1, // DRAW_TEXT_ON_PATH - right after op code
78 1, // DRAW_TEXT_TOP_BOTTOM - right after op code
79 1, // DRAW_VERTICES - right after op code
80 0, // RESTORE - no paint
81 0, // ROTATE - no paint
82 0, // SAVE - no paint
skia.committer@gmail.comf140f182013-03-02 07:01:56 +000083 0, // SAVE_LAYER - see below - this paint's location varies
robertphillips@google.come37ad352013-03-01 19:44:30 +000084 0, // SCALE - no paint
85 0, // SET_MATRIX - no paint
86 0, // SKEW - no paint
87 0, // TRANSLATE - no paint
88 0, // NOOP - no paint
robertphillips@google.com0a4805e2013-05-29 13:24:23 +000089 0, // BEGIN_GROUP - no paint
90 0, // COMMENT - no paint
91 0, // END_GROUP - no paint
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +000092 1, // DRAWDRRECT - right after op code
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +000093 0, // PUSH_CULL - no paint
94 0, // POP_CULL - no paint
dandov963137b2014-08-07 07:49:53 -070095 1, // DRAW_PATCH - right after op code
fmalita9f49cfd2014-08-12 12:24:17 -070096 1, // DRAW_PICTURE_MATRIX_PAINT - right after op code
fmalitab7425172014-08-26 07:56:44 -070097 1, // DRAW_TEXT_BLOB- right after op code
skia.committer@gmail.comf140f182013-03-02 07:01:56 +000098 };
robertphillips@google.come37ad352013-03-01 19:44:30 +000099
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000100 SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
101 need_to_be_in_sync);
robertphillips@google.come37ad352013-03-01 19:44:30 +0000102 SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
103
104 int overflow = 0;
105 if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
106 // This op's size overflows so an extra uint32_t will be written
107 // after the op code
108 overflow = sizeof(uint32_t);
109 }
110
111 if (SAVE_LAYER == op) {
112 static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
113 static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
114
115 if (kSaveLayerNoBoundsSize == opSize) {
116 return kSaveLayerNoBoundsPaintOffset + overflow;
117 } else {
118 SkASSERT(kSaveLayerWithBoundsSize == opSize);
119 return kSaveLayerWithBoundsPaintOffset + overflow;
120 }
121 }
122
123 SkASSERT(0 != gPaintOffsets[op]); // really shouldn't be calling this method
124 return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
125}
mtklein8e126562014-10-01 09:29:35 -0700126#endif//SK_DEBUG
robertphillips@google.come37ad352013-03-01 19:44:30 +0000127
Florin Malita5f6102d2014-06-30 10:13:28 -0400128void SkPictureRecord::willSave() {
reed@google.comffacd3c2012-08-30 15:31:23 +0000129 // record the offset to us, making it non-positive to distinguish a save
130 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000131 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
Florin Malita5f6102d2014-06-30 10:13:28 -0400132 this->recordSave();
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000133
Florin Malita5f6102d2014-06-30 10:13:28 -0400134 this->INHERITED::willSave();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000135}
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000136
Florin Malita5f6102d2014-06-30 10:13:28 -0400137void SkPictureRecord::recordSave() {
robertphillipsc019ec42014-08-12 05:35:58 -0700138 fContentInfo.onSave();
139
Florin Malita5f6102d2014-06-30 10:13:28 -0400140 // op only
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000141 size_t size = kSaveSize;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000142 size_t initialOffset = this->addDraw(SAVE, &size);
reed@google.com82065d62011-02-07 15:30:46 +0000143
robertphillips@google.com8b169312013-10-15 17:47:36 +0000144 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145}
146
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000147SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
148 const SkPaint* paint, SaveFlags flags) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000149 // record the offset to us, making it non-positive to distinguish a save
150 // from a clip entry.
reed@google.com44699382013-10-31 17:28:30 +0000151 fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000152 this->recordSaveLayer(bounds, paint, flags);
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000153
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000154 this->INHERITED::willSaveLayer(bounds, paint, flags);
155 /* No need for a (potentially very big) layer which we don't actually need
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000156 at this time (and may not be able to afford since during record our
157 clip starts out the size of the picture, which is often much larger
158 than the size of the actual device we'll use during playback).
159 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000160 return kNoLayer_SaveLayerStrategy;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000161}
162
163void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000164 SaveFlags flags) {
robertphillipsc019ec42014-08-12 05:35:58 -0700165 fContentInfo.onSaveLayer();
166
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000167 // op + bool for 'bounds'
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000168 size_t size = 2 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700169 if (bounds) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000170 size += sizeof(*bounds); // + rect
171 }
172 // + paint index + flags
173 size += 2 * kUInt32Size;
174
robertphillips@google.come37ad352013-03-01 19:44:30 +0000175 SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
176
robertphillips@google.com8b169312013-10-15 17:47:36 +0000177 size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000178 this->addRectPtr(bounds);
mtklein8e126562014-10-01 09:29:35 -0700179 SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000180 this->addPaintPtr(paint);
181 this->addInt(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000182
robertphillips@google.com8b169312013-10-15 17:47:36 +0000183 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184}
185
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000186#ifdef SK_DEBUG
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +0000187/*
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000188 * Read the op code from 'offset' in 'writer' and extract the size too.
189 */
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000190static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000191 uint32_t peek = writer->readTAt<uint32_t>(offset);
reed@google.comffacd3c2012-08-30 15:31:23 +0000192
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000193 uint32_t op;
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000194 UNPACK_8_24(peek, op, *size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000195 if (MASK_24 == *size) {
196 // size required its own slot right after the op code
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000197 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000198 }
199 return (DrawType) op;
reed@google.comffacd3c2012-08-30 15:31:23 +0000200}
mtklein46616af2014-09-30 14:47:10 -0700201#endif//SK_DEBUG
commit-bot@chromium.org4b32bd52013-03-15 15:06:03 +0000202
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000203void SkPictureRecord::willRestore() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000204 // FIXME: SkDeferredCanvas needs to be refactored to respect
205 // save/restore balancing so that the following test can be
206 // turned on permanently.
207#if 0
208 SkASSERT(fRestoreOffsetStack.count() > 1);
209#endif
210
reed@android.comb4e22d62009-07-09 15:20:25 +0000211 // check for underflow
212 if (fRestoreOffsetStack.count() == 0) {
213 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000214 }
reed@android.comb4e22d62009-07-09 15:20:25 +0000215
mtklein46616af2014-09-30 14:47:10 -0700216 this->recordRestore();
reed@google.comffacd3c2012-08-30 15:31:23 +0000217
reed@android.comb4e22d62009-07-09 15:20:25 +0000218 fRestoreOffsetStack.pop();
reed@android.com32a42492009-07-10 03:33:52 +0000219
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000220 this->INHERITED::willRestore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000221}
222
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000223void SkPictureRecord::recordRestore(bool fillInSkips) {
robertphillipsc019ec42014-08-12 05:35:58 -0700224 fContentInfo.onRestore();
225
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000226 if (fillInSkips) {
227 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
228 }
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000229 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
230 size_t initialOffset = this->addDraw(RESTORE, &size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000231 this->validate(initialOffset, size);
232}
233
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000234void SkPictureRecord::recordTranslate(const SkMatrix& m) {
235 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
236
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000237 // op + dx + dy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000238 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000239 size_t initialOffset = this->addDraw(TRANSLATE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000240 this->addScalar(m.getTranslateX());
241 this->addScalar(m.getTranslateY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000242 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000243}
244
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000245void SkPictureRecord::recordScale(const SkMatrix& m) {
246 SkASSERT(SkMatrix::kScale_Mask == m.getType());
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000247
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000248 // op + sx + sy
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000249 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000250 size_t initialOffset = this->addDraw(SCALE, &size);
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000251 this->addScalar(m.getScaleX());
252 this->addScalar(m.getScaleY());
robertphillips@google.com8b169312013-10-15 17:47:36 +0000253 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000254}
255
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000256void SkPictureRecord::didConcat(const SkMatrix& matrix) {
commit-bot@chromium.orgd9ea09e2014-03-25 17:32:26 +0000257 switch (matrix.getType()) {
258 case SkMatrix::kTranslate_Mask:
259 this->recordTranslate(matrix);
260 break;
261 case SkMatrix::kScale_Mask:
262 this->recordScale(matrix);
263 break;
264 default:
265 this->recordConcat(matrix);
266 break;
267 }
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000268 this->INHERITED::didConcat(matrix);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000269}
270
271void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000272 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000273 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000274 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000275 size_t initialOffset = this->addDraw(CONCAT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000276 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000277 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000278}
279
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000280void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
reed@google.com44699382013-10-31 17:28:30 +0000281 this->validate(fWriter.bytesWritten(), 0);
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000282 // op + matrix
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000283 size_t size = kUInt32Size + matrix.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000284 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000285 this->addMatrix(matrix);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000286 this->validate(initialOffset, size);
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000287 this->INHERITED::didSetMatrix(matrix);
reed@android.com6e073b92009-01-06 15:03:30 +0000288}
289
reed@google.com45482d12011-08-29 19:02:39 +0000290static bool regionOpExpands(SkRegion::Op op) {
291 switch (op) {
292 case SkRegion::kUnion_Op:
293 case SkRegion::kXOR_Op:
294 case SkRegion::kReverseDifference_Op:
295 case SkRegion::kReplace_Op:
296 return true;
297 case SkRegion::kIntersect_Op:
298 case SkRegion::kDifference_Op:
299 return false;
300 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000301 SkDEBUGFAIL("unknown region op");
reed@google.com45482d12011-08-29 19:02:39 +0000302 return false;
303 }
304}
305
robertphillips@google.come37ad352013-03-01 19:44:30 +0000306void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
reed@google.comffacd3c2012-08-30 15:31:23 +0000307 int32_t offset = fRestoreOffsetStack.top();
308 while (offset > 0) {
commit-bot@chromium.org536ac5e2014-02-11 22:38:51 +0000309 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
310 fWriter.overwriteTAt(offset, restoreOffset);
commit-bot@chromium.orgc6d3c442014-01-31 16:22:57 +0000311 offset = peek;
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000312 }
skia.committer@gmail.com11f86922012-08-31 17:14:46 +0000313
reed@google.comffacd3c2012-08-30 15:31:23 +0000314#ifdef SK_DEBUG
reed2ff1fce2014-12-11 07:07:37 -0800315 // offset of 0 has been disabled, so we skip it
316 if (offset > 0) {
317 // assert that the final offset value points to a save verb
318 uint32_t opSize;
319 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
320 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
321 }
reed@google.comffacd3c2012-08-30 15:31:23 +0000322#endif
junov@chromium.orge3dbedb2012-07-09 16:03:55 +0000323}
324
reed@google.comd86e7ab2012-09-27 20:31:31 +0000325void SkPictureRecord::beginRecording() {
326 // we have to call this *after* our constructor, to ensure that it gets
327 // recorded. This is balanced by restoreToCount() call from endRecording,
328 // which in-turn calls our overridden restore(), so those get recorded too.
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000329 fInitialSaveCount = this->save();
reed@google.comd86e7ab2012-09-27 20:31:31 +0000330}
331
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000332void SkPictureRecord::endRecording() {
junov@chromium.org4e6dfa52012-07-16 14:04:59 +0000333 SkASSERT(kNoInitialSave != fInitialSaveCount);
334 this->restoreToCount(fInitialSaveCount);
junov@chromium.orga6c9e0e2012-07-12 17:47:34 +0000335}
336
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000337size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
reed@google.com21b519d2012-10-02 17:42:15 +0000338 if (fRestoreOffsetStack.isEmpty()) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000339 return -1;
reed@google.com21b519d2012-10-02 17:42:15 +0000340 }
341
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000342 // The RestoreOffset field is initially filled with a placeholder
343 // value that points to the offset of the previous RestoreOffset
344 // in the current stack level, thus forming a linked list so that
345 // the restore offsets can be filled in when the corresponding
346 // restore command is recorded.
347 int32_t prevOffset = fRestoreOffsetStack.top();
348
reed@google.com45482d12011-08-29 19:02:39 +0000349 if (regionOpExpands(op)) {
350 // Run back through any previous clip ops, and mark their offset to
351 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
352 // they could hide this clips ability to expand the clip (i.e. go from
353 // empty to non-empty).
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000354 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
fmalita@google.comd0f1a4f2013-08-27 15:50:19 +0000355
356 // Reset the pointer back to the previous clip so that subsequent
357 // restores don't overwrite the offsets we just cleared.
358 prevOffset = 0;
reed@google.com45482d12011-08-29 19:02:39 +0000359 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000360
reed@google.com44699382013-10-31 17:28:30 +0000361 size_t offset = fWriter.bytesWritten();
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000362 this->addInt(prevOffset);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000363 fRestoreOffsetStack.top() = SkToU32(offset);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000364 return offset;
reed@google.com45482d12011-08-29 19:02:39 +0000365}
366
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000367void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000368 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000369 this->INHERITED::onClipRect(rect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000370}
371
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000372size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000373 // id + rect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000374 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000375 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000376 if (!fRestoreOffsetStack.isEmpty()) {
377 // + restore offset
378 size += kUInt32Size;
379 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000380 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000381 this->addRect(rect);
382 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000383 size_t offset = this->recordRestoreOffsetPlaceholder(op);
skia.committer@gmail.com306ab9d2012-12-13 02:01:33 +0000384
robertphillips@google.com8b169312013-10-15 17:47:36 +0000385 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000386 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000387}
388
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000389void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000390 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700391 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000392}
393
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000394size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
robertphillips@google.comf9291502013-02-15 15:13:27 +0000395 // op + rrect + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000396 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
robertphillips@google.com4310c662013-03-01 14:17:58 +0000397 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000398 if (!fRestoreOffsetStack.isEmpty()) {
399 // + restore offset
400 size += kUInt32Size;
401 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000402 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000403 this->addRRect(rrect);
404 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000405 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000406 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000407 return offset;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000408}
409
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000410void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000411 int pathID = this->addPathToHeap(path);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000412 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
reedd9544982014-09-09 18:46:22 -0700413 this->INHERITED::onClipPath(path, op, edgeStyle);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000414}
415
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000416size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000417 // op + path index + clip params
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000418 size_t size = 3 * kUInt32Size;
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000419 // recordRestoreOffsetPlaceholder doesn't always write an offset
420 if (!fRestoreOffsetStack.isEmpty()) {
421 // + restore offset
422 size += kUInt32Size;
423 }
424 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000425 this->addInt(pathID);
426 this->addInt(ClipParams_pack(op, doAA));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000427 size_t offset = recordRestoreOffsetPlaceholder(op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000428 this->validate(initialOffset, size);
429 return offset;
430}
431
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000432void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000433 this->recordClipRegion(region, op);
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000434 this->INHERITED::onClipRegion(region, op);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000435}
436
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000437size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000438 // op + clip params + region
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000439 size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
robertphillips@google.com4310c662013-03-01 14:17:58 +0000440 // recordRestoreOffsetPlaceholder doesn't always write an offset
robertphillips@google.comf9291502013-02-15 15:13:27 +0000441 if (!fRestoreOffsetStack.isEmpty()) {
442 // + restore offset
443 size += kUInt32Size;
444 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000445 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000446 this->addRegion(region);
447 this->addInt(ClipParams_pack(op, false));
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000448 size_t offset = this->recordRestoreOffsetPlaceholder(op);
reed@google.com82065d62011-02-07 15:30:46 +0000449
robertphillips@google.com8b169312013-10-15 17:47:36 +0000450 this->validate(initialOffset, size);
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000451 return offset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000452}
453
reed41af9662015-01-05 07:49:08 -0800454void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000455 // op + paint index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000456 size_t size = 2 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000457 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700458 SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000459 this->addPaint(paint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000460 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000461}
462
reed41af9662015-01-05 07:49:08 -0800463void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
464 const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700465 fContentInfo.onDrawPoints(count, paint);
robertphillips@google.com105a4a52014-02-11 15:10:40 +0000466
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000467 // op + paint index + mode + count + point data
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000468 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000469 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
mtklein8e126562014-10-01 09:29:35 -0700470 SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000471 this->addPaint(paint);
hendrikwafdada22014-08-08 10:44:33 -0700472
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000473 this->addInt(mode);
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000474 this->addInt(SkToInt(count));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000475 fWriter.writeMul4(pts, count * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000476 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000477}
478
reed41af9662015-01-05 07:49:08 -0800479void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000480 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000481 size_t size = 2 * kUInt32Size + sizeof(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000482 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
mtklein8e126562014-10-01 09:29:35 -0700483 SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000484 this->addPaint(paint);
485 this->addRect(oval);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000486 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000487}
488
reed41af9662015-01-05 07:49:08 -0800489void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000490 // op + paint index + rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000491 size_t size = 2 * kUInt32Size + sizeof(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000492 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700493 SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000494 this->addPaint(paint);
495 this->addRect(rect);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000496 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000497}
498
reed41af9662015-01-05 07:49:08 -0800499void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtklein46616af2014-09-30 14:47:10 -0700500 // op + paint index + rrect
501 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
502 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700503 SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700504 this->addPaint(paint);
505 this->addRRect(rrect);
506 this->validate(initialOffset, size);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000507}
508
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000509void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
510 const SkPaint& paint) {
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000511 // op + paint index + rrects
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000512 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
513 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700514 SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000515 this->addPaint(paint);
516 this->addRRect(outer);
517 this->addRRect(inner);
518 this->validate(initialOffset, size);
519}
520
reed41af9662015-01-05 07:49:08 -0800521void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
hendrikwafdada22014-08-08 10:44:33 -0700522 fContentInfo.onDrawPath(path, paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000523
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000524 // op + paint index + path index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000525 size_t size = 3 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000526 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700527 SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000528 this->addPaint(paint);
529 this->addPath(path);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000530 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000531}
532
reed41af9662015-01-05 07:49:08 -0800533void SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
534 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000535 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000536 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000537 size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
mtklein8e126562014-10-01 09:29:35 -0700538 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000539 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000540 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000541 this->addScalar(left);
542 this->addScalar(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000543 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000544}
545
reed41af9662015-01-05 07:49:08 -0800546void SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
547 const SkPaint* paint, DrawBitmapRectFlags flags) {
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000548 // id + paint index + bitmap index + bool for 'src' + flags
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000549 size_t size = 5 * kUInt32Size;
bsalomon49f085d2014-09-05 13:34:00 -0700550 if (src) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000551 size += sizeof(*src); // + rect
552 }
553 size += sizeof(dst); // + rect
554
robertphillips@google.com8b169312013-10-15 17:47:36 +0000555 size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
mtklein8e126562014-10-01 09:29:35 -0700556 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT_TO_RECT, size)
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000557 == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000558 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000559 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000560 this->addRectPtr(src); // may be null
561 this->addRect(dst);
562 this->addInt(flags);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000563 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000564}
565
reed41af9662015-01-05 07:49:08 -0800566void SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
567 const SkRect& dst, const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000568 // op + paint index + bitmap id + center + dst rect
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000569 size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000570 size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
mtklein8e126562014-10-01 09:29:35 -0700571 SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000572 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000573 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000574 this->addIRect(center);
575 this->addRect(dst);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000576 this->validate(initialOffset, size);
reed@google.comf0b5e112011-09-07 11:57:34 +0000577}
578
reed41af9662015-01-05 07:49:08 -0800579void SkPictureRecord::onDrawSprite(const SkBitmap& bitmap, int left, int top,
580 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000581 // op + paint index + bitmap index + left + top
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000582 size_t size = 5 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000583 size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
mtklein8e126562014-10-01 09:29:35 -0700584 SkASSERT(initialOffset+get_paint_offset(DRAW_SPRITE, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000585 this->addPaintPtr(paint);
commit-bot@chromium.orgf6a5afb2014-04-14 15:02:50 +0000586 this->addBitmap(bitmap);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000587 this->addInt(left);
588 this->addInt(top);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000589 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590}
591
reed@google.come0d9ce82014-04-23 04:00:17 +0000592void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
593 const SkPaint& paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000594 // op + paint index + length + 'length' worth of chars + x + y
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000595 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000596
mtklein46616af2014-09-30 14:47:10 -0700597 DrawType op = DRAW_TEXT;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000598 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700599 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700600 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000601 this->addText(text, byteLength);
602 this->addScalar(x);
603 this->addScalar(y);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000604 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000605}
606
reed@google.come0d9ce82014-04-23 04:00:17 +0000607void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
608 const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000609 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000610
mtklein46616af2014-09-30 14:47:10 -0700611 // op + paint index + length + 'length' worth of data + num points + x&y point data
612 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
reed@google.com82065d62011-02-07 15:30:46 +0000613
mtklein46616af2014-09-30 14:47:10 -0700614 DrawType op = DRAW_POS_TEXT;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000615
robertphillips@google.com8b169312013-10-15 17:47:36 +0000616 size_t initialOffset = this->addDraw(op, &size);
mtklein8e126562014-10-01 09:29:35 -0700617 SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
mtklein46616af2014-09-30 14:47:10 -0700618 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000619 this->addText(text, byteLength);
620 this->addInt(points);
mtklein46616af2014-09-30 14:47:10 -0700621 fWriter.writeMul4(pos, points * sizeof(SkPoint));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000622 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000623}
624
reed@google.come0d9ce82014-04-23 04:00:17 +0000625void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
626 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000627 int points = paint.countText(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000628
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000629 // op + paint index + length + 'length' worth of data + num points
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000630 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000631 // + y + the actual points
632 size += 1 * kUInt32Size + points * sizeof(SkScalar);
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000633
mtklein46616af2014-09-30 14:47:10 -0700634 size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
635 this->addPaint(paint);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000636 this->addText(text, byteLength);
637 this->addInt(points);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000638 this->addScalar(constY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000639 fWriter.writeMul4(xpos, points * sizeof(SkScalar));
robertphillips@google.com8b169312013-10-15 17:47:36 +0000640 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000641}
642
reed@google.come0d9ce82014-04-23 04:00:17 +0000643void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
644 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000645 // op + paint index + length + 'length' worth of data + path index + matrix
646 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000647 size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000648 size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
mtklein8e126562014-10-01 09:29:35 -0700649 SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000650 this->addPaint(paint);
651 this->addText(text, byteLength);
652 this->addPath(path);
653 this->addMatrix(m);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000654 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000655}
656
fmalitab7425172014-08-26 07:56:44 -0700657void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
658 const SkPaint& paint) {
659
660 // op + paint index + blob index + x/y
661 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
662 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
mtklein8e126562014-10-01 09:29:35 -0700663 SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
fmalitab7425172014-08-26 07:56:44 -0700664
665 this->addPaint(paint);
666 this->addTextBlob(blob);
667 this->addScalar(x);
668 this->addScalar(y);
669
670 this->validate(initialOffset, size);
671}
672
reedd5fa1a42014-08-09 11:08:05 -0700673void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
674 const SkPaint* paint) {
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000675 // op + picture index
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000676 size_t size = 2 * kUInt32Size;
reedd5fa1a42014-08-09 11:08:05 -0700677 size_t initialOffset;
678
679 if (NULL == matrix && NULL == paint) {
680 initialOffset = this->addDraw(DRAW_PICTURE, &size);
681 this->addPicture(picture);
682 } else {
683 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
684 size += m.writeToMemory(NULL) + kUInt32Size; // matrix + paint
685 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
mtklein8e126562014-10-01 09:29:35 -0700686 SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
fmalita9f49cfd2014-08-12 12:24:17 -0700687 == fWriter.bytesWritten());
reedd5fa1a42014-08-09 11:08:05 -0700688 this->addPaintPtr(paint);
fmalita9f49cfd2014-08-12 12:24:17 -0700689 this->addMatrix(m);
690 this->addPicture(picture);
reedd5fa1a42014-08-09 11:08:05 -0700691 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000692 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000693}
694
reed41af9662015-01-05 07:49:08 -0800695void SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
696 const SkPoint vertices[], const SkPoint texs[],
697 const SkColor colors[], SkXfermode* xfer,
698 const uint16_t indices[], int indexCount,
699 const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000700 uint32_t flags = 0;
701 if (texs) {
702 flags |= DRAW_VERTICES_HAS_TEXS;
703 }
704 if (colors) {
705 flags |= DRAW_VERTICES_HAS_COLORS;
706 }
707 if (indexCount > 0) {
708 flags |= DRAW_VERTICES_HAS_INDICES;
709 }
bsalomon49f085d2014-09-05 13:34:00 -0700710 if (xfer) {
reed@google.com85e143c2013-12-30 15:51:25 +0000711 SkXfermode::Mode mode;
712 if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
713 flags |= DRAW_VERTICES_HAS_XFER;
714 }
715 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000716
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000717 // op + paint index + flags + vmode + vCount + vertices
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000718 size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000719 if (flags & DRAW_VERTICES_HAS_TEXS) {
720 size += vertexCount * sizeof(SkPoint); // + uvs
721 }
722 if (flags & DRAW_VERTICES_HAS_COLORS) {
723 size += vertexCount * sizeof(SkColor); // + vert colors
724 }
725 if (flags & DRAW_VERTICES_HAS_INDICES) {
726 // + num indices + indices
727 size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
728 }
reed@google.com85e143c2013-12-30 15:51:25 +0000729 if (flags & DRAW_VERTICES_HAS_XFER) {
730 size += kUInt32Size; // mode enum
731 }
robertphillips@google.com2ca1aaa2013-02-15 13:47:37 +0000732
robertphillips@google.com8b169312013-10-15 17:47:36 +0000733 size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
mtklein8e126562014-10-01 09:29:35 -0700734 SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000735 this->addPaint(paint);
736 this->addInt(flags);
737 this->addInt(vmode);
738 this->addInt(vertexCount);
739 this->addPoints(vertices, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000740 if (flags & DRAW_VERTICES_HAS_TEXS) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000741 this->addPoints(texs, vertexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000742 }
743 if (flags & DRAW_VERTICES_HAS_COLORS) {
744 fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
745 }
746 if (flags & DRAW_VERTICES_HAS_INDICES) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000747 this->addInt(indexCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000748 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
749 }
reed@google.com85e143c2013-12-30 15:51:25 +0000750 if (flags & DRAW_VERTICES_HAS_XFER) {
751 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
752 (void)xfer->asMode(&mode);
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000753 this->addInt(mode);
reed@google.com85e143c2013-12-30 15:51:25 +0000754 }
robertphillips@google.com8b169312013-10-15 17:47:36 +0000755 this->validate(initialOffset, size);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000756}
757
dandovb3c9d1c2014-08-12 08:34:29 -0700758void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
759 const SkPoint texCoords[4], SkXfermode* xmode,
760 const SkPaint& paint) {
761 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
762 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
763 uint32_t flag = 0;
bsalomon49f085d2014-09-05 13:34:00 -0700764 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700765 flag |= DRAW_VERTICES_HAS_COLORS;
766 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
767 }
bsalomon49f085d2014-09-05 13:34:00 -0700768 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700769 flag |= DRAW_VERTICES_HAS_TEXS;
770 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
771 }
bsalomon49f085d2014-09-05 13:34:00 -0700772 if (xmode) {
dandovb3c9d1c2014-08-12 08:34:29 -0700773 SkXfermode::Mode mode;
774 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
775 flag |= DRAW_VERTICES_HAS_XFER;
776 size += kUInt32Size;
777 }
778 }
mtklein46616af2014-09-30 14:47:10 -0700779
dandov963137b2014-08-07 07:49:53 -0700780 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
mtklein8e126562014-10-01 09:29:35 -0700781 SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
dandov963137b2014-08-07 07:49:53 -0700782 this->addPaint(paint);
dandovb3c9d1c2014-08-12 08:34:29 -0700783 this->addPatch(cubics);
784 this->addInt(flag);
mtklein46616af2014-09-30 14:47:10 -0700785
dandovb3c9d1c2014-08-12 08:34:29 -0700786 // write optional parameters
bsalomon49f085d2014-09-05 13:34:00 -0700787 if (colors) {
dandovb3c9d1c2014-08-12 08:34:29 -0700788 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
789 }
bsalomon49f085d2014-09-05 13:34:00 -0700790 if (texCoords) {
dandovb3c9d1c2014-08-12 08:34:29 -0700791 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
792 }
793 if (flag & DRAW_VERTICES_HAS_XFER) {
794 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
795 xmode->asMode(&mode);
796 this->addInt(mode);
797 }
dandov963137b2014-08-07 07:49:53 -0700798 this->validate(initialOffset, size);
799}
800
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000801void SkPictureRecord::beginCommentGroup(const char* description) {
802 // op/size + length of string + \0 terminated chars
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000803 size_t length = strlen(description);
804 size_t size = 2 * kUInt32Size + SkAlign4(length + 1);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000805 size_t initialOffset = this->addDraw(BEGIN_COMMENT_GROUP, &size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000806 fWriter.writeString(description, length);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000807 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000808}
809
810void SkPictureRecord::addComment(const char* kywd, const char* value) {
811 // op/size + 2x length of string + 2x \0 terminated chars
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000812 size_t kywdLen = strlen(kywd);
813 size_t valueLen = strlen(value);
814 size_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000815 size_t initialOffset = this->addDraw(COMMENT, &size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000816 fWriter.writeString(kywd, kywdLen);
817 fWriter.writeString(value, valueLen);
robertphillips@google.com8b169312013-10-15 17:47:36 +0000818 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000819}
820
821void SkPictureRecord::endCommentGroup() {
822 // op/size
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000823 size_t size = 1 * kUInt32Size;
robertphillips@google.com8b169312013-10-15 17:47:36 +0000824 size_t initialOffset = this->addDraw(END_COMMENT_GROUP, &size);
825 this->validate(initialOffset, size);
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000826}
827
reed@android.com8a1c16f2008-12-17 15:59:43 +0000828///////////////////////////////////////////////////////////////////////////////
reed@google.com82065d62011-02-07 15:30:46 +0000829
reed4a8126e2014-09-22 07:29:03 -0700830SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000831 return NULL;
reed@google.com76f10a32014-02-05 15:32:21 +0000832}
833
mtkleine0694002014-11-12 12:49:47 -0800834// If we already have a stored, can we reuse it instead of also storing b?
835static bool equivalent(const SkBitmap& a, const SkBitmap& b) {
836 if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
837 // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
838 // but it sure makes things easier to reason about below.
839 return false;
840 }
841 if (a.pixelRef() == b.pixelRef()) {
842 return true; // Same shape and same pixels -> same bitmap.
843 }
844
845 // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
846 if (!a.pixelRef() || !b.pixelRef()) {
847 return false;
848 }
849
850 // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
851 SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
852 encB(b.pixelRef()->refEncodedData());
853 if (encA && encB) {
854 return encA->equals(encB);
855 } else if (encA || encB) {
856 return false; // One has encoded data but the other does not.
857 }
858
859 // As a last resort, we have to look at the pixels. This will read back textures.
860 SkAutoLockPixels al(a), bl(b);
861 const char* ap = (const char*)a.getPixels();
862 const char* bp = (const char*)b.getPixels();
863 if (ap && bp) {
864 // We check row by row; row bytes might differ.
865 SkASSERT(a.info() == b.info()); // We checked this above.
866 SkASSERT(a.info().bytesPerPixel() > 0); // If we have pixelRefs, this better be true.
867 const SkImageInfo info = a.info();
868 const size_t bytesToCompare = info.width() * info.bytesPerPixel();
869 for (int row = 0; row < info.height(); row++) {
870 if (0 != memcmp(ap, bp, bytesToCompare)) {
871 return false;
872 }
873 ap += a.rowBytes();
874 bp += b.rowBytes();
875 }
876 return true;
877 }
878 return false; // Couldn't get pixels for both bitmaps.
879}
880
881void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
882 // First see if we already have this bitmap. This deduplication should really
883 // only be important for our tests, where bitmaps tend not to be tagged immutable.
884 // In Chrome (and hopefully Android?) they're typically immutable.
885 for (int i = 0; i < fBitmaps.count(); i++) {
886 if (equivalent(fBitmaps[i], bitmap)) {
887 this->addInt(i); // Unlike the rest, bitmap indices are 0-based.
888 return;
889 }
890 }
891 // Don't have it. We'll add it to our list, making sure it's tagged as immutable.
mtklein71a23632014-11-12 10:24:55 -0800892 if (bitmap.isImmutable()) {
mtkleine0694002014-11-12 12:49:47 -0800893 // Shallow copies of bitmaps are cheap, so immutable == fast.
mtklein71a23632014-11-12 10:24:55 -0800894 fBitmaps.push_back(bitmap);
895 } else {
mtkleine0694002014-11-12 12:49:47 -0800896 // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
mtklein71a23632014-11-12 10:24:55 -0800897 SkBitmap copy;
898 bitmap.copyTo(&copy);
899 copy.setImmutable();
900 fBitmaps.push_back(copy);
901 }
mtkleine0694002014-11-12 12:49:47 -0800902 this->addInt(fBitmaps.count()-1); // Remember, 0-based.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000903}
904
905void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000906 fWriter.writeMatrix(matrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000907}
908
mtklein46616af2014-09-30 14:47:10 -0700909void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
hendrikwafdada22014-08-08 10:44:33 -0700910 fContentInfo.onAddPaintPtr(paint);
commit-bot@chromium.orge2cb12a2014-04-24 21:53:13 +0000911
mtklein46616af2014-09-30 14:47:10 -0700912 if (paint) {
mtkleina74ce852014-11-12 09:19:02 -0800913 fPaints.push_back(*paint);
914 this->addInt(fPaints.count());
mtklein46616af2014-09-30 14:47:10 -0700915 } else {
916 this->addInt(0);
917 }
commit-bot@chromium.orgcf7be952013-08-22 17:19:52 +0000918}
919
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000920int SkPictureRecord::addPathToHeap(const SkPath& path) {
mtklein71a23632014-11-12 10:24:55 -0800921 fPaths.push_back(path);
922 return fPaths.count();
robertphillips@google.com5a63f242014-02-04 20:07:50 +0000923}
924
925void SkPictureRecord::addPath(const SkPath& path) {
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000926 this->addInt(this->addPathToHeap(path));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000927}
928
dandovb3c9d1c2014-08-12 08:34:29 -0700929void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
930 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
dandov963137b2014-08-07 07:49:53 -0700931}
932
robertphillips9b14f262014-06-04 05:40:44 -0700933void SkPictureRecord::addPicture(const SkPicture* picture) {
934 int index = fPictureRefs.find(picture);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000935 if (index < 0) { // not found
936 index = fPictureRefs.count();
robertphillips9b14f262014-06-04 05:40:44 -0700937 *fPictureRefs.append() = picture;
938 picture->ref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000939 }
940 // follow the convention of recording a 1-based index
robertphillips@google.comcb6adec2014-02-05 14:05:38 +0000941 this->addInt(index + 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000942}
943
944void SkPictureRecord::addPoint(const SkPoint& point) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000945 fWriter.writePoint(point);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000946}
reed@google.com82065d62011-02-07 15:30:46 +0000947
reed@android.com8a1c16f2008-12-17 15:59:43 +0000948void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
949 fWriter.writeMul4(pts, count * sizeof(SkPoint));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000950}
951
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000952void SkPictureRecord::addNoOp() {
953 size_t size = kUInt32Size; // op
954 this->addDraw(NOOP, &size);
955}
956
reed@android.com8a1c16f2008-12-17 15:59:43 +0000957void SkPictureRecord::addRect(const SkRect& rect) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000958 fWriter.writeRect(rect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000959}
960
961void SkPictureRecord::addRectPtr(const SkRect* rect) {
962 if (fWriter.writeBool(rect != NULL)) {
963 fWriter.writeRect(*rect);
964 }
965}
966
reed@google.comf0b5e112011-09-07 11:57:34 +0000967void SkPictureRecord::addIRect(const SkIRect& rect) {
968 fWriter.write(&rect, sizeof(rect));
969}
970
reed@android.com8a1c16f2008-12-17 15:59:43 +0000971void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
972 if (fWriter.writeBool(rect != NULL)) {
973 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
974 }
975}
976
reed@google.com4ed0fb72012-12-12 20:48:18 +0000977void SkPictureRecord::addRRect(const SkRRect& rrect) {
978 fWriter.writeRRect(rrect);
979}
980
reed@android.com8a1c16f2008-12-17 15:59:43 +0000981void SkPictureRecord::addRegion(const SkRegion& region) {
commit-bot@chromium.orgfed2ab62014-01-23 15:16:05 +0000982 fWriter.writeRegion(region);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000983}
984
985void SkPictureRecord::addText(const void* text, size_t byteLength) {
hendrikwafdada22014-08-08 10:44:33 -0700986 fContentInfo.onDrawText();
commit-bot@chromium.orgdcecb162014-04-22 17:54:29 +0000987 addInt(SkToInt(byteLength));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000988 fWriter.writePad(text, byteLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000989}
990
fmalitab7425172014-08-26 07:56:44 -0700991void SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
jbromandd1e9f72014-09-08 13:24:33 -0700992 int index = fTextBlobRefs.count();
993 *fTextBlobRefs.append() = blob;
994 blob->ref();
fmalitab7425172014-08-26 07:56:44 -0700995 // follow the convention of recording a 1-based index
996 this->addInt(index + 1);
997}
998
reed@android.com8a1c16f2008-12-17 15:59:43 +0000999///////////////////////////////////////////////////////////////////////////////
1000