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"
9d575eed3549dcb943ae84cfeb0a31463d6edad34junov@chromium.org#include "SkDevice.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"
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();
37b7425173f96e93b090787e2386ba5f022b6c2869fmalita    fTextBlobRefs.unrefAll();
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
425f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitavoid SkPictureRecord::willSave() {
43ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // record the offset to us, making it non-positive to distinguish a save
44ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // from a clip entry.
454469938e92d779dff05e745559e67907bbf21e78reed@google.com    fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
465f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    this->recordSave();
47e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
485f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    this->INHERITED::willSave();
495a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
5011f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
515f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitavoid SkPictureRecord::recordSave() {
52c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onSave();
53c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
545f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    // op only
55512f3e3b2592097a39bde9331829b38d16c0f85dreed    size_t size = sizeof(kUInt32Size);
568b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SAVE, &size);
5782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
588b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
614960eeec4a1f2a772654883d7f3615d47bcd5dc3reedSkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
62ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // record the offset to us, making it non-positive to distinguish a save
63ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // from a clip entry.
644469938e92d779dff05e745559e67907bbf21e78reed@google.com    fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
654960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    this->recordSaveLayer(rec);
6611f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
674960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    (void)this->INHERITED::getSaveLayerStrategy(rec);
68e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    /*  No need for a (potentially very big) layer which we don't actually need
695a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        at this time (and may not be able to afford since during record our
705a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        clip starts out the size of the picture, which is often much larger
715a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        than the size of the actual device we'll use during playback).
725a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com     */
73e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    return kNoLayer_SaveLayerStrategy;
745a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
755a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
764960eeec4a1f2a772654883d7f3615d47bcd5dc3reedvoid SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
77c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onSaveLayer();
78c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
79bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    // op + flatflags
80dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
81bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    uint32_t flatFlags = 0;
82bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed
834960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (rec.fBounds) {
84bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_BOUNDS;
85bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(*rec.fBounds);
86bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
87bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (rec.fPaint) {
88bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_PAINT;
89bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(uint32_t); // index
90bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
91bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (rec.fBackdrop) {
92bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_BACKDROP;
93bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(uint32_t); // (paint) index
94bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
95bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (rec.fSaveLayerFlags) {
96bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        flatFlags |= SAVELAYERREC_HAS_FLAGS;
97bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        size += sizeof(uint32_t);
982ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
100bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
101bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    this->addInt(flatFlags);
102bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
103bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addRect(*rec.fBounds);
104bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
105bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_PAINT) {
106bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addPaintPtr(rec.fPaint);
107bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
108bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
109bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        // overkill, but we didn't already track single flattenables, so using a paint for that
110bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        SkPaint paint;
111bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        paint.setImageFilter(const_cast<SkImageFilter*>(rec.fBackdrop));
112bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addPaint(paint);
113bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
114bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
115bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        this->addInt(rec.fSaveLayerFlags);
116bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    }
1178b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
120210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org#ifdef SK_DEBUG
121210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org/*
1222ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com * Read the op code from 'offset' in 'writer' and extract the size too.
1232ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com */
124dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgstatic DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
125536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    uint32_t peek = writer->readTAt<uint32_t>(offset);
1262ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
1272ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    uint32_t op;
128c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org    UNPACK_8_24(peek, op, *size);
1292ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    if (MASK_24 == *size) {
1302ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        // size required its own slot right after the op code
131536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
1322ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
1332ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    return (DrawType) op;
134ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com}
13546616af01b412ea984a516fda1ed8ec08e689f29mtklein#endif//SK_DEBUG
1364b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org
137e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgvoid SkPictureRecord::willRestore() {
1384e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org#if 0
1394e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    SkASSERT(fRestoreOffsetStack.count() > 1);
1404e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org#endif
1414e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org
142b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    // check for underflow
143b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    if (fRestoreOffsetStack.count() == 0) {
144b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com        return;
145b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    }
146b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com
14746616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->recordRestore();
148ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com
149b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    fRestoreOffsetStack.pop();
15032a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com
151e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    this->INHERITED::willRestore();
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
154105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.comvoid SkPictureRecord::recordRestore(bool fillInSkips) {
155c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onRestore();
156c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
157105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    if (fillInSkips) {
158105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
159105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
160dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
161dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t initialOffset = this->addDraw(RESTORE, &size);
1625a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    this->validate(initialOffset, size);
1635a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
1645a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
165d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.orgvoid SkPictureRecord::recordTranslate(const SkMatrix& m) {
166d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
167d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
1682ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + dx + dy
169dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
1708b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(TRANSLATE, &size);
171d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getTranslateX());
172d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getTranslateY());
1738b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
176d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.orgvoid SkPictureRecord::recordScale(const SkMatrix& m) {
177d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkASSERT(SkMatrix::kScale_Mask == m.getType());
178105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
1792ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + sx + sy
180dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
1818b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SCALE, &size);
182d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getScaleX());
183d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getScaleY());
1848b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkPictureRecord::didConcat(const SkMatrix& matrix) {
188d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    switch (matrix.getType()) {
189d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        case SkMatrix::kTranslate_Mask:
190d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordTranslate(matrix);
191d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
192d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        case SkMatrix::kScale_Mask:
193d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordScale(matrix);
194d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
195d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        default:
196d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordConcat(matrix);
197d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
198d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
19944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->INHERITED::didConcat(matrix);
2005a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
2015a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
2025a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comvoid SkPictureRecord::recordConcat(const SkMatrix& matrix) {
2034469938e92d779dff05e745559e67907bbf21e78reed@google.com    this->validate(fWriter.bytesWritten(), 0);
204fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + matrix
20596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
2068b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CONCAT, &size);
207cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(matrix);
2088b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
2124469938e92d779dff05e745559e67907bbf21e78reed@google.com    this->validate(fWriter.bytesWritten(), 0);
213fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + matrix
21496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
2158b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SET_MATRIX, &size);
216cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(matrix);
2178b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
21844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->INHERITED::didSetMatrix(matrix);
2196e073b9e2b70d6bbf8a06050fff1364827204f08reed@android.com}
2206e073b9e2b70d6bbf8a06050fff1364827204f08reed@android.com
22145482d1d2b97de185df137a1db40cbe5a62313a5reed@google.comstatic bool regionOpExpands(SkRegion::Op op) {
22245482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    switch (op) {
22345482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kUnion_Op:
22445482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kXOR_Op:
22545482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kReverseDifference_Op:
22645482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kReplace_Op:
22745482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return true;
22845482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kIntersect_Op:
22945482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kDifference_Op:
23045482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return false;
23145482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        default:
2320c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown region op");
23345482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return false;
23445482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    }
23545482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com}
23645482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com
237e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.comvoid SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
238ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    int32_t offset = fRestoreOffsetStack.top();
239ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    while (offset > 0) {
240536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        uint32_t peek = fWriter.readTAt<uint32_t>(offset);
241536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        fWriter.overwriteTAt(offset, restoreOffset);
242c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org        offset = peek;
243e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org    }
24411f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
245ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com#ifdef SK_DEBUG
2462ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    // offset of 0 has been disabled, so we skip it
2472ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (offset > 0) {
2482ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // assert that the final offset value points to a save verb
2492ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        uint32_t opSize;
2502ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
2514960eeec4a1f2a772654883d7f3615d47bcd5dc3reed        SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
252bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
253bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
2542ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
255ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com#endif
256e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org}
257e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org
258d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.comvoid SkPictureRecord::beginRecording() {
259d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // we have to call this *after* our constructor, to ensure that it gets
260d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // recorded. This is balanced by restoreToCount() call from endRecording,
261d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // which in-turn calls our overridden restore(), so those get recorded too.
262091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org    fInitialSaveCount = this->save();
263d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com}
264d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com
265a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.orgvoid SkPictureRecord::endRecording() {
2664e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    SkASSERT(kNoInitialSave != fInitialSaveCount);
2674e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    this->restoreToCount(fInitialSaveCount);
268a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.org}
269a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.org
270dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgsize_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
27121b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com    if (fRestoreOffsetStack.isEmpty()) {
2725a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        return -1;
27321b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com    }
27421b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com
275d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // The RestoreOffset field is initially filled with a placeholder
276d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // value that points to the offset of the previous RestoreOffset
277d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // in the current stack level, thus forming a linked list so that
278d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // the restore offsets can be filled in when the corresponding
279d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // restore command is recorded.
280d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    int32_t prevOffset = fRestoreOffsetStack.top();
281d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com
28245482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    if (regionOpExpands(op)) {
28345482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // Run back through any previous clip ops, and mark their offset to
28445482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // be 0, disabling their ability to trigger a jump-to-restore, otherwise
28545482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // they could hide this clips ability to expand the clip (i.e. go from
28645482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // empty to non-empty).
287cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com        this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
288d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com
289d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        // Reset the pointer back to the previous clip so that subsequent
290d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        // restores don't overwrite the offsets we just cleared.
291d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        prevOffset = 0;
29245482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    }
29374b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
2944469938e92d779dff05e745559e67907bbf21e78reed@google.com    size_t offset = fWriter.bytesWritten();
295cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(prevOffset);
296dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    fRestoreOffsetStack.top() = SkToU32(offset);
2975a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
29845482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com}
29945482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com
3008f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
3018f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
3028f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->INHERITED::onClipRect(rect, op, edgeStyle);
3035a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3045a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
305dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgsize_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
306f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // id + rect + clip params
307dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
3084310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
309f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
310f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
311f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
312f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3138b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_RECT, &size);
314cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(rect);
315cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
316dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = this->recordRestoreOffsetPlaceholder(op);
317306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
3188b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3195a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
32068d61ed83ec7b6e98e9623c2f5c9e7b1a32d25bbreed@google.com}
32168d61ed83ec7b6e98e9623c2f5c9e7b1a32d25bbreed@google.com
3228f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
3238f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
324d954498c01ccf0417feacf89e45d0c62a06a813breed    this->INHERITED::onClipRRect(rrect, op, edgeStyle);
3255a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3265a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
327dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgsize_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
328f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // op + rrect + clip params
329dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
3304310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
331f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
332f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
333f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
334f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3358b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
336cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRRect(rrect);
337cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
338dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = recordRestoreOffsetPlaceholder(op);
3398b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3405a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
3414ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
3424ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
3438f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
3445a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    int pathID = this->addPathToHeap(path);
3458f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
346d954498c01ccf0417feacf89e45d0c62a06a813breed    this->INHERITED::onClipPath(path, op, edgeStyle);
3475a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3485a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
349dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgsize_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
350f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // op + path index + clip params
351dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size;
3524310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
353f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
354f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
355f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
356f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3578b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_PATH, &size);
358cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(pathID);
359cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
360dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = recordRestoreOffsetPlaceholder(op);
3618b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3625a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
3665a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    this->recordClipRegion(region, op);
3678f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->INHERITED::onClipRegion(region, op);
3685a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3695a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
370dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgsize_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
371fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + clip params + region
37296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
3734310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
374f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
375f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
376f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
377f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3788b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_REGION, &size);
379cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRegion(region);
380cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, false));
381dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = this->recordRestoreOffsetPlaceholder(op);
38282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3838b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3845a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
38741af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPaint(const SkPaint& paint) {
3882ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index
389dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
3908b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
391cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
3928b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
39541af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
39641af966ab338e95eee81ab618ab28195075338f7reed                                   const SkPaint& paint) {
397afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawPoints(count, paint);
398105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
3992ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + mode + count + point data
400dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
4018b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
402cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
403afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw
404cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(mode);
405dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    this->addInt(SkToInt(count));
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(pts, count * sizeof(SkPoint));
4078b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
41041af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
4112ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + rect
412dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + sizeof(oval);
4138b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
414cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
415cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(oval);
4168b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4174ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
4184ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
41941af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
4202ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + rect
421dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + sizeof(rect);
4228b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_RECT, &size);
423cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
424cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(rect);
4258b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42841af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
42946616af01b412ea984a516fda1ed8ec08e689f29mtklein    // op + paint index + rrect
43046616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
43146616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
43246616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
43346616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addRRect(rrect);
43446616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->validate(initialOffset, size);
4354ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
4364ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
437ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
438ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                                   const SkPaint& paint) {
439ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // op + paint index + rrects
440dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
441dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
442ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addPaint(paint);
443ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addRRect(outer);
444ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addRRect(inner);
445ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->validate(initialOffset, size);
446ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
447ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
44841af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
449afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawPath(path, paint);
450e2cb12a82ad924f7b134a9459b190213485c6a50commit-bot@chromium.org
4512ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + path index
452dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size;
4538b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_PATH, &size);
454cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
455cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPath(path);
4568b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45941af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
46041af966ab338e95eee81ab618ab28195075338f7reed                                   const SkPaint* paint) {
4612ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + bitmap index + left + top
462dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
4638b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
464cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaintPtr(paint);
465f6a5afb66b661c884cd308577431b7abf025b182commit-bot@chromium.org    this->addBitmap(bitmap);
466cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(left);
467cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(top);
4688b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
47141af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
472562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                       const SkPaint* paint, SrcRectConstraint constraint) {
473eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org    // id + paint index + bitmap index + bool for 'src' + flags
474dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 5 * kUInt32Size;
47549f085dddff10473b6ebf832a974288300224e60bsalomon    if (src) {
4762ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        size += sizeof(*src);   // + rect
4772ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
4782ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    size += sizeof(dst);        // + rect
4792ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
480a5517e2b190a8083b38964972b031c13e99f1012reed    size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT, &size);
481cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaintPtr(paint);
482f6a5afb66b661c884cd308577431b7abf025b182commit-bot@chromium.org    this->addBitmap(bitmap);
483cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRectPtr(src);  // may be null
484cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(dst);
485a5517e2b190a8083b38964972b031c13e99f1012reed    this->addInt(constraint);
4868b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
489a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
490a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                  const SkPaint* paint) {
491871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    // op + paint_index + image_index + x + y
492871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
493871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
494871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addPaintPtr(paint);
495871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addImage(image);
496871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addScalar(x);
497871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addScalar(y);
498871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->validate(initialOffset, size);
499a85d4d0814818e4ddabb9237da209d61d6cd5854reed}
500a85d4d0814818e4ddabb9237da209d61d6cd5854reed
501a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
502562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                      const SkPaint* paint, SrcRectConstraint constraint) {
503a5517e2b190a8083b38964972b031c13e99f1012reed    // id + paint_index + image_index + bool_for_src + constraint
504a5517e2b190a8083b38964972b031c13e99f1012reed    size_t size = 5 * kUInt32Size;
505871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    if (src) {
506871872f3f247f6b699617f6d9ef50ef5da6fbe74reed        size += sizeof(*src);   // + rect
507a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
508871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size += sizeof(dst);        // + rect
509c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein
510871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
511871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addPaintPtr(paint);
512871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addImage(image);
513871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addRectPtr(src);  // may be null
514871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->addRect(dst);
515a5517e2b190a8083b38964972b031c13e99f1012reed    this->addInt(constraint);
516871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    this->validate(initialOffset, size);
517a85d4d0814818e4ddabb9237da209d61d6cd5854reed}
518a85d4d0814818e4ddabb9237da209d61d6cd5854reed
5194c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
5204c21dc5ddf3b482293ed34eead876d8d61a662c3reed                                      const SkPaint* paint) {
5214c21dc5ddf3b482293ed34eead876d8d61a662c3reed    // id + paint_index + image_index + center + dst
5224c21dc5ddf3b482293ed34eead876d8d61a662c3reed    size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
523c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein
5244c21dc5ddf3b482293ed34eead876d8d61a662c3reed    size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
5254c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addPaintPtr(paint);
5264c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addImage(img);
5274c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addIRect(center);
5284c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->addRect(dst);
5294c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->validate(initialOffset, size);
5304c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
5314c21dc5ddf3b482293ed34eead876d8d61a662c3reed
53241af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
53341af966ab338e95eee81ab618ab28195075338f7reed                                       const SkRect& dst, const SkPaint* paint) {
5342ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + bitmap id + center + dst rect
535dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
5368b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
537cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaintPtr(paint);
538f6a5afb66b661c884cd308577431b7abf025b182commit-bot@chromium.org    this->addBitmap(bitmap);
539cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addIRect(center);
540cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(dst);
5418b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
542f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com}
543f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com
544e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
545e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                 const SkPaint& paint) {
5462ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + length + 'length' worth of chars + x + y
547dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
5482ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
54946616af01b412ea984a516fda1ed8ec08e689f29mtklein    DrawType op = DRAW_TEXT;
5508b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(op, &size);
55146616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
552cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
553cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(x);
554cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(y);
5558b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
558e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
559e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                    const SkPaint& paint) {
560dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    int points = paint.countText(text, byteLength);
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56246616af01b412ea984a516fda1ed8ec08e689f29mtklein    // op + paint index + length + 'length' worth of data + num points + x&y point data
56346616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56546616af01b412ea984a516fda1ed8ec08e689f29mtklein    DrawType op = DRAW_POS_TEXT;
5662ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
5678b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(op, &size);
56846616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
569cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
570cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(points);
57146616af01b412ea984a516fda1ed8ec08e689f29mtklein    fWriter.writeMul4(pos, points * sizeof(SkPoint));
5728b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
575e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
576e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                     SkScalar constY, const SkPaint& paint) {
577dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    int points = paint.countText(text, byteLength);
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5792ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + length + 'length' worth of data + num points
580dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
5812ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // + y + the actual points
5822ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    size += 1 * kUInt32Size + points * sizeof(SkScalar);
583cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org
58446616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
58546616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
586cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
587cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(points);
588cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(constY);
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(xpos, points * sizeof(SkScalar));
5908b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
593e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
594e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                       const SkMatrix* matrix, const SkPaint& paint) {
595fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + paint index + length + 'length' worth of data + path index + matrix
596fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
59796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
5988b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
599cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
600cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
601cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPath(path);
602cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(m);
6038b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
606b7425173f96e93b090787e2386ba5f022b6c2869fmalitavoid SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
607b7425173f96e93b090787e2386ba5f022b6c2869fmalita                                     const SkPaint& paint) {
608b7425173f96e93b090787e2386ba5f022b6c2869fmalita
609b7425173f96e93b090787e2386ba5f022b6c2869fmalita    // op + paint index + blob index + x/y
610b7425173f96e93b090787e2386ba5f022b6c2869fmalita    size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
611b7425173f96e93b090787e2386ba5f022b6c2869fmalita    size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
612b7425173f96e93b090787e2386ba5f022b6c2869fmalita
613b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addPaint(paint);
614b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addTextBlob(blob);
615b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addScalar(x);
616b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addScalar(y);
617b7425173f96e93b090787e2386ba5f022b6c2869fmalita
618b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->validate(initialOffset, size);
619b7425173f96e93b090787e2386ba5f022b6c2869fmalita}
620b7425173f96e93b090787e2386ba5f022b6c2869fmalita
621d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
622d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                                    const SkPaint* paint) {
6232ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + picture index
624dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
625d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    size_t initialOffset;
626d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
62796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == matrix && nullptr == paint) {
628d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        initialOffset = this->addDraw(DRAW_PICTURE, &size);
629d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        this->addPicture(picture);
630d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    } else {
631d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
63296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        size += m.writeToMemory(nullptr) + kUInt32Size;    // matrix + paint
633d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
634d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        this->addPaintPtr(paint);
6359f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita        this->addMatrix(m);
6369f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita        this->addPicture(picture);
637d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
6388b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
64141af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
64241af966ab338e95eee81ab618ab28195075338f7reed                                     const SkPoint vertices[], const SkPoint texs[],
64341af966ab338e95eee81ab618ab28195075338f7reed                                     const SkColor colors[], SkXfermode* xfer,
64441af966ab338e95eee81ab618ab28195075338f7reed                                     const uint16_t indices[], int indexCount,
64541af966ab338e95eee81ab618ab28195075338f7reed                                     const SkPaint& paint) {
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t flags = 0;
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (texs) {
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= DRAW_VERTICES_HAS_TEXS;
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (colors) {
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= DRAW_VERTICES_HAS_COLORS;
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (indexCount > 0) {
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= DRAW_VERTICES_HAS_INDICES;
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
65649f085dddff10473b6ebf832a974288300224e60bsalomon    if (xfer) {
65785e143c33c214e54187aa28146aa7666961a0d17reed@google.com        SkXfermode::Mode mode;
65885e143c33c214e54187aa28146aa7666961a0d17reed@google.com        if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
65985e143c33c214e54187aa28146aa7666961a0d17reed@google.com            flags |= DRAW_VERTICES_HAS_XFER;
66085e143c33c214e54187aa28146aa7666961a0d17reed@google.com        }
66185e143c33c214e54187aa28146aa7666961a0d17reed@google.com    }
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6632ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + flags + vmode + vCount + vertices
664dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
6652ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    if (flags & DRAW_VERTICES_HAS_TEXS) {
6662ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        size += vertexCount * sizeof(SkPoint);  // + uvs
6672ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
6682ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    if (flags & DRAW_VERTICES_HAS_COLORS) {
6692ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        size += vertexCount * sizeof(SkColor);  // + vert colors
6702ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
6712ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    if (flags & DRAW_VERTICES_HAS_INDICES) {
6722ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        // + num indices + indices
6732ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
6742ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
67585e143c33c214e54187aa28146aa7666961a0d17reed@google.com    if (flags & DRAW_VERTICES_HAS_XFER) {
67685e143c33c214e54187aa28146aa7666961a0d17reed@google.com        size += kUInt32Size;    // mode enum
67785e143c33c214e54187aa28146aa7666961a0d17reed@google.com    }
6782ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
6798b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
680cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
681cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(flags);
682cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(vmode);
683cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(vertexCount);
684cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPoints(vertices, vertexCount);
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (flags & DRAW_VERTICES_HAS_TEXS) {
686cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com        this->addPoints(texs, vertexCount);
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (flags & DRAW_VERTICES_HAS_COLORS) {
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (flags & DRAW_VERTICES_HAS_INDICES) {
692cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com        this->addInt(indexCount);
6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWriter.writePad(indices, indexCount * sizeof(uint16_t));
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
69585e143c33c214e54187aa28146aa7666961a0d17reed@google.com    if (flags & DRAW_VERTICES_HAS_XFER) {
69685e143c33c214e54187aa28146aa7666961a0d17reed@google.com        SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
69785e143c33c214e54187aa28146aa7666961a0d17reed@google.com        (void)xfer->asMode(&mode);
698cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com        this->addInt(mode);
69985e143c33c214e54187aa28146aa7666961a0d17reed@google.com    }
7008b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
703b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
704b3c9d1c33caf325aada244204215eb790c228c12dandov                                  const SkPoint texCoords[4], SkXfermode* xmode,
705b3c9d1c33caf325aada244204215eb790c228c12dandov                                  const SkPaint& paint) {
706b3c9d1c33caf325aada244204215eb790c228c12dandov    // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
707b3c9d1c33caf325aada244204215eb790c228c12dandov    size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
708b3c9d1c33caf325aada244204215eb790c228c12dandov    uint32_t flag = 0;
70949f085dddff10473b6ebf832a974288300224e60bsalomon    if (colors) {
710b3c9d1c33caf325aada244204215eb790c228c12dandov        flag |= DRAW_VERTICES_HAS_COLORS;
711b3c9d1c33caf325aada244204215eb790c228c12dandov        size += SkPatchUtils::kNumCorners * sizeof(SkColor);
712b3c9d1c33caf325aada244204215eb790c228c12dandov    }
71349f085dddff10473b6ebf832a974288300224e60bsalomon    if (texCoords) {
714b3c9d1c33caf325aada244204215eb790c228c12dandov        flag |= DRAW_VERTICES_HAS_TEXS;
715b3c9d1c33caf325aada244204215eb790c228c12dandov        size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
716b3c9d1c33caf325aada244204215eb790c228c12dandov    }
71749f085dddff10473b6ebf832a974288300224e60bsalomon    if (xmode) {
718b3c9d1c33caf325aada244204215eb790c228c12dandov        SkXfermode::Mode mode;
719b3c9d1c33caf325aada244204215eb790c228c12dandov        if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
720b3c9d1c33caf325aada244204215eb790c228c12dandov            flag |= DRAW_VERTICES_HAS_XFER;
721b3c9d1c33caf325aada244204215eb790c228c12dandov            size += kUInt32Size;
722b3c9d1c33caf325aada244204215eb790c228c12dandov        }
723b3c9d1c33caf325aada244204215eb790c228c12dandov    }
72446616af01b412ea984a516fda1ed8ec08e689f29mtklein
725963137b75c0a1fe91f35e9826742f36309f5e65ddandov    size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
726963137b75c0a1fe91f35e9826742f36309f5e65ddandov    this->addPaint(paint);
727b3c9d1c33caf325aada244204215eb790c228c12dandov    this->addPatch(cubics);
728b3c9d1c33caf325aada244204215eb790c228c12dandov    this->addInt(flag);
72946616af01b412ea984a516fda1ed8ec08e689f29mtklein
730b3c9d1c33caf325aada244204215eb790c228c12dandov    // write optional parameters
73149f085dddff10473b6ebf832a974288300224e60bsalomon    if (colors) {
732b3c9d1c33caf325aada244204215eb790c228c12dandov        fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
733b3c9d1c33caf325aada244204215eb790c228c12dandov    }
73449f085dddff10473b6ebf832a974288300224e60bsalomon    if (texCoords) {
735b3c9d1c33caf325aada244204215eb790c228c12dandov        fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
736b3c9d1c33caf325aada244204215eb790c228c12dandov    }
737b3c9d1c33caf325aada244204215eb790c228c12dandov    if (flag & DRAW_VERTICES_HAS_XFER) {
738b3c9d1c33caf325aada244204215eb790c228c12dandov        SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
739b3c9d1c33caf325aada244204215eb790c228c12dandov        xmode->asMode(&mode);
740b3c9d1c33caf325aada244204215eb790c228c12dandov        this->addInt(mode);
741b3c9d1c33caf325aada244204215eb790c228c12dandov    }
742963137b75c0a1fe91f35e9826742f36309f5e65ddandov    this->validate(initialOffset, size);
743963137b75c0a1fe91f35e9826742f36309f5e65ddandov}
744963137b75c0a1fe91f35e9826742f36309f5e65ddandov
74571c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
74671c3c760a83123ee0b3127b8c65c6394ce541c50reed                                  const SkColor colors[], int count, SkXfermode::Mode mode,
74771c3c760a83123ee0b3127b8c65c6394ce541c50reed                                  const SkRect* cull, const SkPaint* paint) {
74871c3c760a83123ee0b3127b8c65c6394ce541c50reed    // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
74971c3c760a83123ee0b3127b8c65c6394ce541c50reed    size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
75071c3c760a83123ee0b3127b8c65c6394ce541c50reed    uint32_t flags = 0;
75171c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (colors) {
75271c3c760a83123ee0b3127b8c65c6394ce541c50reed        flags |= DRAW_ATLAS_HAS_COLORS;
75371c3c760a83123ee0b3127b8c65c6394ce541c50reed        size += count * sizeof(SkColor);
75471c3c760a83123ee0b3127b8c65c6394ce541c50reed        size += sizeof(uint32_t);   // xfermode::mode
75571c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
75671c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull) {
75771c3c760a83123ee0b3127b8c65c6394ce541c50reed        flags |= DRAW_ATLAS_HAS_CULL;
75871c3c760a83123ee0b3127b8c65c6394ce541c50reed        size += sizeof(SkRect);
75971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
760c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein
76171c3c760a83123ee0b3127b8c65c6394ce541c50reed    size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
76271c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addPaintPtr(paint);
76371c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addImage(atlas);
76471c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addInt(flags);
76571c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->addInt(count);
76671c3c760a83123ee0b3127b8c65c6394ce541c50reed    fWriter.write(xform, count * sizeof(SkRSXform));
76771c3c760a83123ee0b3127b8c65c6394ce541c50reed    fWriter.write(tex, count * sizeof(SkRect));
76871c3c760a83123ee0b3127b8c65c6394ce541c50reed
76971c3c760a83123ee0b3127b8c65c6394ce541c50reed    // write optional parameters
77071c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (colors) {
77171c3c760a83123ee0b3127b8c65c6394ce541c50reed        fWriter.write(colors, count * sizeof(SkColor));
77271c3c760a83123ee0b3127b8c65c6394ce541c50reed        this->addInt(mode);
77371c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
77471c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull) {
77571c3c760a83123ee0b3127b8c65c6394ce541c50reed        fWriter.write(cull, sizeof(SkRect));
77671c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
77771c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->validate(initialOffset, size);
77871c3c760a83123ee0b3127b8c65c6394ce541c50reed}
77971c3c760a83123ee0b3127b8c65c6394ce541c50reed
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
78182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
7824a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
78396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
78476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
78576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
786e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein// If we already have a stored, can we reuse it instead of also storing b?
787e069400cabd0edd3db52bbf1958063d3ed12ef28mtkleinstatic bool equivalent(const SkBitmap& a, const SkBitmap& b) {
788e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
789e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
790e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        // but it sure makes things easier to reason about below.
791e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return false;
792e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
793e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    if (a.pixelRef() == b.pixelRef()) {
794e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return true;  // Same shape and same pixels -> same bitmap.
795e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
796e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein
797e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
798e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    if (!a.pixelRef() || !b.pixelRef()) {
799e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return false;
800e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
801e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein
802e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
803e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
804e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein                         encB(b.pixelRef()->refEncodedData());
805e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    if (encA && encB) {
806e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return encA->equals(encB);
807e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    } else if (encA || encB) {
808e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return false;   // One has encoded data but the other does not.
809e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
810e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein
811e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // As a last resort, we have to look at the pixels.  This will read back textures.
812e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    SkAutoLockPixels al(a), bl(b);
813e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    const char* ap = (const char*)a.getPixels();
814e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    const char* bp = (const char*)b.getPixels();
815e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    if (ap && bp) {
816e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        // We check row by row; row bytes might differ.
817e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        SkASSERT(a.info() == b.info());          // We checked this above.
818e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        SkASSERT(a.info().bytesPerPixel() > 0);  // If we have pixelRefs, this better be true.
819e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        const SkImageInfo info = a.info();
820e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        const size_t bytesToCompare = info.width() * info.bytesPerPixel();
821e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        for (int row = 0; row < info.height(); row++) {
822e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            if (0 != memcmp(ap, bp, bytesToCompare)) {
823e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein                return false;
824e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            }
825e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            ap += a.rowBytes();
826e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            bp += b.rowBytes();
827e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        }
828e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return true;
829e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
830e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    return false;  // Couldn't get pixels for both bitmaps.
831e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein}
832e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein
833e069400cabd0edd3db52bbf1958063d3ed12ef28mtkleinvoid SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
834e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // First see if we already have this bitmap.  This deduplication should really
835e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // only be important for our tests, where bitmaps tend not to be tagged immutable.
836e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // In Chrome (and hopefully Android?) they're typically immutable.
837e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    for (int i = 0; i < fBitmaps.count(); i++) {
838e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        if (equivalent(fBitmaps[i], bitmap)) {
839e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            this->addInt(i);  // Unlike the rest, bitmap indices are 0-based.
840e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            return;
841e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        }
842e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
843e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // Don't have it.  We'll add it to our list, making sure it's tagged as immutable.
84471a236370792416b367a7d2d6b8e471b06b331cdmtklein    if (bitmap.isImmutable()) {
845e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        // Shallow copies of bitmaps are cheap, so immutable == fast.
84671a236370792416b367a7d2d6b8e471b06b331cdmtklein        fBitmaps.push_back(bitmap);
84771a236370792416b367a7d2d6b8e471b06b331cdmtklein    } else {
848e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
84971a236370792416b367a7d2d6b8e471b06b331cdmtklein        SkBitmap copy;
85071a236370792416b367a7d2d6b8e471b06b331cdmtklein        bitmap.copyTo(&copy);
85171a236370792416b367a7d2d6b8e471b06b331cdmtklein        copy.setImmutable();
85271a236370792416b367a7d2d6b8e471b06b331cdmtklein        fBitmaps.push_back(copy);
85371a236370792416b367a7d2d6b8e471b06b331cdmtklein    }
854e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    this->addInt(fBitmaps.count()-1);  // Remember, 0-based.
8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
857871872f3f247f6b699617f6d9ef50ef5da6fbe74reedvoid SkPictureRecord::addImage(const SkImage* image) {
858871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    int index = fImageRefs.find(image);
859871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    if (index >= 0) {
860871872f3f247f6b699617f6d9ef50ef5da6fbe74reed        this->addInt(index);
861871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    } else {
862871872f3f247f6b699617f6d9ef50ef5da6fbe74reed        *fImageRefs.append() = SkRef(image);
863871872f3f247f6b699617f6d9ef50ef5da6fbe74reed        this->addInt(fImageRefs.count()-1);
864871872f3f247f6b699617f6d9ef50ef5da6fbe74reed    }
865871872f3f247f6b699617f6d9ef50ef5da6fbe74reed}
866871872f3f247f6b699617f6d9ef50ef5da6fbe74reed
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addMatrix(const SkMatrix& matrix) {
868fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    fWriter.writeMatrix(matrix);
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
87146616af01b412ea984a516fda1ed8ec08e689f29mtkleinvoid SkPictureRecord::addPaintPtr(const SkPaint* paint) {
872afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onAddPaintPtr(paint);
873e2cb12a82ad924f7b134a9459b190213485c6a50commit-bot@chromium.org
87446616af01b412ea984a516fda1ed8ec08e689f29mtklein    if (paint) {
875a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein        fPaints.push_back(*paint);
876a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein        this->addInt(fPaints.count());
87746616af01b412ea984a516fda1ed8ec08e689f29mtklein    } else {
87846616af01b412ea984a516fda1ed8ec08e689f29mtklein        this->addInt(0);
87946616af01b412ea984a516fda1ed8ec08e689f29mtklein    }
880cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org}
881cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org
8825a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comint SkPictureRecord::addPathToHeap(const SkPath& path) {
883c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    if (int* n = fPaths.find(path)) {
884c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein        return *n;
885c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    }
886c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    int n = fPaths.count() + 1;  // 0 is reserved for null / error.
887c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    fPaths.set(path, n);
888c2e2977014c4581aed5da435fc2b7eba38e777b6mtklein    return n;
8895a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
8905a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
8915a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comvoid SkPictureRecord::addPath(const SkPath& path) {
892cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(this->addPathToHeap(path));
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
895b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkPictureRecord::addPatch(const SkPoint cubics[12]) {
896b3c9d1c33caf325aada244204215eb790c228c12dandov    fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
897963137b75c0a1fe91f35e9826742f36309f5e65ddandov}
898963137b75c0a1fe91f35e9826742f36309f5e65ddandov
8999b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkPictureRecord::addPicture(const SkPicture* picture) {
9009b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    int index = fPictureRefs.find(picture);
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (index < 0) {    // not found
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        index = fPictureRefs.count();
9039b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips        *fPictureRefs.append() = picture;
9049b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips        picture->ref();
9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // follow the convention of recording a 1-based index
907cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(index + 1);
9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addPoint(const SkPoint& point) {
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writePoint(point);
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
91382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addPoints(const SkPoint pts[], int count) {
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(pts, count * sizeof(SkPoint));
9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
91868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.orgvoid SkPictureRecord::addNoOp() {
91968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    size_t size = kUInt32Size; // op
92068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    this->addDraw(NOOP, &size);
92168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org}
92268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRect(const SkRect& rect) {
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeRect(rect);
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRectPtr(const SkRect* rect) {
92896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (fWriter.writeBool(rect != nullptr)) {
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWriter.writeRect(*rect);
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
933f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.comvoid SkPictureRecord::addIRect(const SkIRect& rect) {
934f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com    fWriter.write(&rect, sizeof(rect));
935f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com}
936f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addIRectPtr(const SkIRect* rect) {
93896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (fWriter.writeBool(rect != nullptr)) {
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9434ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkPictureRecord::addRRect(const SkRRect& rrect) {
9444ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    fWriter.writeRRect(rrect);
9454ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
9464ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRegion(const SkRegion& region) {
948fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    fWriter.writeRegion(region);
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addText(const void* text, size_t byteLength) {
952afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawText();
953dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    addInt(SkToInt(byteLength));
9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writePad(text, byteLength);
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
957b7425173f96e93b090787e2386ba5f022b6c2869fmalitavoid SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
958dd1e9f75969c72da53657e58a080c47b30f64140jbroman    int index = fTextBlobRefs.count();
959dd1e9f75969c72da53657e58a080c47b30f64140jbroman    *fTextBlobRefs.append() = blob;
960dd1e9f75969c72da53657e58a080c47b30f64140jbroman    blob->ref();
961b7425173f96e93b090787e2386ba5f022b6c2869fmalita    // follow the convention of recording a 1-based index
962b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addInt(index + 1);
963b7425173f96e93b090787e2386ba5f022b6c2869fmalita}
964b7425173f96e93b090787e2386ba5f022b6c2869fmalita
9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
967