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"
9a85d4d0814818e4ddabb9237da209d61d6cd5854reed#include "SkImage_Base.h"
10b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
11b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPixelRef.h"
12b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkRRect.h"
1371c3c760a83123ee0b3127b8c65c6394ce541c50reed#include "SkRSXform.h"
14b7425173f96e93b090787e2386ba5f022b6c2869fmalita#include "SkTextBlob.h"
15b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkTSearch.h"
16ebfce6d9b42198e04288a15953f40c395a7b6139Mike Reed#include "SkClipOpPriv.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define HEAP_BLOCK_SIZE 4096
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
204e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.orgenum {
21d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // just need a value that save or getSaveCount would never return
224e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    kNoInitialSave = -1,
234e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org};
244e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org
252ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
262ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.comstatic int const kUInt32Size = 4;
272ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
280bdbea75ff1a6f3c313c18cab0139728967cb93erobertphillipsSkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
2919fafef9784fe7c644540ffd0ee9f6da1914a038commit-bot@chromium.org    : INHERITED(dimensions.width(), dimensions.height())
3071a236370792416b367a7d2d6b8e471b06b331cdmtklein    , fRecordFlags(flags)
3171a236370792416b367a7d2d6b8e471b06b331cdmtklein    , fInitialSaveCount(kNoInitialSave) {
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkPictureRecord::~SkPictureRecord() {
355351aad9bc5b2e3101472248967e3dc1f84d24eerobertphillips    fImageRefs.unrefAll();
3621830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com    fPictureRefs.unrefAll();
3795416f477d2ca264f2fb065455e95778a2289a1dmsarett    fDrawableRefs.unrefAll();
38b7425173f96e93b090787e2386ba5f022b6c2869fmalita    fTextBlobRefs.unrefAll();
39e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    fVerticesRefs.unrefAll();
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
445f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitavoid SkPictureRecord::willSave() {
45ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // record the offset to us, making it non-positive to distinguish a save
46ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // from a clip entry.
474469938e92d779dff05e745559e67907bbf21e78reed@google.com    fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
485f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    this->recordSave();
49e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
505f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    this->INHERITED::willSave();
515a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
5211f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
535f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitavoid SkPictureRecord::recordSave() {
54c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onSave();
55c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
565f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    // op only
57512f3e3b2592097a39bde9331829b38d16c0f85dreed    size_t size = sizeof(kUInt32Size);
588b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SAVE, &size);
5982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
608b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
634960eeec4a1f2a772654883d7f3615d47bcd5dc3reedSkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
64ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // record the offset to us, making it non-positive to distinguish a save
65ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // from a clip entry.
664469938e92d779dff05e745559e67907bbf21e78reed@google.com    fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
674960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    this->recordSaveLayer(rec);
6811f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
694960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    (void)this->INHERITED::getSaveLayerStrategy(rec);
70e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    /*  No need for a (potentially very big) layer which we don't actually need
715a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        at this time (and may not be able to afford since during record our
725a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        clip starts out the size of the picture, which is often much larger
735a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        than the size of the actual device we'll use during playback).
745a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com     */
75e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    return kNoLayer_SaveLayerStrategy;
765a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
775a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
784960eeec4a1f2a772654883d7f3615d47bcd5dc3reedvoid SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
79c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onSaveLayer();
80c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
81bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    // op + flatflags
82dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
83bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    uint32_t flatFlags = 0;
84bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed
854960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (rec.fBounds) {
86bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_BOUNDS;
87bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(*rec.fBounds);
88bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
89bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (rec.fPaint) {
90bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_PAINT;
91bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(uint32_t); // index
92bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
93bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (rec.fBackdrop) {
94bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_BACKDROP;
95bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(uint32_t); // (paint) index
96bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
97bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (rec.fSaveLayerFlags) {
98bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_FLAGS;
99bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(uint32_t);
1002ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
102bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
103bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    this->addInt(flatFlags);
104bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
105bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addRect(*rec.fBounds);
106bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
107bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_PAINT) {
108bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addPaintPtr(rec.fPaint);
109bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
110bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
111bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        // overkill, but we didn't already track single flattenables, so using a paint for that
112bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        SkPaint paint;
1135e25717ab6313b011ec54eac0109c414aa8ffc17Mike Reed        paint.setImageFilter(sk_ref_sp(const_cast<SkImageFilter*>(rec.fBackdrop)));
114bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addPaint(paint);
115bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
116bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
117bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addInt(rec.fSaveLayerFlags);
118bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
1198b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
122210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org#ifdef SK_DEBUG
123210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org/*
1242ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com * Read the op code from 'offset' in 'writer' and extract the size too.
1252ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com */
126dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgstatic DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
127536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    uint32_t peek = writer->readTAt<uint32_t>(offset);
1282ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
1292ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    uint32_t op;
130c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org    UNPACK_8_24(peek, op, *size);
1312ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    if (MASK_24 == *size) {
1322ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        // size required its own slot right after the op code
133536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
1342ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
1352ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    return (DrawType) op;
136ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com}
13746616af01b412ea984a516fda1ed8ec08e689f29mtklein#endif//SK_DEBUG
1384b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org
139e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgvoid SkPictureRecord::willRestore() {
1404e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org#if 0
1414e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    SkASSERT(fRestoreOffsetStack.count() > 1);
1424e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org#endif
1434e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org
144b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    // check for underflow
145b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    if (fRestoreOffsetStack.count() == 0) {
146b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com        return;
147b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    }
148b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com
14946616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->recordRestore();
150ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com
151b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    fRestoreOffsetStack.pop();
15232a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com
153e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    this->INHERITED::willRestore();
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
156105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.comvoid SkPictureRecord::recordRestore(bool fillInSkips) {
157c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onRestore();
158c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
159105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    if (fillInSkips) {
160105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
161105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
162dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
163dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t initialOffset = this->addDraw(RESTORE, &size);
1645a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    this->validate(initialOffset, size);
1655a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
1665a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
167d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.orgvoid SkPictureRecord::recordTranslate(const SkMatrix& m) {
168d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
169d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
1702ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + dx + dy
171dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
1728b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(TRANSLATE, &size);
173d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getTranslateX());
174d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getTranslateY());
1758b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
178d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.orgvoid SkPictureRecord::recordScale(const SkMatrix& m) {
179d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkASSERT(SkMatrix::kScale_Mask == m.getType());
180105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
1812ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + sx + sy
182dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
1838b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SCALE, &size);
184d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getScaleX());
185d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getScaleY());
1868b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkPictureRecord::didConcat(const SkMatrix& matrix) {
190d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    switch (matrix.getType()) {
191d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        case SkMatrix::kTranslate_Mask:
192d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordTranslate(matrix);
193d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
194d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        case SkMatrix::kScale_Mask:
195d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordScale(matrix);
196d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
197d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        default:
198d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordConcat(matrix);
199d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
200d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
20144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->INHERITED::didConcat(matrix);
2025a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
2035a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
2045a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comvoid SkPictureRecord::recordConcat(const SkMatrix& matrix) {
2054469938e92d779dff05e745559e67907bbf21e78reed@google.com    this->validate(fWriter.bytesWritten(), 0);
206fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + matrix
20796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
2088b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CONCAT, &size);
209cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(matrix);
2108b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21344c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
2144469938e92d779dff05e745559e67907bbf21e78reed@google.com    this->validate(fWriter.bytesWritten(), 0);
215fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + matrix
21696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
2178b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SET_MATRIX, &size);
218cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(matrix);
2198b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
22044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->INHERITED::didSetMatrix(matrix);
2216e073b9e2b70d6bbf8a06050fff1364827204f08reed@android.com}
2226e073b9e2b70d6bbf8a06050fff1364827204f08reed@android.com
223e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblackvoid SkPictureRecord::didTranslateZ(SkScalar z) {
22495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#ifdef SK_EXPERIMENTAL_SHADOWING
225e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->validate(fWriter.bytesWritten(), 0);
226e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    // op + scalar
227e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    size_t size = 1 * kUInt32Size + 1 * sizeof(SkScalar);
228e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    size_t initialOffset = this->addDraw(TRANSLATE_Z, &size);
229e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->addScalar(z);
230e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->validate(initialOffset, size);
231e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->INHERITED::didTranslateZ(z);
23295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#endif
233e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack}
234e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack
235c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedstatic bool clipOpExpands(SkClipOp op) {
23645482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    switch (op) {
237c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kUnion_SkClipOp:
238c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kXOR_SkClipOp:
239c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kReverseDifference_SkClipOp:
240c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kReplace_SkClipOp:
24145482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return true;
242c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kIntersect_SkClipOp:
243c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        case kDifference_SkClipOp:
24445482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return false;
24545482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        default:
246c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed            SkDEBUGFAIL("unknown clipop");
24745482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return false;
24845482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    }
24945482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com}
25045482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com
251e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.comvoid SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
252ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    int32_t offset = fRestoreOffsetStack.top();
253ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    while (offset > 0) {
254536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        uint32_t peek = fWriter.readTAt<uint32_t>(offset);
255536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        fWriter.overwriteTAt(offset, restoreOffset);
256c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org        offset = peek;
257e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org    }
25811f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
259ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com#ifdef SK_DEBUG
2602ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    // offset of 0 has been disabled, so we skip it
2612ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (offset > 0) {
2622ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // assert that the final offset value points to a save verb
2632ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        uint32_t opSize;
2642ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
2654960eeec4a1f2a772654883d7f3615d47bcd5dc3reed        SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
266bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
267bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
2682ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
269ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com#endif
270e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org}
271e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org
272d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.comvoid SkPictureRecord::beginRecording() {
273d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // we have to call this *after* our constructor, to ensure that it gets
274d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // recorded. This is balanced by restoreToCount() call from endRecording,
275d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // which in-turn calls our overridden restore(), so those get recorded too.
276091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org    fInitialSaveCount = this->save();
277d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com}
278d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com
279a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.orgvoid SkPictureRecord::endRecording() {
2804e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    SkASSERT(kNoInitialSave != fInitialSaveCount);
2814e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    this->restoreToCount(fInitialSaveCount);
282a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.org}
283a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.org
284c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedsize_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkClipOp op) {
28521b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com    if (fRestoreOffsetStack.isEmpty()) {
2865a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        return -1;
28721b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com    }
28821b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com
289d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // The RestoreOffset field is initially filled with a placeholder
290d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // value that points to the offset of the previous RestoreOffset
291d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // in the current stack level, thus forming a linked list so that
292d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // the restore offsets can be filled in when the corresponding
293d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // restore command is recorded.
294d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    int32_t prevOffset = fRestoreOffsetStack.top();
295d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com
29673603f3c52ffd89fe9d035be827b566a0e7d3b79reed    if (clipOpExpands(op)) {
29745482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // Run back through any previous clip ops, and mark their offset to
29845482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // be 0, disabling their ability to trigger a jump-to-restore, otherwise
29945482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // they could hide this clips ability to expand the clip (i.e. go from
30045482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // empty to non-empty).
301cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com        this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
302d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com
303d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        // Reset the pointer back to the previous clip so that subsequent
304d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        // restores don't overwrite the offsets we just cleared.
305d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        prevOffset = 0;
30645482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    }
30774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3084469938e92d779dff05e745559e67907bbf21e78reed@google.com    size_t offset = fWriter.bytesWritten();
309cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(prevOffset);
310dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    fRestoreOffsetStack.top() = SkToU32(offset);
3115a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
31245482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com}
31345482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com
314c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkPictureRecord::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
3158f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
3168f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->INHERITED::onClipRect(rect, op, edgeStyle);
3175a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3185a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
319c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedsize_t SkPictureRecord::recordClipRect(const SkRect& rect, SkClipOp op, bool doAA) {
320f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // id + rect + clip params
321dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
3224310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
323f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
324f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
325f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
326f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3278b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_RECT, &size);
328cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(rect);
329cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
330dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = this->recordRestoreOffsetPlaceholder(op);
331306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
3328b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3335a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
33468d61ed83ec7b6e98e9623c2f5c9e7b1a32d25bbreed@google.com}
33568d61ed83ec7b6e98e9623c2f5c9e7b1a32d25bbreed@google.com
336c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkPictureRecord::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
3378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
338d954498c01ccf0417feacf89e45d0c62a06a813breed    this->INHERITED::onClipRRect(rrect, op, edgeStyle);
3395a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3405a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
341c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedsize_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
342f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // op + rrect + clip params
343dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
3444310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
345f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
346f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
347f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
348f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3498b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
350cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRRect(rrect);
351cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
352dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = recordRestoreOffsetPlaceholder(op);
3538b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3545a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
3554ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
3564ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
357c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkPictureRecord::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
3585a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    int pathID = this->addPathToHeap(path);
3598f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
360d954498c01ccf0417feacf89e45d0c62a06a813breed    this->INHERITED::onClipPath(path, op, edgeStyle);
3615a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3625a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
363c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedsize_t SkPictureRecord::recordClipPath(int pathID, SkClipOp op, bool doAA) {
364f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // op + path index + clip params
365dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size;
3664310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
367f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
368f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
369f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
370f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3718b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_PATH, &size);
372cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(pathID);
373cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
374dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = recordRestoreOffsetPlaceholder(op);
3758b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3765a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
379c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkPictureRecord::onClipRegion(const SkRegion& region, SkClipOp op) {
3805a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    this->recordClipRegion(region, op);
3818f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->INHERITED::onClipRegion(region, op);
3825a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3835a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
384c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedsize_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkClipOp op) {
385fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + clip params + region
38696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
3874310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
388f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
389f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
390f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
391f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3928b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_REGION, &size);
393cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRegion(region);
394cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, false));
395dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = this->recordRestoreOffsetPlaceholder(op);
39682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3978b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3985a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
40141af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPaint(const SkPaint& paint) {
4022ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index
403dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
4048b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
405cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
4068b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
40941af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
41041af966ab338e95eee81ab618ab28195075338f7reed                                   const SkPaint& paint) {
411afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawPoints(count, paint);
412105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
4132ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + mode + count + point data
414dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
4158b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
416cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
417afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw
418cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(mode);
419dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    this->addInt(SkToInt(count));
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(pts, count * sizeof(SkPoint));
4218b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42441af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
4252ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + rect
426dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + sizeof(oval);
4278b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
428cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
429cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(oval);
4308b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4314ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
4324ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
433ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomonvoid SkPictureRecord::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
434ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                                bool useCenter, const SkPaint& paint) {
435ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    // op + paint index + rect + start + sweep + bool (as int)
436ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    size_t size = 2 * kUInt32Size + sizeof(oval) + sizeof(startAngle) + sizeof(sweepAngle) +
437ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                  sizeof(int);
438ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    size_t initialOffset = this->addDraw(DRAW_ARC, &size);
439ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->addPaint(paint);
440ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->addRect(oval);
441ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->addScalar(startAngle);
442ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->addScalar(sweepAngle);
443ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->addInt(useCenter);
444ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    this->validate(initialOffset, size);
445ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon}
446ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
44741af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
4482ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + rect
449dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + sizeof(rect);
4508b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_RECT, &size);
451cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
452cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(rect);
4538b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45644df651ebefc284acc2f66425dff3ea0b0e14b36msarettvoid SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
45744df651ebefc284acc2f66425dff3ea0b0e14b36msarett    // op + paint index + region
45844df651ebefc284acc2f66425dff3ea0b0e14b36msarett    size_t regionBytes = region.writeToMemory(nullptr);
45944df651ebefc284acc2f66425dff3ea0b0e14b36msarett    size_t size = 2 * kUInt32Size + regionBytes;
46044df651ebefc284acc2f66425dff3ea0b0e14b36msarett    size_t initialOffset = this->addDraw(DRAW_REGION, &size);
46144df651ebefc284acc2f66425dff3ea0b0e14b36msarett    this->addPaint(paint);
46244df651ebefc284acc2f66425dff3ea0b0e14b36msarett    fWriter.writeRegion(region);
46344df651ebefc284acc2f66425dff3ea0b0e14b36msarett    this->validate(initialOffset, size);
46444df651ebefc284acc2f66425dff3ea0b0e14b36msarett}
46544df651ebefc284acc2f66425dff3ea0b0e14b36msarett
46641af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
46746616af01b412ea984a516fda1ed8ec08e689f29mtklein    // op + paint index + rrect
46846616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
46946616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
47046616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
47146616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addRRect(rrect);
47246616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->validate(initialOffset, size);
4734ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
4744ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
475ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
476ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                                   const SkPaint& paint) {
477ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // op + paint index + rrects
478dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
479dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
480ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addPaint(paint);
481ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addRRect(outer);
482ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addRRect(inner);
483ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->validate(initialOffset, size);
484ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
485ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
48641af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
487afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawPath(path, paint);
488e2cb12a82ad924f7b134a9459b190213485c6a50commit-bot@chromium.org
4892ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + path index
490dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size;
4918b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_PATH, &size);
492cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
493cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPath(path);
4948b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
497a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
498a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                  const SkPaint* paint) {
499871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    // op + paint_index + image_index + x + y
500871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
501871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
502871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addPaintPtr(paint);
503871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addImage(image);
504871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addScalar(x);
505871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addScalar(y);
506871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->validate(initialOffset, size);
507a85d4d0814818e4ddabb9237da209d61d6cd5854reed}
508a85d4d0814818e4ddabb9237da209d61d6cd5854reed
509a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
510562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                      const SkPaint* paint, SrcRectConstraint constraint) {
511a5517e2b190a8083b38964972b031c13e99f1012reed    // id + paint_index + image_index + bool_for_src + constraint
512a5517e2b190a8083b38964972b031c13e99f1012reed    size_t size = 5 * kUInt32Size;
513871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    if (src) {
514871872f3f247f6b699617f6d9ef50ef5da6fbe74reed        size += sizeof(*src);   // + rect
515a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
516871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size += sizeof(dst);        // + rect
517c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein
518871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
519871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addPaintPtr(paint);
520871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addImage(image);
521871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addRectPtr(src);  // may be null
522871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addRect(dst);
523a5517e2b190a8083b38964972b031c13e99f1012reed    this->addInt(constraint);
524871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->validate(initialOffset, size);
525a85d4d0814818e4ddabb9237da209d61d6cd5854reed}
526a85d4d0814818e4ddabb9237da209d61d6cd5854reed
5274c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
5284c21dc5ddf3b482293ed34eead876d8d61a662c3reed                                      const SkPaint* paint) {
5294c21dc5ddf3b482293ed34eead876d8d61a662c3reed    // id + paint_index + image_index + center + dst
5304c21dc5ddf3b482293ed34eead876d8d61a662c3reed    size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
531c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein
5324c21dc5ddf3b482293ed34eead876d8d61a662c3reed    size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
5334c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addPaintPtr(paint);
5344c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addImage(img);
5354c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addIRect(center);
5364c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addRect(dst);
5374c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->validate(initialOffset, size);
5384c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
5394c21dc5ddf3b482293ed34eead876d8d61a662c3reed
540168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
541168820625c35a8c19f66c661efcbce7a5e334837msarett                                         const SkRect& dst, const SkPaint* paint) {
542168820625c35a8c19f66c661efcbce7a5e334837msarett    // xCount + xDivs + yCount+ yDivs
5430764efe6a9ae65ad83992f614f57ca9db5b1f191msarett    int flagCount = (nullptr == lattice.fFlags) ? 0 : (lattice.fXCount + 1) * (lattice.fYCount + 1);
5440764efe6a9ae65ad83992f614f57ca9db5b1f191msarett    size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size +
54571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett                         SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)) + sizeof(SkIRect);
546168820625c35a8c19f66c661efcbce7a5e334837msarett
547168820625c35a8c19f66c661efcbce7a5e334837msarett    // op + paint index + image index + lattice + dst rect
548168820625c35a8c19f66c661efcbce7a5e334837msarett    size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
549168820625c35a8c19f66c661efcbce7a5e334837msarett    size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
550168820625c35a8c19f66c661efcbce7a5e334837msarett    this->addPaintPtr(paint);
551168820625c35a8c19f66c661efcbce7a5e334837msarett    this->addImage(image);
552168820625c35a8c19f66c661efcbce7a5e334837msarett    this->addInt(lattice.fXCount);
553168820625c35a8c19f66c661efcbce7a5e334837msarett    fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
554168820625c35a8c19f66c661efcbce7a5e334837msarett    this->addInt(lattice.fYCount);
555168820625c35a8c19f66c661efcbce7a5e334837msarett    fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
5560764efe6a9ae65ad83992f614f57ca9db5b1f191msarett    this->addInt(flagCount);
5570764efe6a9ae65ad83992f614f57ca9db5b1f191msarett    fWriter.writePad(lattice.fFlags, flagCount * sizeof(SkCanvas::Lattice::Flags));
55871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    SkASSERT(lattice.fBounds);
55971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    this->addIRect(*lattice.fBounds);
560168820625c35a8c19f66c661efcbce7a5e334837msarett    this->addRect(dst);
561168820625c35a8c19f66c661efcbce7a5e334837msarett    this->validate(initialOffset, size);
562168820625c35a8c19f66c661efcbce7a5e334837msarett}
563168820625c35a8c19f66c661efcbce7a5e334837msarett
564e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
565e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                 const SkPaint& paint) {
5662ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + length + 'length' worth of chars + x + y
567dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
5682ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
56946616af01b412ea984a516fda1ed8ec08e689f29mtklein    DrawType op = DRAW_TEXT;
5708b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(op, &size);
57146616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
572cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
573cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(x);
574cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(y);
5758b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
578e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
579e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                    const SkPaint& paint) {
580dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    int points = paint.countText(text, byteLength);
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58246616af01b412ea984a516fda1ed8ec08e689f29mtklein    // op + paint index + length + 'length' worth of data + num points + x&y point data
58346616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58546616af01b412ea984a516fda1ed8ec08e689f29mtklein    DrawType op = DRAW_POS_TEXT;
5862ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
5878b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(op, &size);
58846616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
589cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
590cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(points);
59146616af01b412ea984a516fda1ed8ec08e689f29mtklein    fWriter.writeMul4(pos, points * sizeof(SkPoint));
5928b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
595e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
596e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                     SkScalar constY, const SkPaint& paint) {
597dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    int points = paint.countText(text, byteLength);
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5992ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + length + 'length' worth of data + num points
600dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
6012ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // + y + the actual points
6022ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    size += 1 * kUInt32Size + points * sizeof(SkScalar);
603cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org
60446616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
60546616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
606cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
607cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(points);
608cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(constY);
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(xpos, points * sizeof(SkScalar));
6108b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
613e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
614e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                       const SkMatrix* matrix, const SkPaint& paint) {
615fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + paint index + length + 'length' worth of data + path index + matrix
616fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
61796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
6188b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
619cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
620cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
621cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPath(path);
622cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(m);
6238b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62645561a0b15fe045ba272c328684c3f7ae290785areedvoid SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
62745561a0b15fe045ba272c328684c3f7ae290785areed                                        const SkRSXform xform[], const SkRect* cull,
62845561a0b15fe045ba272c328684c3f7ae290785areed                                        const SkPaint& paint) {
62945561a0b15fe045ba272c328684c3f7ae290785areed    const int count = paint.countText(text, byteLength);
63045561a0b15fe045ba272c328684c3f7ae290785areed    // [op + paint-index + count + flags + length] + [text] + [xform] + cull
63145561a0b15fe045ba272c328684c3f7ae290785areed    size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
63245561a0b15fe045ba272c328684c3f7ae290785areed    uint32_t flags = 0;
63345561a0b15fe045ba272c328684c3f7ae290785areed    if (cull) {
63445561a0b15fe045ba272c328684c3f7ae290785areed        flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
63545561a0b15fe045ba272c328684c3f7ae290785areed        size += sizeof(SkRect);
63645561a0b15fe045ba272c328684c3f7ae290785areed    }
63745561a0b15fe045ba272c328684c3f7ae290785areed
63845561a0b15fe045ba272c328684c3f7ae290785areed    size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
63945561a0b15fe045ba272c328684c3f7ae290785areed    this->addPaint(paint);
64045561a0b15fe045ba272c328684c3f7ae290785areed    this->addInt(count);
64145561a0b15fe045ba272c328684c3f7ae290785areed    this->addInt(flags);
64245561a0b15fe045ba272c328684c3f7ae290785areed    this->addText(text, byteLength);
64345561a0b15fe045ba272c328684c3f7ae290785areed    fWriter.write(xform, count * sizeof(SkRSXform));
64445561a0b15fe045ba272c328684c3f7ae290785areed    if (cull) {
64545561a0b15fe045ba272c328684c3f7ae290785areed        fWriter.write(cull, sizeof(SkRect));
64645561a0b15fe045ba272c328684c3f7ae290785areed    }
64745561a0b15fe045ba272c328684c3f7ae290785areed    this->validate(initialOffset, size);
64845561a0b15fe045ba272c328684c3f7ae290785areed}
64945561a0b15fe045ba272c328684c3f7ae290785areed
650b7425173f96e93b090787e2386ba5f022b6c2869fmalitavoid SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
651b7425173f96e93b090787e2386ba5f022b6c2869fmalita                                     const SkPaint& paint) {
652b7425173f96e93b090787e2386ba5f022b6c2869fmalita
653b7425173f96e93b090787e2386ba5f022b6c2869fmalita    // op + paint index + blob index + x/y
654b7425173f96e93b090787e2386ba5f022b6c2869fmalita    size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
655b7425173f96e93b090787e2386ba5f022b6c2869fmalita    size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
656b7425173f96e93b090787e2386ba5f022b6c2869fmalita
657b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addPaint(paint);
658b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addTextBlob(blob);
659b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addScalar(x);
660b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addScalar(y);
661b7425173f96e93b090787e2386ba5f022b6c2869fmalita
662b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->validate(initialOffset, size);
663b7425173f96e93b090787e2386ba5f022b6c2869fmalita}
664b7425173f96e93b090787e2386ba5f022b6c2869fmalita
665d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
666d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                                    const SkPaint* paint) {
6672ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + picture index
668dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
669d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    size_t initialOffset;
670d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
67196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == matrix && nullptr == paint) {
672d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        initialOffset = this->addDraw(DRAW_PICTURE, &size);
673d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        this->addPicture(picture);
674d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    } else {
675d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
67696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        size += m.writeToMemory(nullptr) + kUInt32Size;    // matrix + paint
677d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
678d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        this->addPaintPtr(paint);
6799f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita        this->addMatrix(m);
6809f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita        this->addPicture(picture);
681d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
6828b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
68595302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblackvoid SkPictureRecord::onDrawShadowedPicture(const SkPicture* picture,
68695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack                                            const SkMatrix* matrix,
687e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                            const SkPaint* paint,
688e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                            const SkShadowParams& params) {
68995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    // op + picture index
69095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    size_t size = 2 * kUInt32Size;
69195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    size_t initialOffset;
69295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
693e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack    // TODO: handle recording params.
69495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    if (nullptr == matrix && nullptr == paint) {
69595302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        initialOffset = this->addDraw(DRAW_PICTURE, &size);
69695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        this->addPicture(picture);
69795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    } else {
69895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
69995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        size += m.writeToMemory(nullptr) + kUInt32Size;    // matrix + paint
70095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
70195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        this->addPaintPtr(paint);
70295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        this->addMatrix(m);
70395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        this->addPicture(picture);
70495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    }
70595302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    this->validate(initialOffset, size);
70695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
70795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
70895416f477d2ca264f2fb065455e95778a2289a1dmsarettvoid SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
70995416f477d2ca264f2fb065455e95778a2289a1dmsarett    // op + drawable index
71095416f477d2ca264f2fb065455e95778a2289a1dmsarett    size_t size = 2 * kUInt32Size;
71195416f477d2ca264f2fb065455e95778a2289a1dmsarett    size_t initialOffset;
71295416f477d2ca264f2fb065455e95778a2289a1dmsarett
71395416f477d2ca264f2fb065455e95778a2289a1dmsarett    if (nullptr == matrix) {
71495416f477d2ca264f2fb065455e95778a2289a1dmsarett        initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
71595416f477d2ca264f2fb065455e95778a2289a1dmsarett        this->addDrawable(drawable);
71695416f477d2ca264f2fb065455e95778a2289a1dmsarett    } else {
71795416f477d2ca264f2fb065455e95778a2289a1dmsarett        size += matrix->writeToMemory(nullptr);    // matrix
71895416f477d2ca264f2fb065455e95778a2289a1dmsarett        initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
71995416f477d2ca264f2fb065455e95778a2289a1dmsarett        this->addMatrix(*matrix);
72095416f477d2ca264f2fb065455e95778a2289a1dmsarett        this->addDrawable(drawable);
72195416f477d2ca264f2fb065455e95778a2289a1dmsarett    }
72295416f477d2ca264f2fb065455e95778a2289a1dmsarett    this->validate(initialOffset, size);
72395416f477d2ca264f2fb065455e95778a2289a1dmsarett}
72495416f477d2ca264f2fb065455e95778a2289a1dmsarett
725e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkPictureRecord::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
726e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed                                           const SkPaint& paint) {
727e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    // op + paint index + vertices index + mode
728e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    size_t size = 4 * kUInt32Size;
729e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    size_t initialOffset = this->addDraw(DRAW_VERTICES_OBJECT, &size);
7302ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
731cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
732e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->addVertices(vertices);
733e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->addInt(static_cast<uint32_t>(mode));
734e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed
7358b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
738b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
739faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                                  const SkPoint texCoords[4], SkBlendMode bmode,
740b3c9d1c33caf325aada244204215eb790c228c12dandov                                  const SkPaint& paint) {
741b3c9d1c33caf325aada244204215eb790c228c12dandov    // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
742b3c9d1c33caf325aada244204215eb790c228c12dandov    size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
743b3c9d1c33caf325aada244204215eb790c228c12dandov    uint32_t flag = 0;
74449f085dddff10473b6ebf832a974288300224e60bsalomon    if (colors) {
745b3c9d1c33caf325aada244204215eb790c228c12dandov        flag |= DRAW_VERTICES_HAS_COLORS;
746b3c9d1c33caf325aada244204215eb790c228c12dandov        size += SkPatchUtils::kNumCorners * sizeof(SkColor);
747b3c9d1c33caf325aada244204215eb790c228c12dandov    }
74849f085dddff10473b6ebf832a974288300224e60bsalomon    if (texCoords) {
749b3c9d1c33caf325aada244204215eb790c228c12dandov        flag |= DRAW_VERTICES_HAS_TEXS;
750b3c9d1c33caf325aada244204215eb790c228c12dandov        size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
751b3c9d1c33caf325aada244204215eb790c228c12dandov    }
7527d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    if (SkBlendMode::kModulate != bmode) {
7537d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        flag |= DRAW_VERTICES_HAS_XFER;
7547d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        size += kUInt32Size;
755b3c9d1c33caf325aada244204215eb790c228c12dandov    }
75646616af01b412ea984a516fda1ed8ec08e689f29mtklein
757963137b75c0a1fe91f35e9826742f36309f5e65ddandov    size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
758963137b75c0a1fe91f35e9826742f36309f5e65ddandov    this->addPaint(paint);
759b3c9d1c33caf325aada244204215eb790c228c12dandov    this->addPatch(cubics);
760b3c9d1c33caf325aada244204215eb790c228c12dandov    this->addInt(flag);
76146616af01b412ea984a516fda1ed8ec08e689f29mtklein
762b3c9d1c33caf325aada244204215eb790c228c12dandov    // write optional parameters
76349f085dddff10473b6ebf832a974288300224e60bsalomon    if (colors) {
764b3c9d1c33caf325aada244204215eb790c228c12dandov        fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
765b3c9d1c33caf325aada244204215eb790c228c12dandov    }
76649f085dddff10473b6ebf832a974288300224e60bsalomon    if (texCoords) {
767b3c9d1c33caf325aada244204215eb790c228c12dandov        fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
768b3c9d1c33caf325aada244204215eb790c228c12dandov    }
769b3c9d1c33caf325aada244204215eb790c228c12dandov    if (flag & DRAW_VERTICES_HAS_XFER) {
7707d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        this->addInt((int)bmode);
771b3c9d1c33caf325aada244204215eb790c228c12dandov    }
772963137b75c0a1fe91f35e9826742f36309f5e65ddandov    this->validate(initialOffset, size);
773963137b75c0a1fe91f35e9826742f36309f5e65ddandov}
774963137b75c0a1fe91f35e9826742f36309f5e65ddandov
77571c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
776faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                                  const SkColor colors[], int count, SkBlendMode mode,
77771c3c760a83123ee0b3127b8c65c6394ce541c50reed                                  const SkRect* cull, const SkPaint* paint) {
77871c3c760a83123ee0b3127b8c65c6394ce541c50reed    // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
77971c3c760a83123ee0b3127b8c65c6394ce541c50reed    size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
78071c3c760a83123ee0b3127b8c65c6394ce541c50reed    uint32_t flags = 0;
78171c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (colors) {
78271c3c760a83123ee0b3127b8c65c6394ce541c50reed        flags |= DRAW_ATLAS_HAS_COLORS;
78371c3c760a83123ee0b3127b8c65c6394ce541c50reed        size += count * sizeof(SkColor);
78471c3c760a83123ee0b3127b8c65c6394ce541c50reed        size += sizeof(uint32_t);   // xfermode::mode
78571c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
78671c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull) {
78771c3c760a83123ee0b3127b8c65c6394ce541c50reed        flags |= DRAW_ATLAS_HAS_CULL;
78871c3c760a83123ee0b3127b8c65c6394ce541c50reed        size += sizeof(SkRect);
78971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
790c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein
79171c3c760a83123ee0b3127b8c65c6394ce541c50reed    size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
79271c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addPaintPtr(paint);
79371c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addImage(atlas);
79471c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addInt(flags);
79571c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addInt(count);
79671c3c760a83123ee0b3127b8c65c6394ce541c50reed    fWriter.write(xform, count * sizeof(SkRSXform));
79771c3c760a83123ee0b3127b8c65c6394ce541c50reed    fWriter.write(tex, count * sizeof(SkRect));
79871c3c760a83123ee0b3127b8c65c6394ce541c50reed
79971c3c760a83123ee0b3127b8c65c6394ce541c50reed    // write optional parameters
80071c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (colors) {
80171c3c760a83123ee0b3127b8c65c6394ce541c50reed        fWriter.write(colors, count * sizeof(SkColor));
8027d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        this->addInt((int)mode);
80371c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
80471c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull) {
80571c3c760a83123ee0b3127b8c65c6394ce541c50reed        fWriter.write(cull, sizeof(SkRect));
80671c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
80771c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->validate(initialOffset, size);
80871c3c760a83123ee0b3127b8c65c6394ce541c50reed}
80971c3c760a83123ee0b3127b8c65c6394ce541c50reed
810f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
811f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    size_t keyLen = fWriter.WriteStringSize(key);
812f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    size_t valueLen = fWriter.WriteDataSize(value);
813f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
814f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
815f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
816f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    this->addRect(rect);
817f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    fWriter.writeString(key);
818f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    fWriter.writeData(value);
819f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    this->validate(initialOffset, size);
820f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
821f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
82382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
82422b2af1dc42c0b95fe93b9a951313efe438e54cdreedtemplate <typename T> int find_or_append_uniqueID(SkTDArray<const T*>& array, const T* obj) {
82522b2af1dc42c0b95fe93b9a951313efe438e54cdreed    int index = array.select([&](const T* elem) {
82622b2af1dc42c0b95fe93b9a951313efe438e54cdreed        return elem->uniqueID() == obj->uniqueID();
82722b2af1dc42c0b95fe93b9a951313efe438e54cdreed    });
82822b2af1dc42c0b95fe93b9a951313efe438e54cdreed    if (index < 0) {
82922b2af1dc42c0b95fe93b9a951313efe438e54cdreed        index = array.count();
83022b2af1dc42c0b95fe93b9a951313efe438e54cdreed        *array.append() = SkRef(obj);
83122b2af1dc42c0b95fe93b9a951313efe438e54cdreed    }
83222b2af1dc42c0b95fe93b9a951313efe438e54cdreed    return index;
83322b2af1dc42c0b95fe93b9a951313efe438e54cdreed}
83422b2af1dc42c0b95fe93b9a951313efe438e54cdreed
835e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
83696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
83776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
83876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
839871872f3f247f6b699617f6d9ef50ef5da6fbe74reedvoid SkPictureRecord::addImage(const SkImage* image) {
84022b2af1dc42c0b95fe93b9a951313efe438e54cdreed    // convention for images is 0-based index
84122b2af1dc42c0b95fe93b9a951313efe438e54cdreed    this->addInt(find_or_append_uniqueID(fImageRefs, image));
842871872f3f247f6b699617f6d9ef50ef5da6fbe74reed}
843871872f3f247f6b699617f6d9ef50ef5da6fbe74reed
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addMatrix(const SkMatrix& matrix) {
845fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    fWriter.writeMatrix(matrix);
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
84846616af01b412ea984a516fda1ed8ec08e689f29mtkleinvoid SkPictureRecord::addPaintPtr(const SkPaint* paint) {
849afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onAddPaintPtr(paint);
850e2cb12a82ad924f7b134a9459b190213485c6a50commit-bot@chromium.org
85146616af01b412ea984a516fda1ed8ec08e689f29mtklein    if (paint) {
852a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein        fPaints.push_back(*paint);
853a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein        this->addInt(fPaints.count());
85446616af01b412ea984a516fda1ed8ec08e689f29mtklein    } else {
85546616af01b412ea984a516fda1ed8ec08e689f29mtklein        this->addInt(0);
85646616af01b412ea984a516fda1ed8ec08e689f29mtklein    }
857cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org}
858cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org
8595a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comint SkPictureRecord::addPathToHeap(const SkPath& path) {
860c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    if (int* n = fPaths.find(path)) {
861c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein        return *n;
862c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    }
863c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    int n = fPaths.count() + 1;  // 0 is reserved for null / error.
864c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    fPaths.set(path, n);
865c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    return n;
8665a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
8675a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
8685a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comvoid SkPictureRecord::addPath(const SkPath& path) {
869cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(this->addPathToHeap(path));
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
872b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkPictureRecord::addPatch(const SkPoint cubics[12]) {
873b3c9d1c33caf325aada244204215eb790c228c12dandov    fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
874963137b75c0a1fe91f35e9826742f36309f5e65ddandov}
875963137b75c0a1fe91f35e9826742f36309f5e65ddandov
8769b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkPictureRecord::addPicture(const SkPicture* picture) {
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // follow the convention of recording a 1-based index
87822b2af1dc42c0b95fe93b9a951313efe438e54cdreed    this->addInt(find_or_append_uniqueID(fPictureRefs, picture) + 1);
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88195416f477d2ca264f2fb065455e95778a2289a1dmsarettvoid SkPictureRecord::addDrawable(SkDrawable* drawable) {
88295416f477d2ca264f2fb065455e95778a2289a1dmsarett    int index = fDrawableRefs.find(drawable);
88395416f477d2ca264f2fb065455e95778a2289a1dmsarett    if (index < 0) {    // not found
88495416f477d2ca264f2fb065455e95778a2289a1dmsarett        index = fDrawableRefs.count();
88595416f477d2ca264f2fb065455e95778a2289a1dmsarett        *fDrawableRefs.append() = drawable;
88695416f477d2ca264f2fb065455e95778a2289a1dmsarett        drawable->ref();
88795416f477d2ca264f2fb065455e95778a2289a1dmsarett    }
88895416f477d2ca264f2fb065455e95778a2289a1dmsarett    // follow the convention of recording a 1-based index
88995416f477d2ca264f2fb065455e95778a2289a1dmsarett    this->addInt(index + 1);
89095416f477d2ca264f2fb065455e95778a2289a1dmsarett}
89195416f477d2ca264f2fb065455e95778a2289a1dmsarett
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addPoint(const SkPoint& point) {
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writePoint(point);
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
89582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addPoints(const SkPoint pts[], int count) {
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(pts, count * sizeof(SkPoint));
8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
90068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.orgvoid SkPictureRecord::addNoOp() {
90168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    size_t size = kUInt32Size; // op
90268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    this->addDraw(NOOP, &size);
90368250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org}
90468250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRect(const SkRect& rect) {
9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeRect(rect);
9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRectPtr(const SkRect* rect) {
91096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (fWriter.writeBool(rect != nullptr)) {
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWriter.writeRect(*rect);
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
915f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.comvoid SkPictureRecord::addIRect(const SkIRect& rect) {
916f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com    fWriter.write(&rect, sizeof(rect));
917f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com}
918f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addIRectPtr(const SkIRect* rect) {
92096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (fWriter.writeBool(rect != nullptr)) {
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9254ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkPictureRecord::addRRect(const SkRRect& rrect) {
9264ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    fWriter.writeRRect(rrect);
9274ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
9284ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRegion(const SkRegion& region) {
930fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    fWriter.writeRegion(region);
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addText(const void* text, size_t byteLength) {
934afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawText();
935dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    addInt(SkToInt(byteLength));
9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writePad(text, byteLength);
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
93922b2af1dc42c0b95fe93b9a951313efe438e54cdreedvoid SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
940b7425173f96e93b090787e2386ba5f022b6c2869fmalita    // follow the convention of recording a 1-based index
94122b2af1dc42c0b95fe93b9a951313efe438e54cdreed    this->addInt(find_or_append_uniqueID(fTextBlobRefs, blob) + 1);
942b7425173f96e93b090787e2386ba5f022b6c2869fmalita}
943b7425173f96e93b090787e2386ba5f022b6c2869fmalita
944e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkPictureRecord::addVertices(const SkVertices* vertices) {
945e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    // follow the convention of recording a 1-based index
946e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->addInt(find_or_append_uniqueID(fVerticesRefs, vertices) + 1);
947e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed}
948e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
950