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"
14b7425173f96e93b090787e2386ba5f022b6c2869fmalita#include "SkTextBlob.h"
15b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkTSearch.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define HEAP_BLOCK_SIZE 4096
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
194e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.orgenum {
20d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // just need a value that save or getSaveCount would never return
214e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    kNoInitialSave = -1,
224e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org};
234e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org
242ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
252ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.comstatic int const kUInt32Size = 4;
262ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
275f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitastatic const uint32_t kSaveSize = kUInt32Size;
288e12656096fceeed8b3cc4284d57dea04893b455mtklein#ifdef SK_DEBUG
29e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.comstatic const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
30e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.comstatic const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
318e12656096fceeed8b3cc4284d57dea04893b455mtklein#endif//SK_DEBUG
32e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com
330bdbea75ff1a6f3c313c18cab0139728967cb93erobertphillipsSkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
3419fafef9784fe7c644540ffd0ee9f6da1914a038commit-bot@chromium.org    : INHERITED(dimensions.width(), dimensions.height())
3571a236370792416b367a7d2d6b8e471b06b331cdmtklein    , fRecordFlags(flags)
3671a236370792416b367a7d2d6b8e471b06b331cdmtklein    , fInitialSaveCount(kNoInitialSave) {
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkPictureRecord::~SkPictureRecord() {
4021830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com    fPictureRefs.unrefAll();
41b7425173f96e93b090787e2386ba5f022b6c2869fmalita    fTextBlobRefs.unrefAll();
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
468e12656096fceeed8b3cc4284d57dea04893b455mtklein#ifdef SK_DEBUG
47e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com// Return the offset of the paint inside a given op's byte stream. A zero
48e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com// return value means there is no paint (and you really shouldn't be calling
49e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com// this method)
508e12656096fceeed8b3cc4284d57dea04893b455mtkleinstatic inline size_t get_paint_offset(DrawType op, size_t opSize) {
51e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com    // These offsets are where the paint would be if the op size doesn't overflow
529f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita    static const uint8_t gPaintOffsets[] = {
53e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // UNUSED - no paint
54e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // CLIP_PATH - no paint
55e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // CLIP_REGION - no paint
56e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // CLIP_RECT - no paint
57e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // CLIP_RRECT - no paint
58e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // CONCAT - no paint
59e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_BITMAP - right after op code
60c54d8db4d169ea5f2af2a9a2349df007bd428475Florin Malita        1,  // DRAW_BITMAP_MATRIX - right after op code, deprecated
61e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_BITMAP_NINE - right after op code
62e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_BITMAP_RECT_TO_RECT - right after op code
63e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // DRAW_CLEAR - no paint
64e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // DRAW_DATA - no paint
65e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_OVAL - right after op code
66e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_PAINT - right after op code
67e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_PATH - right after op code
68e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // DRAW_PICTURE - no paint
69e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_POINTS - right after op code
70e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_POS_TEXT - right after op code
71e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_POS_TEXT_TOP_BOTTOM - right after op code
72e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_POS_TEXT_H - right after op code
73e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_POS_TEXT_H_TOP_BOTTOM - right after op code
74e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_RECT - right after op code
75e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_RRECT - right after op code
76e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_SPRITE - right after op code
77e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_TEXT - right after op code
78e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_TEXT_ON_PATH - right after op code
79e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_TEXT_TOP_BOTTOM - right after op code
80e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        1,  // DRAW_VERTICES - right after op code
81e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // RESTORE - no paint
82e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // ROTATE - no paint
83e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // SAVE - no paint
84f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com        0,  // SAVE_LAYER - see below - this paint's location varies
85e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // SCALE - no paint
86e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // SET_MATRIX - no paint
87e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // SKEW - no paint
88e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // TRANSLATE - no paint
89e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        0,  // NOOP - no paint
900a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com        0,  // BEGIN_GROUP - no paint
910a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com        0,  // COMMENT - no paint
920a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com        0,  // END_GROUP - no paint
93ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        1,  // DRAWDRRECT - right after op code
94210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org        0,  // PUSH_CULL - no paint
95210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org        0,  // POP_CULL - no paint
96963137b75c0a1fe91f35e9826742f36309f5e65ddandov        1,  // DRAW_PATCH - right after op code
979f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita        1,  // DRAW_PICTURE_MATRIX_PAINT - right after op code
98b7425173f96e93b090787e2386ba5f022b6c2869fmalita        1,  // DRAW_TEXT_BLOB- right after op code
99f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com    };
100e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com
101ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
102ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                      need_to_be_in_sync);
103e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com    SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
104e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com
105e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com    int overflow = 0;
106e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com    if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
107e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        // This op's size overflows so an extra uint32_t will be written
108e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        // after the op code
109e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        overflow = sizeof(uint32_t);
110e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com    }
111e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com
112e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com    if (SAVE_LAYER == op) {
113e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
114e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
115e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com
116e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        if (kSaveLayerNoBoundsSize == opSize) {
117e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com            return kSaveLayerNoBoundsPaintOffset + overflow;
118e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        } else {
119e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com            SkASSERT(kSaveLayerWithBoundsSize == opSize);
120e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com            return kSaveLayerWithBoundsPaintOffset + overflow;
121e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com        }
122e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com    }
123e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com
124e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com    SkASSERT(0 != gPaintOffsets[op]);   // really shouldn't be calling this method
125e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com    return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
126e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com}
1278e12656096fceeed8b3cc4284d57dea04893b455mtklein#endif//SK_DEBUG
128e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com
1295f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitavoid SkPictureRecord::willSave() {
130ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // record the offset to us, making it non-positive to distinguish a save
131ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // from a clip entry.
1324469938e92d779dff05e745559e67907bbf21e78reed@google.com    fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
1335f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    this->recordSave();
134e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
1355f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    this->INHERITED::willSave();
1365a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
13711f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
1385f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitavoid SkPictureRecord::recordSave() {
139c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onSave();
140c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
1415f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    // op only
142dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = kSaveSize;
1438b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SAVE, &size);
14482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1458b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
148e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgSkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
149e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org                                                           const SkPaint* paint, SaveFlags flags) {
150ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // record the offset to us, making it non-positive to distinguish a save
151ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    // from a clip entry.
1524469938e92d779dff05e745559e67907bbf21e78reed@google.com    fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
1535a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    this->recordSaveLayer(bounds, paint, flags);
15411f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
155e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    this->INHERITED::willSaveLayer(bounds, paint, flags);
156e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    /*  No need for a (potentially very big) layer which we don't actually need
1575a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        at this time (and may not be able to afford since during record our
1585a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        clip starts out the size of the picture, which is often much larger
1595a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        than the size of the actual device we'll use during playback).
1605a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com     */
161e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    return kNoLayer_SaveLayerStrategy;
1625a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
1635a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
1645a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comvoid SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
165105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com                                      SaveFlags flags) {
166c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onSaveLayer();
167c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
1682ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + bool for 'bounds'
169dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
17049f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1712ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        size += sizeof(*bounds); // + rect
1722ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
1732ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // + paint index + flags
1742ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    size += 2 * kUInt32Size;
1752ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
176e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com    SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
177e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com
1788b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
179cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRectPtr(bounds);
1808e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(SAVE_LAYER, size) == fWriter.bytesWritten());
181cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaintPtr(paint);
182cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(flags);
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1848b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
187210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org#ifdef SK_DEBUG
188210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org/*
1892ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com * Read the op code from 'offset' in 'writer' and extract the size too.
1902ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com */
191dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgstatic DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
192536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    uint32_t peek = writer->readTAt<uint32_t>(offset);
1932ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
1942ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    uint32_t op;
195c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org    UNPACK_8_24(peek, op, *size);
1962ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    if (MASK_24 == *size) {
1972ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        // size required its own slot right after the op code
198536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
1992ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
2002ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    return (DrawType) op;
201ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com}
20246616af01b412ea984a516fda1ed8ec08e689f29mtklein#endif//SK_DEBUG
2034b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org
204e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgvoid SkPictureRecord::willRestore() {
2054e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    // FIXME: SkDeferredCanvas needs to be refactored to respect
2064e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    // save/restore balancing so that the following test can be
2074e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    // turned on permanently.
2084e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org#if 0
2094e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    SkASSERT(fRestoreOffsetStack.count() > 1);
2104e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org#endif
2114e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org
212b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    // check for underflow
213b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    if (fRestoreOffsetStack.count() == 0) {
214b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com        return;
215b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    }
216b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com
21746616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->recordRestore();
218ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com
219b4e22d62da422f3599ef9bd5091c5f4b7709d27ereed@android.com    fRestoreOffsetStack.pop();
22032a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com
221e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    this->INHERITED::willRestore();
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
224105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.comvoid SkPictureRecord::recordRestore(bool fillInSkips) {
225c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips    fContentInfo.onRestore();
226c019ec412ba2704bc6e2cdfd321ea06787ba415drobertphillips
227105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    if (fillInSkips) {
228105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
229105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
230dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
231dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t initialOffset = this->addDraw(RESTORE, &size);
2325a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    this->validate(initialOffset, size);
2335a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
2345a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
235d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.orgvoid SkPictureRecord::recordTranslate(const SkMatrix& m) {
236d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
237d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
2382ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + dx + dy
239dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
2408b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(TRANSLATE, &size);
241d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getTranslateX());
242d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getTranslateY());
2438b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
246d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.orgvoid SkPictureRecord::recordScale(const SkMatrix& m) {
247d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkASSERT(SkMatrix::kScale_Mask == m.getType());
248105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
2492ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + sx + sy
250dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
2518b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SCALE, &size);
252d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getScaleX());
253d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->addScalar(m.getScaleY());
2548b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkPictureRecord::didConcat(const SkMatrix& matrix) {
258d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    switch (matrix.getType()) {
259d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        case SkMatrix::kTranslate_Mask:
260d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordTranslate(matrix);
261d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
262d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        case SkMatrix::kScale_Mask:
263d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordScale(matrix);
264d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
265d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        default:
266d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            this->recordConcat(matrix);
267d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org            break;
268d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
26944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->INHERITED::didConcat(matrix);
2705a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
2715a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
2725a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comvoid SkPictureRecord::recordConcat(const SkMatrix& matrix) {
2734469938e92d779dff05e745559e67907bbf21e78reed@google.com    this->validate(fWriter.bytesWritten(), 0);
274fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + matrix
275dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = kUInt32Size + matrix.writeToMemory(NULL);
2768b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CONCAT, &size);
277cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(matrix);
2788b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
2824469938e92d779dff05e745559e67907bbf21e78reed@google.com    this->validate(fWriter.bytesWritten(), 0);
283fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + matrix
284dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = kUInt32Size + matrix.writeToMemory(NULL);
2858b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(SET_MATRIX, &size);
286cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(matrix);
2878b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
28844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->INHERITED::didSetMatrix(matrix);
2896e073b9e2b70d6bbf8a06050fff1364827204f08reed@android.com}
2906e073b9e2b70d6bbf8a06050fff1364827204f08reed@android.com
29145482d1d2b97de185df137a1db40cbe5a62313a5reed@google.comstatic bool regionOpExpands(SkRegion::Op op) {
29245482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    switch (op) {
29345482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kUnion_Op:
29445482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kXOR_Op:
29545482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kReverseDifference_Op:
29645482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kReplace_Op:
29745482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return true;
29845482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kIntersect_Op:
29945482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        case SkRegion::kDifference_Op:
30045482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return false;
30145482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        default:
3020c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown region op");
30345482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com            return false;
30445482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    }
30545482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com}
30645482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com
307e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.comvoid SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
308ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    int32_t offset = fRestoreOffsetStack.top();
309ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com    while (offset > 0) {
310536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        uint32_t peek = fWriter.readTAt<uint32_t>(offset);
311536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        fWriter.overwriteTAt(offset, restoreOffset);
312c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org        offset = peek;
313e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org    }
31411f869277c81a232fd4e40eca41e6f71b95b4b17skia.committer@gmail.com
315ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com#ifdef SK_DEBUG
3162ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    // offset of 0 has been disabled, so we skip it
3172ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (offset > 0) {
3182ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // assert that the final offset value points to a save verb
3192ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        uint32_t opSize;
3202ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
3212ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
3222ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
323ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com#endif
324e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org}
325e3dbedb44cad6c7b7e5c9aae5224d0b0abec9bf4junov@chromium.org
326d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.comvoid SkPictureRecord::beginRecording() {
327d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // we have to call this *after* our constructor, to ensure that it gets
328d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // recorded. This is balanced by restoreToCount() call from endRecording,
329d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com    // which in-turn calls our overridden restore(), so those get recorded too.
330091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org    fInitialSaveCount = this->save();
331d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com}
332d86e7ab6044e4aba017cb126a26dd378eec9fcbareed@google.com
333a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.orgvoid SkPictureRecord::endRecording() {
3344e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    SkASSERT(kNoInitialSave != fInitialSaveCount);
3354e6dfa51525e174d79cb88800d8e5f2c88291270junov@chromium.org    this->restoreToCount(fInitialSaveCount);
336a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.org}
337a6c9e0e02be390d36b80f4872c628edb3594208ejunov@chromium.org
338dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgsize_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
33921b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com    if (fRestoreOffsetStack.isEmpty()) {
3405a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com        return -1;
34121b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com    }
34221b519d56f9838c2e6e7abe704d3313e03f6f754reed@google.com
343d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // The RestoreOffset field is initially filled with a placeholder
344d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // value that points to the offset of the previous RestoreOffset
345d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // in the current stack level, thus forming a linked list so that
346d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // the restore offsets can be filled in when the corresponding
347d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    // restore command is recorded.
348d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com    int32_t prevOffset = fRestoreOffsetStack.top();
349d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com
35045482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    if (regionOpExpands(op)) {
35145482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // Run back through any previous clip ops, and mark their offset to
35245482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // be 0, disabling their ability to trigger a jump-to-restore, otherwise
35345482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // they could hide this clips ability to expand the clip (i.e. go from
35445482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com        // empty to non-empty).
355cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com        this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
356d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com
357d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        // Reset the pointer back to the previous clip so that subsequent
358d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        // restores don't overwrite the offsets we just cleared.
359d0f1a4fb28057de42d116005d82166b2302d28e9fmalita@google.com        prevOffset = 0;
36045482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com    }
36174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3624469938e92d779dff05e745559e67907bbf21e78reed@google.com    size_t offset = fWriter.bytesWritten();
363cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(prevOffset);
364dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    fRestoreOffsetStack.top() = SkToU32(offset);
3655a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
36645482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com}
36745482d1d2b97de185df137a1db40cbe5a62313a5reed@google.com
3688f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
3698f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
3708f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->INHERITED::onClipRect(rect, op, edgeStyle);
3715a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3725a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
373dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgsize_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
374f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // id + rect + clip params
375dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
3764310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
377f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
378f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
379f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
380f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
3818b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_RECT, &size);
382cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(rect);
383cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
384dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = this->recordRestoreOffsetPlaceholder(op);
385306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
3868b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
3875a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
38868d61ed83ec7b6e98e9623c2f5c9e7b1a32d25bbreed@google.com}
38968d61ed83ec7b6e98e9623c2f5c9e7b1a32d25bbreed@google.com
3908f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
3918f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
392d954498c01ccf0417feacf89e45d0c62a06a813breed    this->INHERITED::onClipRRect(rrect, op, edgeStyle);
3935a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
3945a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
395dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgsize_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
396f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // op + rrect + clip params
397dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
3984310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
399f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
400f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
401f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
402f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
4038b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
404cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRRect(rrect);
405cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
406dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = recordRestoreOffsetPlaceholder(op);
4078b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4085a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
4094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
4104ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
4118f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
4125a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    int pathID = this->addPathToHeap(path);
4138f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
414d954498c01ccf0417feacf89e45d0c62a06a813breed    this->INHERITED::onClipPath(path, op, edgeStyle);
4155a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
4165a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
417dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgsize_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
418f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    // op + path index + clip params
419dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size;
4204310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
421f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
422f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
423f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
424f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
4258b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_PATH, &size);
426cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(pathID);
427cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, doAA));
428dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = recordRestoreOffsetPlaceholder(op);
4298b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4305a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4338f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
4345a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    this->recordClipRegion(region, op);
4358f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->INHERITED::onClipRegion(region, op);
4365a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
4375a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
438dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.orgsize_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
439fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + clip params + region
440dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
4414310c66ed4bb67c96ec65d8b499b8a9c4deab2edrobertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
442f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
443f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        // + restore offset
444f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com        size += kUInt32Size;
445f92915089fa914843ca63594efc47a80b8f971bcrobertphillips@google.com    }
4468b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(CLIP_REGION, &size);
447cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRegion(region);
448cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(ClipParams_pack(op, false));
449dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t offset = this->recordRestoreOffsetPlaceholder(op);
45082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4518b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4525a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com    return offset;
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45541af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPaint(const SkPaint& paint) {
4562ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index
457dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
4588b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
4598e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_PAINT, size) == fWriter.bytesWritten());
460cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
4618b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
46441af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
46541af966ab338e95eee81ab618ab28195075338f7reed                                   const SkPaint& paint) {
466afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawPoints(count, paint);
467105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
4682ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + mode + count + point data
469dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
4708b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
4718e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
472cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
473afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw
474cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(mode);
475dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    this->addInt(SkToInt(count));
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(pts, count * sizeof(SkPoint));
4778b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
48041af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
4812ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + rect
482dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + sizeof(oval);
4838b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
4848e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_OVAL, size) == fWriter.bytesWritten());
485cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
486cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(oval);
4878b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4884ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
4894ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
49041af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
4912ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + rect
492dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + sizeof(rect);
4938b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_RECT, &size);
4948e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_RECT, size) == fWriter.bytesWritten());
495cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
496cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(rect);
4978b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50041af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
50146616af01b412ea984a516fda1ed8ec08e689f29mtklein    // op + paint index + rrect
50246616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
50346616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
5048e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_RRECT, size) == fWriter.bytesWritten());
50546616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
50646616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addRRect(rrect);
50746616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->validate(initialOffset, size);
5084ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
5094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
510ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
511ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                                   const SkPaint& paint) {
512ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // op + paint index + rrects
513dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
514dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
5158e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_DRRECT, size) == fWriter.bytesWritten());
516ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addPaint(paint);
517ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addRRect(outer);
518ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->addRRect(inner);
519ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->validate(initialOffset, size);
520ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
521ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
52241af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
523afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawPath(path, paint);
524e2cb12a82ad924f7b134a9459b190213485c6a50commit-bot@chromium.org
5252ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + path index
526dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size;
5278b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_PATH, &size);
5288e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_PATH, size) == fWriter.bytesWritten());
529cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
530cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPath(path);
5318b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53441af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
53541af966ab338e95eee81ab618ab28195075338f7reed                                   const SkPaint* paint) {
5362ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + bitmap index + left + top
537dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
5388b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
5398e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP, size) == fWriter.bytesWritten());
540cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaintPtr(paint);
541f6a5afb66b661c884cd308577431b7abf025b182commit-bot@chromium.org    this->addBitmap(bitmap);
542cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(left);
543cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(top);
5448b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54741af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
54841af966ab338e95eee81ab618ab28195075338f7reed                                       const SkPaint* paint, DrawBitmapRectFlags flags) {
549eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org    // id + paint index + bitmap index + bool for 'src' + flags
550dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 5 * kUInt32Size;
55149f085dddff10473b6ebf832a974288300224e60bsalomon    if (src) {
5522ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        size += sizeof(*src);   // + rect
5532ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
5542ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    size += sizeof(dst);        // + rect
5552ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
5568b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
5578e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_RECT_TO_RECT, size)
55850b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org             == fWriter.bytesWritten());
559cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaintPtr(paint);
560f6a5afb66b661c884cd308577431b7abf025b182commit-bot@chromium.org    this->addBitmap(bitmap);
561cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRectPtr(src);  // may be null
562cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(dst);
563cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(flags);
5648b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
567a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
568a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                  const SkPaint* paint) {
569a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkBitmap bm;
570a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (as_IB(image)->getROPixels(&bm)) {
571a85d4d0814818e4ddabb9237da209d61d6cd5854reed        this->SkPictureRecord::onDrawBitmap(bm, x, y, paint);
572a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
573a85d4d0814818e4ddabb9237da209d61d6cd5854reed}
574a85d4d0814818e4ddabb9237da209d61d6cd5854reed
575a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
576a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                      const SkPaint* paint) {
577a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkBitmap bm;
578a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (as_IB(image)->getROPixels(&bm)) {
579a85d4d0814818e4ddabb9237da209d61d6cd5854reed        this->SkPictureRecord::onDrawBitmapRect(bm, src, dst, paint, kNone_DrawBitmapRectFlag);
580a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
581a85d4d0814818e4ddabb9237da209d61d6cd5854reed}
582a85d4d0814818e4ddabb9237da209d61d6cd5854reed
58341af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
58441af966ab338e95eee81ab618ab28195075338f7reed                                       const SkRect& dst, const SkPaint* paint) {
5852ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + bitmap id + center + dst rect
586dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
5878b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
5888e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
589cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaintPtr(paint);
590f6a5afb66b661c884cd308577431b7abf025b182commit-bot@chromium.org    this->addBitmap(bitmap);
591cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addIRect(center);
592cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addRect(dst);
5938b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
594f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com}
595f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com
59641af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawSprite(const SkBitmap& bitmap, int left, int top,
59741af966ab338e95eee81ab618ab28195075338f7reed                                   const SkPaint* paint) {
5982ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + bitmap index + left + top
599dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 5 * kUInt32Size;
6008b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
6018e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_SPRITE, size) == fWriter.bytesWritten());
602cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaintPtr(paint);
603f6a5afb66b661c884cd308577431b7abf025b182commit-bot@chromium.org    this->addBitmap(bitmap);
604cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(left);
605cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(top);
6068b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
609e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
610e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                 const SkPaint& paint) {
6112ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + length + 'length' worth of chars + x + y
612dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
6132ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
61446616af01b412ea984a516fda1ed8ec08e689f29mtklein    DrawType op = DRAW_TEXT;
6158b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(op, &size);
6168e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
61746616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
618cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
619cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(x);
620cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(y);
6218b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
624e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
625e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                    const SkPaint& paint) {
626dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    int points = paint.countText(text, byteLength);
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62846616af01b412ea984a516fda1ed8ec08e689f29mtklein    // op + paint index + length + 'length' worth of data + num points + x&y point data
62946616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
63146616af01b412ea984a516fda1ed8ec08e689f29mtklein    DrawType op = DRAW_POS_TEXT;
6322ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
6338b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(op, &size);
6348e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(op, size) == fWriter.bytesWritten());
63546616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
636cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
637cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(points);
63846616af01b412ea984a516fda1ed8ec08e689f29mtklein    fWriter.writeMul4(pos, points * sizeof(SkPoint));
6398b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
642e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
643e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                     SkScalar constY, const SkPaint& paint) {
644dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    int points = paint.countText(text, byteLength);
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6462ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + length + 'length' worth of data + num points
647dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
6482ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // + y + the actual points
6492ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    size += 1 * kUInt32Size + points * sizeof(SkScalar);
650cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org
65146616af01b412ea984a516fda1ed8ec08e689f29mtklein    size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
65246616af01b412ea984a516fda1ed8ec08e689f29mtklein    this->addPaint(paint);
653cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
654cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(points);
655cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addScalar(constY);
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(xpos, points * sizeof(SkScalar));
6578b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
660e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
661e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                       const SkMatrix* matrix, const SkPaint& paint) {
662fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    // op + paint index + length + 'length' worth of data + path index + matrix
663fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
664dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
6658b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
6668e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
667cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
668cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addText(text, byteLength);
669cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPath(path);
670cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addMatrix(m);
6718b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
674b7425173f96e93b090787e2386ba5f022b6c2869fmalitavoid SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
675b7425173f96e93b090787e2386ba5f022b6c2869fmalita                                     const SkPaint& paint) {
676b7425173f96e93b090787e2386ba5f022b6c2869fmalita
677b7425173f96e93b090787e2386ba5f022b6c2869fmalita    // op + paint index + blob index + x/y
678b7425173f96e93b090787e2386ba5f022b6c2869fmalita    size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
679b7425173f96e93b090787e2386ba5f022b6c2869fmalita    size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
6808e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset + get_paint_offset(DRAW_TEXT_BLOB, size) == fWriter.bytesWritten());
681b7425173f96e93b090787e2386ba5f022b6c2869fmalita
682b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addPaint(paint);
683b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addTextBlob(blob);
684b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addScalar(x);
685b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addScalar(y);
686b7425173f96e93b090787e2386ba5f022b6c2869fmalita
687b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->validate(initialOffset, size);
688b7425173f96e93b090787e2386ba5f022b6c2869fmalita}
689b7425173f96e93b090787e2386ba5f022b6c2869fmalita
690d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
691d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                                    const SkPaint* paint) {
6922ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + picture index
693dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size;
694d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    size_t initialOffset;
695d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
696d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    if (NULL == matrix && NULL == paint) {
697d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        initialOffset = this->addDraw(DRAW_PICTURE, &size);
698d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        this->addPicture(picture);
699d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    } else {
700d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
701d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        size += m.writeToMemory(NULL) + kUInt32Size;    // matrix + paint
702d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
7038e12656096fceeed8b3cc4284d57dea04893b455mtklein        SkASSERT(initialOffset + get_paint_offset(DRAW_PICTURE_MATRIX_PAINT, size)
7049f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita                 == fWriter.bytesWritten());
705d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        this->addPaintPtr(paint);
7069f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita        this->addMatrix(m);
7079f49cfdbf6493b953775890d7f9c97a1dce0d341fmalita        this->addPicture(picture);
708d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
7098b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
71241af966ab338e95eee81ab618ab28195075338f7reedvoid SkPictureRecord::onDrawVertices(VertexMode vmode, int vertexCount,
71341af966ab338e95eee81ab618ab28195075338f7reed                                     const SkPoint vertices[], const SkPoint texs[],
71441af966ab338e95eee81ab618ab28195075338f7reed                                     const SkColor colors[], SkXfermode* xfer,
71541af966ab338e95eee81ab618ab28195075338f7reed                                     const uint16_t indices[], int indexCount,
71641af966ab338e95eee81ab618ab28195075338f7reed                                     const SkPaint& paint) {
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t flags = 0;
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (texs) {
7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= DRAW_VERTICES_HAS_TEXS;
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (colors) {
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= DRAW_VERTICES_HAS_COLORS;
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (indexCount > 0) {
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= DRAW_VERTICES_HAS_INDICES;
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
72749f085dddff10473b6ebf832a974288300224e60bsalomon    if (xfer) {
72885e143c33c214e54187aa28146aa7666961a0d17reed@google.com        SkXfermode::Mode mode;
72985e143c33c214e54187aa28146aa7666961a0d17reed@google.com        if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
73085e143c33c214e54187aa28146aa7666961a0d17reed@google.com            flags |= DRAW_VERTICES_HAS_XFER;
73185e143c33c214e54187aa28146aa7666961a0d17reed@google.com        }
73285e143c33c214e54187aa28146aa7666961a0d17reed@google.com    }
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7342ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    // op + paint index + flags + vmode + vCount + vertices
735dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
7362ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    if (flags & DRAW_VERTICES_HAS_TEXS) {
7372ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        size += vertexCount * sizeof(SkPoint);  // + uvs
7382ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
7392ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    if (flags & DRAW_VERTICES_HAS_COLORS) {
7402ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        size += vertexCount * sizeof(SkColor);  // + vert colors
7412ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
7422ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    if (flags & DRAW_VERTICES_HAS_INDICES) {
7432ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        // + num indices + indices
7442ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com        size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
7452ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com    }
74685e143c33c214e54187aa28146aa7666961a0d17reed@google.com    if (flags & DRAW_VERTICES_HAS_XFER) {
74785e143c33c214e54187aa28146aa7666961a0d17reed@google.com        size += kUInt32Size;    // mode enum
74885e143c33c214e54187aa28146aa7666961a0d17reed@google.com    }
7492ca1aaaa442290b8262e1ca3ec64ebe46a191211robertphillips@google.com
7508b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
7518e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_VERTICES, size) == fWriter.bytesWritten());
752cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPaint(paint);
753cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(flags);
754cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(vmode);
755cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(vertexCount);
756cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addPoints(vertices, vertexCount);
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (flags & DRAW_VERTICES_HAS_TEXS) {
758cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com        this->addPoints(texs, vertexCount);
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (flags & DRAW_VERTICES_HAS_COLORS) {
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (flags & DRAW_VERTICES_HAS_INDICES) {
764cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com        this->addInt(indexCount);
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWriter.writePad(indices, indexCount * sizeof(uint16_t));
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
76785e143c33c214e54187aa28146aa7666961a0d17reed@google.com    if (flags & DRAW_VERTICES_HAS_XFER) {
76885e143c33c214e54187aa28146aa7666961a0d17reed@google.com        SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
76985e143c33c214e54187aa28146aa7666961a0d17reed@google.com        (void)xfer->asMode(&mode);
770cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com        this->addInt(mode);
77185e143c33c214e54187aa28146aa7666961a0d17reed@google.com    }
7728b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
775b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
776b3c9d1c33caf325aada244204215eb790c228c12dandov                                  const SkPoint texCoords[4], SkXfermode* xmode,
777b3c9d1c33caf325aada244204215eb790c228c12dandov                                  const SkPaint& paint) {
778b3c9d1c33caf325aada244204215eb790c228c12dandov    // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
779b3c9d1c33caf325aada244204215eb790c228c12dandov    size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
780b3c9d1c33caf325aada244204215eb790c228c12dandov    uint32_t flag = 0;
78149f085dddff10473b6ebf832a974288300224e60bsalomon    if (colors) {
782b3c9d1c33caf325aada244204215eb790c228c12dandov        flag |= DRAW_VERTICES_HAS_COLORS;
783b3c9d1c33caf325aada244204215eb790c228c12dandov        size += SkPatchUtils::kNumCorners * sizeof(SkColor);
784b3c9d1c33caf325aada244204215eb790c228c12dandov    }
78549f085dddff10473b6ebf832a974288300224e60bsalomon    if (texCoords) {
786b3c9d1c33caf325aada244204215eb790c228c12dandov        flag |= DRAW_VERTICES_HAS_TEXS;
787b3c9d1c33caf325aada244204215eb790c228c12dandov        size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
788b3c9d1c33caf325aada244204215eb790c228c12dandov    }
78949f085dddff10473b6ebf832a974288300224e60bsalomon    if (xmode) {
790b3c9d1c33caf325aada244204215eb790c228c12dandov        SkXfermode::Mode mode;
791b3c9d1c33caf325aada244204215eb790c228c12dandov        if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
792b3c9d1c33caf325aada244204215eb790c228c12dandov            flag |= DRAW_VERTICES_HAS_XFER;
793b3c9d1c33caf325aada244204215eb790c228c12dandov            size += kUInt32Size;
794b3c9d1c33caf325aada244204215eb790c228c12dandov        }
795b3c9d1c33caf325aada244204215eb790c228c12dandov    }
79646616af01b412ea984a516fda1ed8ec08e689f29mtklein
797963137b75c0a1fe91f35e9826742f36309f5e65ddandov    size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
7988e12656096fceeed8b3cc4284d57dea04893b455mtklein    SkASSERT(initialOffset+get_paint_offset(DRAW_PATCH, size) == fWriter.bytesWritten());
799963137b75c0a1fe91f35e9826742f36309f5e65ddandov    this->addPaint(paint);
800b3c9d1c33caf325aada244204215eb790c228c12dandov    this->addPatch(cubics);
801b3c9d1c33caf325aada244204215eb790c228c12dandov    this->addInt(flag);
80246616af01b412ea984a516fda1ed8ec08e689f29mtklein
803b3c9d1c33caf325aada244204215eb790c228c12dandov    // write optional parameters
80449f085dddff10473b6ebf832a974288300224e60bsalomon    if (colors) {
805b3c9d1c33caf325aada244204215eb790c228c12dandov        fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
806b3c9d1c33caf325aada244204215eb790c228c12dandov    }
80749f085dddff10473b6ebf832a974288300224e60bsalomon    if (texCoords) {
808b3c9d1c33caf325aada244204215eb790c228c12dandov        fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
809b3c9d1c33caf325aada244204215eb790c228c12dandov    }
810b3c9d1c33caf325aada244204215eb790c228c12dandov    if (flag & DRAW_VERTICES_HAS_XFER) {
811b3c9d1c33caf325aada244204215eb790c228c12dandov        SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
812b3c9d1c33caf325aada244204215eb790c228c12dandov        xmode->asMode(&mode);
813b3c9d1c33caf325aada244204215eb790c228c12dandov        this->addInt(mode);
814b3c9d1c33caf325aada244204215eb790c228c12dandov    }
815963137b75c0a1fe91f35e9826742f36309f5e65ddandov    this->validate(initialOffset, size);
816963137b75c0a1fe91f35e9826742f36309f5e65ddandov}
817963137b75c0a1fe91f35e9826742f36309f5e65ddandov
8180a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.comvoid SkPictureRecord::beginCommentGroup(const char* description) {
8190a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com    // op/size + length of string + \0 terminated chars
820dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t length = strlen(description);
821dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 2 * kUInt32Size + SkAlign4(length + 1);
8228b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(BEGIN_COMMENT_GROUP, &size);
8230a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com    fWriter.writeString(description, length);
8248b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
8250a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com}
8260a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com
8270a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.comvoid SkPictureRecord::addComment(const char* kywd, const char* value) {
8280a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com    // op/size + 2x length of string + 2x \0 terminated chars
829dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t kywdLen = strlen(kywd);
830dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t valueLen = strlen(value);
831dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
8328b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(COMMENT, &size);
8330a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com    fWriter.writeString(kywd, kywdLen);
8340a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com    fWriter.writeString(value, valueLen);
8358b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
8360a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com}
8370a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com
8380a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.comvoid SkPictureRecord::endCommentGroup() {
8390a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com    // op/size
840dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    size_t size = 1 * kUInt32Size;
8418b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t initialOffset = this->addDraw(END_COMMENT_GROUP, &size);
8428b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    this->validate(initialOffset, size);
8430a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com}
8440a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
84682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
8474a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
848cae54f1f211e3c293ef9afb968067d06ca0ea23dcommit-bot@chromium.org    return NULL;
84976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
85076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
851e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein// If we already have a stored, can we reuse it instead of also storing b?
852e069400cabd0edd3db52bbf1958063d3ed12ef28mtkleinstatic bool equivalent(const SkBitmap& a, const SkBitmap& b) {
853e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    if (a.info() != b.info() || a.pixelRefOrigin() != b.pixelRefOrigin()) {
854e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        // Requiring a.info() == b.info() may be overkill in some cases (alphatype mismatch),
855e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        // but it sure makes things easier to reason about below.
856e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return false;
857e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
858e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    if (a.pixelRef() == b.pixelRef()) {
859e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return true;  // Same shape and same pixels -> same bitmap.
860e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
861e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein
862e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // From here down we're going to have to look at the bitmap data, so we require pixelRefs().
863e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    if (!a.pixelRef() || !b.pixelRef()) {
864e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return false;
865e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
866e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein
867e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // If the bitmaps have encoded data, check first before locking pixels so they don't decode.
868e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    SkAutoTUnref<SkData> encA(a.pixelRef()->refEncodedData()),
869e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein                         encB(b.pixelRef()->refEncodedData());
870e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    if (encA && encB) {
871e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return encA->equals(encB);
872e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    } else if (encA || encB) {
873e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return false;   // One has encoded data but the other does not.
874e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
875e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein
876e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // As a last resort, we have to look at the pixels.  This will read back textures.
877e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    SkAutoLockPixels al(a), bl(b);
878e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    const char* ap = (const char*)a.getPixels();
879e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    const char* bp = (const char*)b.getPixels();
880e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    if (ap && bp) {
881e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        // We check row by row; row bytes might differ.
882e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        SkASSERT(a.info() == b.info());          // We checked this above.
883e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        SkASSERT(a.info().bytesPerPixel() > 0);  // If we have pixelRefs, this better be true.
884e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        const SkImageInfo info = a.info();
885e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        const size_t bytesToCompare = info.width() * info.bytesPerPixel();
886e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        for (int row = 0; row < info.height(); row++) {
887e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            if (0 != memcmp(ap, bp, bytesToCompare)) {
888e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein                return false;
889e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            }
890e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            ap += a.rowBytes();
891e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            bp += b.rowBytes();
892e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        }
893e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        return true;
894e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
895e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    return false;  // Couldn't get pixels for both bitmaps.
896e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein}
897e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein
898e069400cabd0edd3db52bbf1958063d3ed12ef28mtkleinvoid SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
899e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // First see if we already have this bitmap.  This deduplication should really
900e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // only be important for our tests, where bitmaps tend not to be tagged immutable.
901e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // In Chrome (and hopefully Android?) they're typically immutable.
902e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    for (int i = 0; i < fBitmaps.count(); i++) {
903e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        if (equivalent(fBitmaps[i], bitmap)) {
904e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            this->addInt(i);  // Unlike the rest, bitmap indices are 0-based.
905e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein            return;
906e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        }
907e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    }
908e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    // Don't have it.  We'll add it to our list, making sure it's tagged as immutable.
90971a236370792416b367a7d2d6b8e471b06b331cdmtklein    if (bitmap.isImmutable()) {
910e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        // Shallow copies of bitmaps are cheap, so immutable == fast.
91171a236370792416b367a7d2d6b8e471b06b331cdmtklein        fBitmaps.push_back(bitmap);
91271a236370792416b367a7d2d6b8e471b06b331cdmtklein    } else {
913e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein        // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage.
91471a236370792416b367a7d2d6b8e471b06b331cdmtklein        SkBitmap copy;
91571a236370792416b367a7d2d6b8e471b06b331cdmtklein        bitmap.copyTo(&copy);
91671a236370792416b367a7d2d6b8e471b06b331cdmtklein        copy.setImmutable();
91771a236370792416b367a7d2d6b8e471b06b331cdmtklein        fBitmaps.push_back(copy);
91871a236370792416b367a7d2d6b8e471b06b331cdmtklein    }
919e069400cabd0edd3db52bbf1958063d3ed12ef28mtklein    this->addInt(fBitmaps.count()-1);  // Remember, 0-based.
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addMatrix(const SkMatrix& matrix) {
923fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    fWriter.writeMatrix(matrix);
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
92646616af01b412ea984a516fda1ed8ec08e689f29mtkleinvoid SkPictureRecord::addPaintPtr(const SkPaint* paint) {
927afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onAddPaintPtr(paint);
928e2cb12a82ad924f7b134a9459b190213485c6a50commit-bot@chromium.org
92946616af01b412ea984a516fda1ed8ec08e689f29mtklein    if (paint) {
930a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein        fPaints.push_back(*paint);
931a74ce853c824c5ae30e219ddf46a61d91cc0ab2amtklein        this->addInt(fPaints.count());
93246616af01b412ea984a516fda1ed8ec08e689f29mtklein    } else {
93346616af01b412ea984a516fda1ed8ec08e689f29mtklein        this->addInt(0);
93446616af01b412ea984a516fda1ed8ec08e689f29mtklein    }
935cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org}
936cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org
9375a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comint SkPictureRecord::addPathToHeap(const SkPath& path) {
93871a236370792416b367a7d2d6b8e471b06b331cdmtklein    fPaths.push_back(path);
93971a236370792416b367a7d2d6b8e471b06b331cdmtklein    return fPaths.count();
9405a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com}
9415a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.com
9425a63f24558b84610e93c6d7b67d849b5ab435e51robertphillips@google.comvoid SkPictureRecord::addPath(const SkPath& path) {
943cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(this->addPathToHeap(path));
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
946b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkPictureRecord::addPatch(const SkPoint cubics[12]) {
947b3c9d1c33caf325aada244204215eb790c228c12dandov    fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
948963137b75c0a1fe91f35e9826742f36309f5e65ddandov}
949963137b75c0a1fe91f35e9826742f36309f5e65ddandov
9509b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkPictureRecord::addPicture(const SkPicture* picture) {
9519b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    int index = fPictureRefs.find(picture);
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (index < 0) {    // not found
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        index = fPictureRefs.count();
9549b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips        *fPictureRefs.append() = picture;
9559b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips        picture->ref();
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // follow the convention of recording a 1-based index
958cb6adecd4d37ae23c89a473a5f648584e0428520robertphillips@google.com    this->addInt(index + 1);
9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addPoint(const SkPoint& point) {
9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writePoint(point);
9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
96482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addPoints(const SkPoint pts[], int count) {
9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeMul4(pts, count * sizeof(SkPoint));
9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
96968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.orgvoid SkPictureRecord::addNoOp() {
97068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    size_t size = kUInt32Size; // op
97168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    this->addDraw(NOOP, &size);
97268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org}
97368250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRect(const SkRect& rect) {
9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writeRect(rect);
9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRectPtr(const SkRect* rect) {
9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fWriter.writeBool(rect != NULL)) {
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWriter.writeRect(*rect);
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
984f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.comvoid SkPictureRecord::addIRect(const SkIRect& rect) {
985f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com    fWriter.write(&rect, sizeof(rect));
986f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com}
987f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addIRectPtr(const SkIRect* rect) {
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fWriter.writeBool(rect != NULL)) {
9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9944ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkPictureRecord::addRRect(const SkRRect& rrect) {
9954ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    fWriter.writeRRect(rrect);
9964ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
9974ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addRegion(const SkRegion& region) {
999fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    fWriter.writeRegion(region);
10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPictureRecord::addText(const void* text, size_t byteLength) {
1003afdada2eabdef47a59e08c884b2beb1af3f31aa5hendrikw    fContentInfo.onDrawText();
1004dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org    addInt(SkToInt(byteLength));
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fWriter.writePad(text, byteLength);
10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1008b7425173f96e93b090787e2386ba5f022b6c2869fmalitavoid SkPictureRecord::addTextBlob(const SkTextBlob *blob) {
1009dd1e9f75969c72da53657e58a080c47b30f64140jbroman    int index = fTextBlobRefs.count();
1010dd1e9f75969c72da53657e58a080c47b30f64140jbroman    *fTextBlobRefs.append() = blob;
1011dd1e9f75969c72da53657e58a080c47b30f64140jbroman    blob->ref();
1012b7425173f96e93b090787e2386ba5f022b6c2869fmalita    // follow the convention of recording a 1-based index
1013b7425173f96e93b090787e2386ba5f022b6c2869fmalita    this->addInt(index + 1);
1014b7425173f96e93b090787e2386ba5f022b6c2869fmalita}
1015b7425173f96e93b090787e2386ba5f022b6c2869fmalita
10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1018