1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPictureRecord.h"
94123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth#include "SkDrawShadowRec.h"
10a85d4d0814818e4ddabb9237da209d61d6cd5854reed#include "SkImage_Base.h"
11b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
12b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPixelRef.h"
13b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkRRect.h"
1471c3c760a83123ee0b3127b8c65c6394ce541c50reed#include "SkRSXform.h"
15b7425173f96e93b090787e2386ba5f022b6c2869fmalita#include "SkTextBlob.h"
16b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkTSearch.h"
17ebfce6d9b42198e04288a15953f40c395a7b6139Mike Reed#include "SkClipOpPriv.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define HEAP_BLOCK_SIZE 4096
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
214e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.orgenum {
22d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // just need a value that save or getSaveCount would never return
234e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    kNoInitialSave = -1,
244e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org};
254e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org
262ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
272ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.comstatic int const kUInt32Size = 4;
282ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
290bdbea75ff1a6f3c313c18cab0139728967cb93erobertphillipsSkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
3019fafef9784fe7c644540ffd0ee9f6da1914a038commit-bot@chromium.org    : INHERITED(dimensions.width(), dimensions.height())
3171a236370792416b367a7d2d6b8e471b06b331cdmtklein    , fRecordFlags(flags)
3271a236370792416b367a7d2d6b8e471b06b331cdmtklein    , fInitialSaveCount(kNoInitialSave) {
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkPictureRecord::~SkPictureRecord() {
365351aad9bc5b2e3101472248967e3dc1f84d24eerobertphillips    fImageRefs.unrefAll();
3721830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com    fPictureRefs.unrefAll();
3895416f477d2ca264f2fb065455e95778a2289a1dmsarett    fDrawableRefs.unrefAll();
39b7425173f96e93b090787e2386ba5f022b6c2869fmalita    fTextBlobRefs.unrefAll();
40e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    fVerticesRefs.unrefAll();
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
455f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitavoid SkPictureRecord::willSave() {
46ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // record the offset to us, making it non-positive to distinguish a save
47ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // from a clip entry.
484469938e92d779dff05e745559e67907bbf21e78reed@google.com    fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
495f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    this->recordSave();
50e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
515f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    this->INHERITED::willSave();
525a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
5311f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
545f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitavoid SkPictureRecord::recordSave() {
55c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onSave();
56c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
575f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    // op only
58512f3e3b2592097a39bde9331829b38d16c0f85dreed    size_t size = sizeof(kUInt32Size);
598b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SAVE, &size);
6082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
618b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
644960eeec4a1f2a772654883d7f3615d47bcd5dc3reedSkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
65ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // record the offset to us, making it non-positive to distinguish a save
66ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // from a clip entry.
674469938e92d779dff05e745559e67907bbf21e78reed@google.com    fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
684960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    this->recordSaveLayer(rec);
6911f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
704960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    (void)this->INHERITED::getSaveLayerStrategy(rec);
71e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    /*  No need for a (potentially very big) layer which we don't actually need
725a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        at this time (and may not be able to afford since during record our
735a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        clip starts out the size of the picture, which is often much larger
745a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        than the size of the actual device we'll use during playback).
755a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com     */
76e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    return kNoLayer_SaveLayerStrategy;
775a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
785a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
794960eeec4a1f2a772654883d7f3615d47bcd5dc3reedvoid SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
80c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onSaveLayer();
81c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
82bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    // op + flatflags
83dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
84bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    uint32_t flatFlags = 0;
85bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed
864960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (rec.fBounds) {
87bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_BOUNDS;
88bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(*rec.fBounds);
89bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
90bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (rec.fPaint) {
91bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_PAINT;
92bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(uint32_t); // index
93bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
94bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (rec.fBackdrop) {
95bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_BACKDROP;
96bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(uint32_t); // (paint) index
97bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
98bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (rec.fSaveLayerFlags) {
99bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_FLAGS;
100bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(uint32_t);
1012ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
10253f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    if (rec.fClipMask) {
10353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        flatFlags |= SAVELAYERREC_HAS_CLIPMASK;
10453f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        size += sizeof(uint32_t); // clip image index
10553f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    }
10653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    if (rec.fClipMatrix) {
10753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        flatFlags |= SAVELAYERREC_HAS_CLIPMATRIX;
10853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        size += rec.fClipMatrix->writeToMemory(nullptr);
10953f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    }
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
111bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
112bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    this->addInt(flatFlags);
113bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
114bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addRect(*rec.fBounds);
115bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
116bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_PAINT) {
117bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addPaintPtr(rec.fPaint);
118bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
119bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
120bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        // overkill, but we didn't already track single flattenables, so using a paint for that
121bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        SkPaint paint;
1225e25717ab6313b011ec54eac0109c414aa8ffc17Mike Reed        paint.setImageFilter(sk_ref_sp(const_cast<SkImageFilter*>(rec.fBackdrop)));
123bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addPaint(paint);
124bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
125bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
126bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addInt(rec.fSaveLayerFlags);
127bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
12853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
129b34ab04884f6219b93c1f143c83a1fc60fded40cMike Klein        this->addImage(rec.fClipMask);
13053f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    }
13153f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
13253f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        this->addMatrix(*rec.fClipMatrix);
13353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    }
1348b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
137210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org#ifdef SK_DEBUG
138210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org/*
1392ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com * Read the op code from 'offset' in 'writer' and extract the size too.
1402ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com */
141dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgstatic DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
142536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    uint32_t peek = writer->readTAt<uint32_t>(offset);
1432ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
1442ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    uint32_t op;
145c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org    UNPACK_8_24(peek, op, *size);
1462ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    if (MASK_24 == *size) {
1472ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        // size required its own slot right after the op code
148536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
1492ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
1502ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    return (DrawType) op;
151ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com}
15246616af01b412ea984a516fda1ed8ec08e689f29mtklein#endif//SK_DEBUG
1534b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org
154e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgvoid SkPictureRecord::willRestore() {
1554e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org#if 0
1564e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    SkASSERT(fRestoreOffsetStack.count() > 1);
1574e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org#endif
1584e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org
159b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    // check for underflow
160b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    if (fRestoreOffsetStack.count() == 0) {
161b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com        return;
162b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    }
163b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com
16446616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->recordRestore();
165ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com
166b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    fRestoreOffsetStack.pop();
16732a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com
168e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    this->INHERITED::willRestore();
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
171105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.comvoid SkPictureRecord::recordRestore(bool fillInSkips) {
172c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onRestore();
173c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
174105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    if (fillInSkips) {
175105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
176105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
177dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
178dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t initialOffset = this->addDraw(RESTORE, &size);
1795a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    this->validate(initialOffset, size);
1805a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
1815a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
182d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.orgvoid SkPictureRecord::recordTranslate(const SkMatrix& m) {
183d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
184d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
1852ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + dx + dy
186dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
1878b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(TRANSLATE, &size);
188d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getTranslateX());
189d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getTranslateY());
1908b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
193d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.orgvoid SkPictureRecord::recordScale(const SkMatrix& m) {
194d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkASSERT(SkMatrix::kScale_Mask == m.getType());
195105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
1962ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + sx + sy
197dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
1988b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SCALE, &size);
199d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getScaleX());
200d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getScaleY());
2018b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20444c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkPictureRecord::didConcat(const SkMatrix& matrix) {
205d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    switch (matrix.getType()) {
206d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        case SkMatrix::kTranslate_Mask:
207d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordTranslate(matrix);
208d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
209d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        case SkMatrix::kScale_Mask:
210d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordScale(matrix);
211d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
212d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        default:
213d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordConcat(matrix);
214d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
215d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
21644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->INHERITED::didConcat(matrix);
2175a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
2185a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
2195a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comvoid SkPictureRecord::recordConcat(const SkMatrix& matrix) {
2204469938e92d779dff05e745559e67907bbf21e78reed@google.com    this->validate(fWriter.bytesWritten(), 0);
221fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + matrix
22296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
2238b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CONCAT, &size);
224cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(matrix);
2258b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
2294469938e92d779dff05e745559e67907bbf21e78reed@google.com    this->validate(fWriter.bytesWritten(), 0);
230fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + matrix
23196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
2328b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SET_MATRIX, &size);
233cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(matrix);
2348b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
23544c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->INHERITED::didSetMatrix(matrix);
2366e073b9e2b70d6bbf8a06050fff1364827204f08reed@android.com}
2376e073b9e2b70d6bbf8a06050fff1364827204f08reed@android.com
238c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedstatic bool clipOpExpands(SkClipOp op) {
23945482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    switch (op) {
240c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kUnion_SkClipOp:
241c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kXOR_SkClipOp:
242c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kReverseDifference_SkClipOp:
243c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kReplace_SkClipOp:
24445482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return true;
245c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kIntersect_SkClipOp:
246c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kDifference_SkClipOp:
24745482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return false;
24845482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        default:
249c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed            SkDEBUGFAIL("unknown clipop");
25045482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return false;
25145482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    }
25245482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com}
25345482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com
254e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.comvoid SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
255ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    int32_t offset = fRestoreOffsetStack.top();
256ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    while (offset > 0) {
257536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        uint32_t peek = fWriter.readTAt<uint32_t>(offset);
258536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        fWriter.overwriteTAt(offset, restoreOffset);
259c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org        offset = peek;
260e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org    }
26111f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
262ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com#ifdef SK_DEBUG
2632ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    // offset of 0 has been disabled, so we skip it
2642ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (offset > 0) {
2652ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // assert that the final offset value points to a save verb
2662ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        uint32_t opSize;
2672ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
2684960eeec4a1f2a772654883d7f3615d47bcd5dc3reed        SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
269bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
270bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
2712ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
272ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com#endif
273e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org}
274e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org
275d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.comvoid SkPictureRecord::beginRecording() {
276d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // we have to call this *after* our constructor, to ensure that it gets
277d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // recorded. This is balanced by restoreToCount() call from endRecording,
278d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // which in-turn calls our overridden restore(), so those get recorded too.
279091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org    fInitialSaveCount = this->save();
280d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com}
281d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com
282a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.orgvoid SkPictureRecord::endRecording() {
2834e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    SkASSERT(kNoInitialSave != fInitialSaveCount);
2844e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    this->restoreToCount(fInitialSaveCount);
285a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.org}
286a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.org
287c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedsize_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkClipOp op) {
28821b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com    if (fRestoreOffsetStack.isEmpty()) {
2895a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        return -1;
29021b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com    }
29121b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com
292d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // The RestoreOffset field is initially filled with a placeholder
293d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // value that points to the offset of the previous RestoreOffset
294d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // in the current stack level, thus forming a linked list so that
295d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // the restore offsets can be filled in when the corresponding
296d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // restore command is recorded.
297d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    int32_t prevOffset = fRestoreOffsetStack.top();
298d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com
29973603f3c52ffd89fe9d035be827b566a0e7d3b79reed    if (clipOpExpands(op)) {
30045482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // Run back through any previous clip ops, and mark their offset to
30145482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // be 0, disabling their ability to trigger a jump-to-restore, otherwise
30245482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // they could hide this clips ability to expand the clip (i.e. go from
30345482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // empty to non-empty).
304cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com        this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
305d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com
306d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        // Reset the pointer back to the previous clip so that subsequent
307d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        // restores don't overwrite the offsets we just cleared.
308d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        prevOffset = 0;
30945482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    }
31074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3114469938e92d779dff05e745559e67907bbf21e78reed@google.com    size_t offset = fWriter.bytesWritten();
312cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(prevOffset);
313dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    fRestoreOffsetStack.top() = SkToU32(offset);
3145a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
31545482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com}
31645482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com
317c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkPictureRecord::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
3188f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
3198f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->INHERITED::onClipRect(rect, op, edgeStyle);
3205a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3215a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
322c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedsize_t SkPictureRecord::recordClipRect(const SkRect& rect, SkClipOp op, bool doAA) {
323f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // id + rect + clip params
324dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
3254310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
326f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
327f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
328f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
329f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3308b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_RECT, &size);
331cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(rect);
332cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
333dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = this->recordRestoreOffsetPlaceholder(op);
334306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
3358b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3365a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
33768d61ed83ec7b6e98e9623c2f5c9e7b1a32d25bbreed@google.com}
33868d61ed83ec7b6e98e9623c2f5c9e7b1a32d25bbreed@google.com
339c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkPictureRecord::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
3408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
341d954498c01ccf0417feacf89e45d0c62a06a813breed    this->INHERITED::onClipRRect(rrect, op, edgeStyle);
3425a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3435a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
344c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedsize_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
345f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // op + rrect + clip params
346dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
3474310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
348f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
349f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
350f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
351f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3528b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
353cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRRect(rrect);
354cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
355dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = recordRestoreOffsetPlaceholder(op);
3568b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3575a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
3584ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
3594ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
360c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkPictureRecord::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
3615a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    int pathID = this->addPathToHeap(path);
3628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
363d954498c01ccf0417feacf89e45d0c62a06a813breed    this->INHERITED::onClipPath(path, op, edgeStyle);
3645a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3655a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
366c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedsize_t SkPictureRecord::recordClipPath(int pathID, SkClipOp op, bool doAA) {
367f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // op + path index + clip params
368dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size;
3694310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
370f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
371f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
372f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
373f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3748b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_PATH, &size);
375cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(pathID);
376cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
377dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = recordRestoreOffsetPlaceholder(op);
3788b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3795a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
382c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkPictureRecord::onClipRegion(const SkRegion& region, SkClipOp op) {
3835a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    this->recordClipRegion(region, op);
3848f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->INHERITED::onClipRegion(region, op);
3855a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3865a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
387c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedsize_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkClipOp op) {
388fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + clip params + region
38996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
3904310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
391f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
392f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
393f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
394f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3958b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_REGION, &size);
396cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRegion(region);
397cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, false));
398dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = this->recordRestoreOffsetPlaceholder(op);
39982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4008b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4015a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
40441af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPaint(const SkPaint& paint) {
4052ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index
406dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
4078b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
408cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
4098b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
41241af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
41341af966ab338e95eee81ab618ab28195075338f7reed                                   const SkPaint& paint) {
414afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawPoints(count, paint);
415105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
4162ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + mode + count + point data
417dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
4188b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
419cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
420afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw
421cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(mode);
422dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    this->addInt(SkToInt(count));
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(pts, count * sizeof(SkPoint));
4248b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42741af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
4282ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + rect
429dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + sizeof(oval);
4308b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
431cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
432cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(oval);
4338b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4344ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
4354ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
436ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomonvoid SkPictureRecord::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
437ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                                bool useCenter, const SkPaint& paint) {
438ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    // op + paint index + rect + start + sweep + bool (as int)
439ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    size_t size = 2 * kUInt32Size + sizeof(oval) + sizeof(startAngle) + sizeof(sweepAngle) +
440ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                  sizeof(int);
441ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    size_t initialOffset = this->addDraw(DRAW_ARC, &size);
442ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->addPaint(paint);
443ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->addRect(oval);
444ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->addScalar(startAngle);
445ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->addScalar(sweepAngle);
446ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->addInt(useCenter);
447ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->validate(initialOffset, size);
448ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon}
449ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
45041af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
4512ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + rect
452dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + sizeof(rect);
4538b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_RECT, &size);
454cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
455cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(rect);
4568b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45944df651ebefc284acc2f66425dff3ea0b0e14b36msarettvoid SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
46044df651ebefc284acc2f66425dff3ea0b0e14b36msarett    // op + paint index + region
46144df651ebefc284acc2f66425dff3ea0b0e14b36msarett    size_t regionBytes = region.writeToMemory(nullptr);
46244df651ebefc284acc2f66425dff3ea0b0e14b36msarett    size_t size = 2 * kUInt32Size + regionBytes;
46344df651ebefc284acc2f66425dff3ea0b0e14b36msarett    size_t initialOffset = this->addDraw(DRAW_REGION, &size);
46444df651ebefc284acc2f66425dff3ea0b0e14b36msarett    this->addPaint(paint);
46544df651ebefc284acc2f66425dff3ea0b0e14b36msarett    fWriter.writeRegion(region);
46644df651ebefc284acc2f66425dff3ea0b0e14b36msarett    this->validate(initialOffset, size);
46744df651ebefc284acc2f66425dff3ea0b0e14b36msarett}
46844df651ebefc284acc2f66425dff3ea0b0e14b36msarett
46941af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
47046616af01b412ea984a516fda1ed8ec08e689f29mtklein    // op + paint index + rrect
47146616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
47246616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
47346616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
47446616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addRRect(rrect);
47546616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->validate(initialOffset, size);
4764ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
4774ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
478ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
479ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                                   const SkPaint& paint) {
480ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // op + paint index + rrects
481dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
482dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
483ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addPaint(paint);
484ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addRRect(outer);
485ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addRRect(inner);
486ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->validate(initialOffset, size);
487ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
488ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
48941af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
490afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawPath(path, paint);
491e2cb12a82ad924f7b134a9459b190213485c6a50commit-bot@chromium.org
4922ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + path index
493dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size;
4948b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_PATH, &size);
495cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
496cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPath(path);
4978b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
500a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
501a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                  const SkPaint* paint) {
502871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    // op + paint_index + image_index + x + y
503871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
504871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
505871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addPaintPtr(paint);
506871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addImage(image);
507871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addScalar(x);
508871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addScalar(y);
509871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->validate(initialOffset, size);
510a85d4d0814818e4ddabb9237da209d61d6cd5854reed}
511a85d4d0814818e4ddabb9237da209d61d6cd5854reed
512a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
513562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                      const SkPaint* paint, SrcRectConstraint constraint) {
514a5517e2b190a8083b38964972b031c13e99f1012reed    // id + paint_index + image_index + bool_for_src + constraint
515a5517e2b190a8083b38964972b031c13e99f1012reed    size_t size = 5 * kUInt32Size;
516871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    if (src) {
517871872f3f247f6b699617f6d9ef50ef5da6fbe74reed        size += sizeof(*src);   // + rect
518a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
519871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size += sizeof(dst);        // + rect
520c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein
521871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
522871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addPaintPtr(paint);
523871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addImage(image);
524871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addRectPtr(src);  // may be null
525871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addRect(dst);
526a5517e2b190a8083b38964972b031c13e99f1012reed    this->addInt(constraint);
527871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->validate(initialOffset, size);
528a85d4d0814818e4ddabb9237da209d61d6cd5854reed}
529a85d4d0814818e4ddabb9237da209d61d6cd5854reed
5304c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
5314c21dc5ddf3b482293ed34eead876d8d61a662c3reed                                      const SkPaint* paint) {
5324c21dc5ddf3b482293ed34eead876d8d61a662c3reed    // id + paint_index + image_index + center + dst
5334c21dc5ddf3b482293ed34eead876d8d61a662c3reed    size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
534c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein
5354c21dc5ddf3b482293ed34eead876d8d61a662c3reed    size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
5364c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addPaintPtr(paint);
5374c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addImage(img);
5384c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addIRect(center);
5394c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addRect(dst);
5404c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->validate(initialOffset, size);
5414c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
5424c21dc5ddf3b482293ed34eead876d8d61a662c3reed
543168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
544168820625c35a8c19f66c661efcbce7a5e334837msarett                                         const SkRect& dst, const SkPaint* paint) {
545168820625c35a8c19f66c661efcbce7a5e334837msarett    // xCount + xDivs + yCount+ yDivs
5460764efe6a9ae65ad83992f614f57ca9db5b1f191msarett    int flagCount = (nullptr == lattice.fFlags) ? 0 : (lattice.fXCount + 1) * (lattice.fYCount + 1);
5470764efe6a9ae65ad83992f614f57ca9db5b1f191msarett    size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size +
54871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett                         SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)) + sizeof(SkIRect);
549168820625c35a8c19f66c661efcbce7a5e334837msarett
550168820625c35a8c19f66c661efcbce7a5e334837msarett    // op + paint index + image index + lattice + dst rect
551168820625c35a8c19f66c661efcbce7a5e334837msarett    size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
552168820625c35a8c19f66c661efcbce7a5e334837msarett    size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
553168820625c35a8c19f66c661efcbce7a5e334837msarett    this->addPaintPtr(paint);
554168820625c35a8c19f66c661efcbce7a5e334837msarett    this->addImage(image);
555168820625c35a8c19f66c661efcbce7a5e334837msarett    this->addInt(lattice.fXCount);
556168820625c35a8c19f66c661efcbce7a5e334837msarett    fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
557168820625c35a8c19f66c661efcbce7a5e334837msarett    this->addInt(lattice.fYCount);
558168820625c35a8c19f66c661efcbce7a5e334837msarett    fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
5590764efe6a9ae65ad83992f614f57ca9db5b1f191msarett    this->addInt(flagCount);
5600764efe6a9ae65ad83992f614f57ca9db5b1f191msarett    fWriter.writePad(lattice.fFlags, flagCount * sizeof(SkCanvas::Lattice::Flags));
56171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    SkASSERT(lattice.fBounds);
56271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    this->addIRect(*lattice.fBounds);
563168820625c35a8c19f66c661efcbce7a5e334837msarett    this->addRect(dst);
564168820625c35a8c19f66c661efcbce7a5e334837msarett    this->validate(initialOffset, size);
565168820625c35a8c19f66c661efcbce7a5e334837msarett}
566168820625c35a8c19f66c661efcbce7a5e334837msarett
567e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
568e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                 const SkPaint& paint) {
5692ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + length + 'length' worth of chars + x + y
570dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
5712ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
57246616af01b412ea984a516fda1ed8ec08e689f29mtklein    DrawType op = DRAW_TEXT;
5738b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(op, &size);
57446616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
575cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
576cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(x);
577cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(y);
5788b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
581e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
582e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                    const SkPaint& paint) {
583dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    int points = paint.countText(text, byteLength);
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58546616af01b412ea984a516fda1ed8ec08e689f29mtklein    // op + paint index + length + 'length' worth of data + num points + x&y point data
58646616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58846616af01b412ea984a516fda1ed8ec08e689f29mtklein    DrawType op = DRAW_POS_TEXT;
5892ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
5908b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(op, &size);
59146616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
592cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
593cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(points);
59446616af01b412ea984a516fda1ed8ec08e689f29mtklein    fWriter.writeMul4(pos, points * sizeof(SkPoint));
5958b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
598e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
599e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                     SkScalar constY, const SkPaint& paint) {
600dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    int points = paint.countText(text, byteLength);
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6022ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + length + 'length' worth of data + num points
603dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
6042ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // + y + the actual points
6052ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    size += 1 * kUInt32Size + points * sizeof(SkScalar);
606cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org
60746616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
60846616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
609cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
610cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(points);
611cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(constY);
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(xpos, points * sizeof(SkScalar));
6138b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
616e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
617e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                       const SkMatrix* matrix, const SkPaint& paint) {
618fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + paint index + length + 'length' worth of data + path index + matrix
619fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
62096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
6218b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
622cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
623cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
624cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPath(path);
625cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(m);
6268b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62945561a0b15fe045ba272c328684c3f7ae290785areedvoid SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
63045561a0b15fe045ba272c328684c3f7ae290785areed                                        const SkRSXform xform[], const SkRect* cull,
63145561a0b15fe045ba272c328684c3f7ae290785areed                                        const SkPaint& paint) {
63245561a0b15fe045ba272c328684c3f7ae290785areed    const int count = paint.countText(text, byteLength);
63345561a0b15fe045ba272c328684c3f7ae290785areed    // [op + paint-index + count + flags + length] + [text] + [xform] + cull
63445561a0b15fe045ba272c328684c3f7ae290785areed    size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
63545561a0b15fe045ba272c328684c3f7ae290785areed    uint32_t flags = 0;
63645561a0b15fe045ba272c328684c3f7ae290785areed    if (cull) {
63745561a0b15fe045ba272c328684c3f7ae290785areed        flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
63845561a0b15fe045ba272c328684c3f7ae290785areed        size += sizeof(SkRect);
63945561a0b15fe045ba272c328684c3f7ae290785areed    }
64045561a0b15fe045ba272c328684c3f7ae290785areed
64145561a0b15fe045ba272c328684c3f7ae290785areed    size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
64245561a0b15fe045ba272c328684c3f7ae290785areed    this->addPaint(paint);
64345561a0b15fe045ba272c328684c3f7ae290785areed    this->addInt(count);
64445561a0b15fe045ba272c328684c3f7ae290785areed    this->addInt(flags);
64545561a0b15fe045ba272c328684c3f7ae290785areed    this->addText(text, byteLength);
64645561a0b15fe045ba272c328684c3f7ae290785areed    fWriter.write(xform, count * sizeof(SkRSXform));
64745561a0b15fe045ba272c328684c3f7ae290785areed    if (cull) {
64845561a0b15fe045ba272c328684c3f7ae290785areed        fWriter.write(cull, sizeof(SkRect));
64945561a0b15fe045ba272c328684c3f7ae290785areed    }
65045561a0b15fe045ba272c328684c3f7ae290785areed    this->validate(initialOffset, size);
65145561a0b15fe045ba272c328684c3f7ae290785areed}
65245561a0b15fe045ba272c328684c3f7ae290785areed
653b7425173f96e93b090787e2386ba5f022b6c2869fmalitavoid SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
654b7425173f96e93b090787e2386ba5f022b6c2869fmalita                                     const SkPaint& paint) {
655b7425173f96e93b090787e2386ba5f022b6c2869fmalita
656b7425173f96e93b090787e2386ba5f022b6c2869fmalita    // op + paint index + blob index + x/y
657b7425173f96e93b090787e2386ba5f022b6c2869fmalita    size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
658b7425173f96e93b090787e2386ba5f022b6c2869fmalita    size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
659b7425173f96e93b090787e2386ba5f022b6c2869fmalita
660b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addPaint(paint);
661b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addTextBlob(blob);
662b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addScalar(x);
663b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addScalar(y);
664b7425173f96e93b090787e2386ba5f022b6c2869fmalita
665b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->validate(initialOffset, size);
666b7425173f96e93b090787e2386ba5f022b6c2869fmalita}
667b7425173f96e93b090787e2386ba5f022b6c2869fmalita
668d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
669d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                                    const SkPaint* paint) {
6702ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + picture index
671dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
672d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    size_t initialOffset;
673d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
67496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == matrix && nullptr == paint) {
67595302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        initialOffset = this->addDraw(DRAW_PICTURE, &size);
67695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        this->addPicture(picture);
67795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    } else {
67895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
67995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        size += m.writeToMemory(nullptr) + kUInt32Size;    // matrix + paint
68095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
68195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        this->addPaintPtr(paint);
68295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        this->addMatrix(m);
68395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        this->addPicture(picture);
68495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    }
68595302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    this->validate(initialOffset, size);
68695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
68795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
68895416f477d2ca264f2fb065455e95778a2289a1dmsarettvoid SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
68995416f477d2ca264f2fb065455e95778a2289a1dmsarett    // op + drawable index
69095416f477d2ca264f2fb065455e95778a2289a1dmsarett    size_t size = 2 * kUInt32Size;
69195416f477d2ca264f2fb065455e95778a2289a1dmsarett    size_t initialOffset;
69295416f477d2ca264f2fb065455e95778a2289a1dmsarett
69395416f477d2ca264f2fb065455e95778a2289a1dmsarett    if (nullptr == matrix) {
69495416f477d2ca264f2fb065455e95778a2289a1dmsarett        initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
69595416f477d2ca264f2fb065455e95778a2289a1dmsarett        this->addDrawable(drawable);
69695416f477d2ca264f2fb065455e95778a2289a1dmsarett    } else {
69795416f477d2ca264f2fb065455e95778a2289a1dmsarett        size += matrix->writeToMemory(nullptr);    // matrix
69895416f477d2ca264f2fb065455e95778a2289a1dmsarett        initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
69995416f477d2ca264f2fb065455e95778a2289a1dmsarett        this->addMatrix(*matrix);
70095416f477d2ca264f2fb065455e95778a2289a1dmsarett        this->addDrawable(drawable);
70195416f477d2ca264f2fb065455e95778a2289a1dmsarett    }
70295416f477d2ca264f2fb065455e95778a2289a1dmsarett    this->validate(initialOffset, size);
70395416f477d2ca264f2fb065455e95778a2289a1dmsarett}
70495416f477d2ca264f2fb065455e95778a2289a1dmsarett
705e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkPictureRecord::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
706e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed                                           const SkPaint& paint) {
707e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    // op + paint index + vertices index + mode
708e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    size_t size = 4 * kUInt32Size;
709e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    size_t initialOffset = this->addDraw(DRAW_VERTICES_OBJECT, &size);
7102ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
711cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
712e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->addVertices(vertices);
713e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->addInt(static_cast<uint32_t>(mode));
714e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed
7158b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
718b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
719faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                                  const SkPoint texCoords[4], SkBlendMode bmode,
720b3c9d1c33caf325aada244204215eb790c228c12dandov                                  const SkPaint& paint) {
721b3c9d1c33caf325aada244204215eb790c228c12dandov    // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
722b3c9d1c33caf325aada244204215eb790c228c12dandov    size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
723b3c9d1c33caf325aada244204215eb790c228c12dandov    uint32_t flag = 0;
72449f085dddff10473b6ebf832a974288300224e60bsalomon    if (colors) {
725b3c9d1c33caf325aada244204215eb790c228c12dandov        flag |= DRAW_VERTICES_HAS_COLORS;
726b3c9d1c33caf325aada244204215eb790c228c12dandov        size += SkPatchUtils::kNumCorners * sizeof(SkColor);
727b3c9d1c33caf325aada244204215eb790c228c12dandov    }
72849f085dddff10473b6ebf832a974288300224e60bsalomon    if (texCoords) {
729b3c9d1c33caf325aada244204215eb790c228c12dandov        flag |= DRAW_VERTICES_HAS_TEXS;
730b3c9d1c33caf325aada244204215eb790c228c12dandov        size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
731b3c9d1c33caf325aada244204215eb790c228c12dandov    }
7327d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    if (SkBlendMode::kModulate != bmode) {
7337d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        flag |= DRAW_VERTICES_HAS_XFER;
7347d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        size += kUInt32Size;
735b3c9d1c33caf325aada244204215eb790c228c12dandov    }
73646616af01b412ea984a516fda1ed8ec08e689f29mtklein
737963137b75c0a1fe91f35e9826742f36309f5e65ddandov    size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
738963137b75c0a1fe91f35e9826742f36309f5e65ddandov    this->addPaint(paint);
739b3c9d1c33caf325aada244204215eb790c228c12dandov    this->addPatch(cubics);
740b3c9d1c33caf325aada244204215eb790c228c12dandov    this->addInt(flag);
74146616af01b412ea984a516fda1ed8ec08e689f29mtklein
742b3c9d1c33caf325aada244204215eb790c228c12dandov    // write optional parameters
74349f085dddff10473b6ebf832a974288300224e60bsalomon    if (colors) {
744b3c9d1c33caf325aada244204215eb790c228c12dandov        fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
745b3c9d1c33caf325aada244204215eb790c228c12dandov    }
74649f085dddff10473b6ebf832a974288300224e60bsalomon    if (texCoords) {
747b3c9d1c33caf325aada244204215eb790c228c12dandov        fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
748b3c9d1c33caf325aada244204215eb790c228c12dandov    }
749b3c9d1c33caf325aada244204215eb790c228c12dandov    if (flag & DRAW_VERTICES_HAS_XFER) {
7507d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        this->addInt((int)bmode);
751b3c9d1c33caf325aada244204215eb790c228c12dandov    }
752963137b75c0a1fe91f35e9826742f36309f5e65ddandov    this->validate(initialOffset, size);
753963137b75c0a1fe91f35e9826742f36309f5e65ddandov}
754963137b75c0a1fe91f35e9826742f36309f5e65ddandov
75571c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
756faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                                  const SkColor colors[], int count, SkBlendMode mode,
75771c3c760a83123ee0b3127b8c65c6394ce541c50reed                                  const SkRect* cull, const SkPaint* paint) {
75871c3c760a83123ee0b3127b8c65c6394ce541c50reed    // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
75971c3c760a83123ee0b3127b8c65c6394ce541c50reed    size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
76071c3c760a83123ee0b3127b8c65c6394ce541c50reed    uint32_t flags = 0;
76171c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (colors) {
76271c3c760a83123ee0b3127b8c65c6394ce541c50reed        flags |= DRAW_ATLAS_HAS_COLORS;
76371c3c760a83123ee0b3127b8c65c6394ce541c50reed        size += count * sizeof(SkColor);
76471c3c760a83123ee0b3127b8c65c6394ce541c50reed        size += sizeof(uint32_t);   // xfermode::mode
76571c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
76671c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull) {
76771c3c760a83123ee0b3127b8c65c6394ce541c50reed        flags |= DRAW_ATLAS_HAS_CULL;
76871c3c760a83123ee0b3127b8c65c6394ce541c50reed        size += sizeof(SkRect);
76971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
770c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein
77171c3c760a83123ee0b3127b8c65c6394ce541c50reed    size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
77271c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addPaintPtr(paint);
77371c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addImage(atlas);
77471c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addInt(flags);
77571c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addInt(count);
77671c3c760a83123ee0b3127b8c65c6394ce541c50reed    fWriter.write(xform, count * sizeof(SkRSXform));
77771c3c760a83123ee0b3127b8c65c6394ce541c50reed    fWriter.write(tex, count * sizeof(SkRect));
77871c3c760a83123ee0b3127b8c65c6394ce541c50reed
77971c3c760a83123ee0b3127b8c65c6394ce541c50reed    // write optional parameters
78071c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (colors) {
78171c3c760a83123ee0b3127b8c65c6394ce541c50reed        fWriter.write(colors, count * sizeof(SkColor));
7827d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        this->addInt((int)mode);
78371c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
78471c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull) {
78571c3c760a83123ee0b3127b8c65c6394ce541c50reed        fWriter.write(cull, sizeof(SkRect));
78671c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
78771c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->validate(initialOffset, size);
78871c3c760a83123ee0b3127b8c65c6394ce541c50reed}
78971c3c760a83123ee0b3127b8c65c6394ce541c50reed
7904123d0ff867f41c40fd288b31f4c976069753cccJim Van Verthvoid SkPictureRecord::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
7914123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    // op + path index + zParams + lightPos + lightRadius + spot/ambient alphas + color + flags
7924123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    size_t size = 2 * kUInt32Size + 2 * sizeof(SkPoint3) + 3 * sizeof(SkScalar) + 2 * kUInt32Size;
7934123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    size_t initialOffset = this->addDraw(DRAW_SHADOW_REC, &size);
7944123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth
7954123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    this->addPath(path);
7964123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth
7974123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    fWriter.writePoint3(rec.fZPlaneParams);
7984123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    fWriter.writePoint3(rec.fLightPos);
7994123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    fWriter.writeScalar(rec.fLightRadius);
8004123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    fWriter.writeScalar(rec.fAmbientAlpha);
8014123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    fWriter.writeScalar(rec.fSpotAlpha);
8024123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    fWriter.write32(rec.fColor);
8034123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    fWriter.write32(rec.fFlags);
8044123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth
8054123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    this->validate(initialOffset, size);
8064123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth}
8074123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth
808f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
809f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    size_t keyLen = fWriter.WriteStringSize(key);
810f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    size_t valueLen = fWriter.WriteDataSize(value);
811f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
812f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
813f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
814f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    this->addRect(rect);
815f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    fWriter.writeString(key);
816f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    fWriter.writeData(value);
817f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    this->validate(initialOffset, size);
818f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
819f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
82182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
82222b2af1dc42c0b95fe93b9a951313efe438e54cdreedtemplate <typename T> int find_or_append_uniqueID(SkTDArray<const T*>& array, const T* obj) {
82322b2af1dc42c0b95fe93b9a951313efe438e54cdreed    int index = array.select([&](const T* elem) {
82422b2af1dc42c0b95fe93b9a951313efe438e54cdreed        return elem->uniqueID() == obj->uniqueID();
82522b2af1dc42c0b95fe93b9a951313efe438e54cdreed    });
82622b2af1dc42c0b95fe93b9a951313efe438e54cdreed    if (index < 0) {
82722b2af1dc42c0b95fe93b9a951313efe438e54cdreed        index = array.count();
82822b2af1dc42c0b95fe93b9a951313efe438e54cdreed        *array.append() = SkRef(obj);
82922b2af1dc42c0b95fe93b9a951313efe438e54cdreed    }
83022b2af1dc42c0b95fe93b9a951313efe438e54cdreed    return index;
83122b2af1dc42c0b95fe93b9a951313efe438e54cdreed}
83222b2af1dc42c0b95fe93b9a951313efe438e54cdreed
833e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
83496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
83576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
83676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
837871872f3f247f6b699617f6d9ef50ef5da6fbe74reedvoid SkPictureRecord::addImage(const SkImage* image) {
83822b2af1dc42c0b95fe93b9a951313efe438e54cdreed    // convention for images is 0-based index
83922b2af1dc42c0b95fe93b9a951313efe438e54cdreed    this->addInt(find_or_append_uniqueID(fImageRefs, image));
840871872f3f247f6b699617f6d9ef50ef5da6fbe74reed}
841871872f3f247f6b699617f6d9ef50ef5da6fbe74reed
8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addMatrix(const SkMatrix& matrix) {
843fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    fWriter.writeMatrix(matrix);
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
84646616af01b412ea984a516fda1ed8ec08e689f29mtkleinvoid SkPictureRecord::addPaintPtr(const SkPaint* paint) {
847afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onAddPaintPtr(paint);
848e2cb12a82ad924f7b134a9459b190213485c6a50commit-bot@chromium.org
84946616af01b412ea984a516fda1ed8ec08e689f29mtklein    if (paint) {
850a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein        fPaints.push_back(*paint);
851a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein        this->addInt(fPaints.count());
85246616af01b412ea984a516fda1ed8ec08e689f29mtklein    } else {
85346616af01b412ea984a516fda1ed8ec08e689f29mtklein        this->addInt(0);
85446616af01b412ea984a516fda1ed8ec08e689f29mtklein    }
855cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org}
856cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org
8575a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comint SkPictureRecord::addPathToHeap(const SkPath& path) {
858c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    if (int* n = fPaths.find(path)) {
859c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein        return *n;
860c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    }
861c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    int n = fPaths.count() + 1;  // 0 is reserved for null / error.
862c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    fPaths.set(path, n);
863c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    return n;
8645a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
8655a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
8665a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comvoid SkPictureRecord::addPath(const SkPath& path) {
867cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(this->addPathToHeap(path));
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
870b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkPictureRecord::addPatch(const SkPoint cubics[12]) {
871b3c9d1c33caf325aada244204215eb790c228c12dandov    fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
872963137b75c0a1fe91f35e9826742f36309f5e65ddandov}
873963137b75c0a1fe91f35e9826742f36309f5e65ddandov
8749b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkPictureRecord::addPicture(const SkPicture* picture) {
8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // follow the convention of recording a 1-based index
87622b2af1dc42c0b95fe93b9a951313efe438e54cdreed    this->addInt(find_or_append_uniqueID(fPictureRefs, picture) + 1);
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
87995416f477d2ca264f2fb065455e95778a2289a1dmsarettvoid SkPictureRecord::addDrawable(SkDrawable* drawable) {
88095416f477d2ca264f2fb065455e95778a2289a1dmsarett    int index = fDrawableRefs.find(drawable);
88195416f477d2ca264f2fb065455e95778a2289a1dmsarett    if (index < 0) {    // not found
88295416f477d2ca264f2fb065455e95778a2289a1dmsarett        index = fDrawableRefs.count();
88395416f477d2ca264f2fb065455e95778a2289a1dmsarett        *fDrawableRefs.append() = drawable;
88495416f477d2ca264f2fb065455e95778a2289a1dmsarett        drawable->ref();
88595416f477d2ca264f2fb065455e95778a2289a1dmsarett    }
88695416f477d2ca264f2fb065455e95778a2289a1dmsarett    // follow the convention of recording a 1-based index
88795416f477d2ca264f2fb065455e95778a2289a1dmsarett    this->addInt(index + 1);
88895416f477d2ca264f2fb065455e95778a2289a1dmsarett}
88995416f477d2ca264f2fb065455e95778a2289a1dmsarett
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addPoint(const SkPoint& point) {
8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writePoint(point);
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
89382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addPoints(const SkPoint pts[], int count) {
8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(pts, count * sizeof(SkPoint));
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
89868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.orgvoid SkPictureRecord::addNoOp() {
89968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    size_t size = kUInt32Size; // op
90068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    this->addDraw(NOOP, &size);
90168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org}
90268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRect(const SkRect& rect) {
9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeRect(rect);
9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRectPtr(const SkRect* rect) {
90896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (fWriter.writeBool(rect != nullptr)) {
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWriter.writeRect(*rect);
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
913f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.comvoid SkPictureRecord::addIRect(const SkIRect& rect) {
914f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com    fWriter.write(&rect, sizeof(rect));
915f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com}
916f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com
9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addIRectPtr(const SkIRect* rect) {
91896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (fWriter.writeBool(rect != nullptr)) {
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9234ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkPictureRecord::addRRect(const SkRRect& rrect) {
9244ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    fWriter.writeRRect(rrect);
9254ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
9264ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRegion(const SkRegion& region) {
928fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    fWriter.writeRegion(region);
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addText(const void* text, size_t byteLength) {
932afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawText();
933dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    addInt(SkToInt(byteLength));
9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writePad(text, byteLength);
9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
93722b2af1dc42c0b95fe93b9a951313efe438e54cdreedvoid SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
938b7425173f96e93b090787e2386ba5f022b6c2869fmalita    // follow the convention of recording a 1-based index
93922b2af1dc42c0b95fe93b9a951313efe438e54cdreed    this->addInt(find_or_append_uniqueID(fTextBlobRefs, blob) + 1);
940b7425173f96e93b090787e2386ba5f022b6c2869fmalita}
941b7425173f96e93b090787e2386ba5f022b6c2869fmalita
942e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkPictureRecord::addVertices(const SkVertices* vertices) {
943e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    // follow the convention of recording a 1-based index
944e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->addInt(find_or_append_uniqueID(fVerticesRefs, vertices) + 1);
945e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed}
946e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
948