1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/*
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2011 Google Inc.
4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com *
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */
8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPictureRecord.h"
9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkTSearch.h"
10dc8630fa3915d6b1a6cfef385ac6846cf78e0b94junov@chromium.org#include "SkPixelRef.h"
117a7e655343617093a5eea37c7a556602a1bb0576reed@google.com#include "SkRRect.h"
126e832b50c712743d821e01829b127b86271a7ebbrileya@google.com#include "SkBBoxHierarchy.h"
130ae46d53f7563f38a4c07085a036ac2e5490ce1cjunov@chromium.org#include "SkDevice.h"
146e832b50c712743d821e01829b127b86271a7ebbrileya@google.com#include "SkPictureStateTree.h"
15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define MIN_WRITER_SIZE 16384
17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define HEAP_BLOCK_SIZE 4096
18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
19d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.orgenum {
20118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com    // just need a value that save or getSaveCount would never return
21d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org    kNoInitialSave = -1,
22d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org};
23d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org
24f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com// A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
25f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.comstatic int const kUInt32Size = 4;
26f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com
276f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.comstatic const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
286f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.comstatic const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
296f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
30118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.comSkPictureRecord::SkPictureRecord(uint32_t flags, SkDevice* device) :
31118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com        INHERITED(device),
322ec44813c09bf94914e2baf07ae155ac2366909crobertphillips@google.com        fBoundingHierarchy(NULL),
332ec44813c09bf94914e2baf07ae155ac2366909crobertphillips@google.com        fStateTree(NULL),
34a9aa73ae674668fe929a04566a17804eefe7938edjsollen@google.com        fFlattenableHeap(HEAP_BLOCK_SIZE),
35a9aa73ae674668fe929a04566a17804eefe7938edjsollen@google.com        fMatrices(&fFlattenableHeap),
36a9aa73ae674668fe929a04566a17804eefe7938edjsollen@google.com        fPaints(&fFlattenableHeap),
37a9aa73ae674668fe929a04566a17804eefe7938edjsollen@google.com        fRegions(&fFlattenableHeap),
38ba64210404187e9ef7a9d55135695aa0bd745467djsollen@google.com        fWriter(MIN_WRITER_SIZE),
39ba64210404187e9ef7a9d55135695aa0bd745467djsollen@google.com        fRecordFlags(flags) {
40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPointBytes = fRectBytes = fTextBytes = 0;
42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPointWrites = fRectWrites = fTextWrites = 0;
43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fRestoreOffsetStack.setReserve(32);
46919114813d58933c9d9433b141e0222c34b700b1reed@google.com
473855f87fcb9a9e590b6c94d742395415a3f1b06cdjsollen@google.com    fBitmapHeap = SkNEW(SkBitmapHeap);
483855f87fcb9a9e590b6c94d742395415a3f1b06cdjsollen@google.com    fFlattenableHeap.setBitmapStorage(fBitmapHeap);
49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPathHeap = NULL;   // lazy allocate
506bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org    fFirstSavedLayerIndex = kNoSavedLayerIndex;
51118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com
52118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com    fInitialSaveCount = kNoInitialSave;
53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkPictureRecord::~SkPictureRecord() {
563855f87fcb9a9e590b6c94d742395415a3f1b06cdjsollen@google.com    SkSafeUnref(fBitmapHeap);
57a9aa73ae674668fe929a04566a17804eefe7938edjsollen@google.com    SkSafeUnref(fPathHeap);
586e832b50c712743d821e01829b127b86271a7ebbrileya@google.com    SkSafeUnref(fBoundingHierarchy);
596e832b50c712743d821e01829b127b86271a7ebbrileya@google.com    SkSafeUnref(fStateTree);
60a9aa73ae674668fe929a04566a17804eefe7938edjsollen@google.com    fFlattenableHeap.setBitmapStorage(NULL);
61a9aa73ae674668fe929a04566a17804eefe7938edjsollen@google.com    fPictureRefs.unrefAll();
62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
666f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com// Return the offset of the paint inside a given op's byte stream. A zero
676f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com// return value means there is no paint (and you really shouldn't be calling
686f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com// this method)
696f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.comstatic inline uint32_t getPaintOffset(DrawType op, uint32_t opSize) {
706f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // These offsets are where the paint would be if the op size doesn't overflow
71bb6a8d87c696dade8c4730cd09b55c0ecae06462skia.committer@gmail.com    static const uint8_t gPaintOffsets[LAST_DRAWTYPE_ENUM + 1] = {
726f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // UNUSED - no paint
736f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // CLIP_PATH - no paint
746f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // CLIP_REGION - no paint
756f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // CLIP_RECT - no paint
766f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // CLIP_RRECT - no paint
776f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // CONCAT - no paint
786f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_BITMAP - right after op code
796f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_BITMAP_MATRIX - right after op code
806f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_BITMAP_NINE - right after op code
816f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_BITMAP_RECT_TO_RECT - right after op code
826f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // DRAW_CLEAR - no paint
836f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // DRAW_DATA - no paint
846f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_OVAL - right after op code
856f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_PAINT - right after op code
866f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_PATH - right after op code
876f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // DRAW_PICTURE - no paint
886f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_POINTS - right after op code
896f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_POS_TEXT - right after op code
906f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_POS_TEXT_TOP_BOTTOM - right after op code
916f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_POS_TEXT_H - right after op code
926f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_POS_TEXT_H_TOP_BOTTOM - right after op code
936f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_RECT - right after op code
946f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_RRECT - right after op code
956f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_SPRITE - right after op code
966f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_TEXT - right after op code
976f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_TEXT_ON_PATH - right after op code
986f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_TEXT_TOP_BOTTOM - right after op code
996f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        1,  // DRAW_VERTICES - right after op code
1006f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // RESTORE - no paint
1016f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // ROTATE - no paint
1026f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // SAVE - no paint
103bb6a8d87c696dade8c4730cd09b55c0ecae06462skia.committer@gmail.com        0,  // SAVE_LAYER - see below - this paint's location varies
1046f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // SCALE - no paint
1056f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // SET_MATRIX - no paint
1066f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // SKEW - no paint
1076f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // TRANSLATE - no paint
1086f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        0,  // NOOP - no paint
109aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com        0,  // BEGIN_GROUP - no paint
110aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com        0,  // COMMENT - no paint
111aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com        0,  // END_GROUP - no paint
112bb6a8d87c696dade8c4730cd09b55c0ecae06462skia.committer@gmail.com    };
1136f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
1146f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1);
1156f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
1166f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
1176f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    int overflow = 0;
1186f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    if (0 != (opSize & ~MASK_24) || opSize == MASK_24) {
1196f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        // This op's size overflows so an extra uint32_t will be written
1206f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        // after the op code
1216f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        overflow = sizeof(uint32_t);
1226f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    }
1236f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
1246f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    if (SAVE_LAYER == op) {
1256f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
1266f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        static const uint32_t kSaveLayerWithBoundsPaintOffset = 2 * kUInt32Size + sizeof(SkRect);
1276f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
1286f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        if (kSaveLayerNoBoundsSize == opSize) {
1296f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com            return kSaveLayerNoBoundsPaintOffset + overflow;
1306f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        } else {
1316f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com            SkASSERT(kSaveLayerWithBoundsSize == opSize);
1326f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com            return kSaveLayerWithBoundsPaintOffset + overflow;
1336f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        }
1346f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    }
1356f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
1366f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(0 != gPaintOffsets[op]);   // really shouldn't be calling this method
1376f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
1386f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com}
1396f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
140d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.orgSkDevice* SkPictureRecord::setDevice(SkDevice* device) {
141118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com    SkASSERT(!"eeek, don't try to change the device on a recording canvas");
142118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com    return this->INHERITED::setDevice(device);
143d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org}
144d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org
145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkPictureRecord::save(SaveFlags flags) {
1462522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    // record the offset to us, making it non-positive to distinguish a save
1472522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    // from a clip entry.
1482522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    fRestoreOffsetStack.push(-(int32_t)fWriter.size());
14969a95d1bf40aa3b197983cdb1df79b4441b31de1skia.committer@gmail.com
150f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + flags
151f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 2 * kUInt32Size;
152f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(SAVE, &size);
153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(flags);
154919114813d58933c9d9433b141e0222c34b700b1reed@google.com
155f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->INHERITED::save(flags);
157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint,
160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                               SaveFlags flags) {
1612522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    // record the offset to us, making it non-positive to distinguish a save
1622522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    // from a clip entry.
1632522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    fRestoreOffsetStack.push(-(int32_t)fWriter.size());
16469a95d1bf40aa3b197983cdb1df79b4441b31de1skia.committer@gmail.com
165f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + bool for 'bounds'
1664b7bb5ccda62759133bc13e69f5247c91ef6a61eskia.committer@gmail.com    uint32_t size = 2 * kUInt32Size;
167f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (NULL != bounds) {
168f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        size += sizeof(*bounds); // + rect
169f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    }
170f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // + paint index + flags
171f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    size += 2 * kUInt32Size;
172f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com
1736f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
1746f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
175f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(SAVE_LAYER, &size);
176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addRectPtr(bounds);
1776f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(SAVE_LAYER, size) == fWriter.size());
178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaintPtr(paint);
179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(flags);
180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1816bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org    if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
1826bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org        fFirstSavedLayerIndex = fRestoreOffsetStack.count();
1836bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org    }
1846bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org
185f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
1868c8c0c0b8ef2b3c2266c57fecc3f365ec2ea27c9reed@android.com    /*  Don't actually call saveLayer, because that will try to allocate an
1878c8c0c0b8ef2b3c2266c57fecc3f365ec2ea27c9reed@android.com        offscreen device (potentially very big) which we don't actually need
1888c8c0c0b8ef2b3c2266c57fecc3f365ec2ea27c9reed@android.com        at this time (and may not be able to afford since during record our
1898c8c0c0b8ef2b3c2266c57fecc3f365ec2ea27c9reed@android.com        clip starts out the size of the picture, which is often much larger
1908c8c0c0b8ef2b3c2266c57fecc3f365ec2ea27c9reed@android.com        than the size of the actual device we'll use during playback).
1918c8c0c0b8ef2b3c2266c57fecc3f365ec2ea27c9reed@android.com     */
1921457ba3cbcaa320a1d1dd50bc128fda46e23b9fdjunov@chromium.org    int count = this->INHERITED::save(flags);
1931457ba3cbcaa320a1d1dd50bc128fda46e23b9fdjunov@chromium.org    this->clipRectBounds(bounds, flags, NULL);
1941457ba3cbcaa320a1d1dd50bc128fda46e23b9fdjunov@chromium.org    return count;
195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1976bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.orgbool SkPictureRecord::isDrawingToLayer() const {
1986bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org    return fFirstSavedLayerIndex != kNoSavedLayerIndex;
1996bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org}
2006bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org
201f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com/*
202f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com * Read the op code from 'offset' in 'writer' and extract the size too.
203f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com */
204f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.comstatic DrawType peek_op_and_size(SkWriter32* writer, int32_t offset, uint32_t* size) {
205f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t* peek = writer->peek32(offset);
206f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com
207f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t op;
208f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    UNPACK_8_24(*peek, op, *size);
209f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (MASK_24 == *size) {
210f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        // size required its own slot right after the op code
2114b7bb5ccda62759133bc13e69f5247c91ef6a61eskia.committer@gmail.com        *size = *writer->peek32(offset+kUInt32Size);
212f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    }
213f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    return (DrawType) op;
2142522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com}
2152522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com
2162522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com#ifdef TRACK_COLLAPSE_STATS
2172522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    static int gCollapseCount, gCollapseCalls;
2182522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com#endif
2192522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com
2206f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com// Is the supplied paint simply a color?
2216f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.comstatic bool is_simple(const SkPaint& p) {
222bb6a8d87c696dade8c4730cd09b55c0ecae06462skia.committer@gmail.com    intptr_t orAccum = (intptr_t)p.getPathEffect()  |
2236f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com                       (intptr_t)p.getShader()      |
2246f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com                       (intptr_t)p.getXfermode()    |
2256f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com                       (intptr_t)p.getMaskFilter()  |
2266f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com                       (intptr_t)p.getColorFilter() |
2276f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com                       (intptr_t)p.getRasterizer()  |
2286f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com                       (intptr_t)p.getLooper()      |
2296f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com                       (intptr_t)p.getImageFilter();
2306f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    return 0 == orAccum;
2316f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com}
2326f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
233ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com// CommandInfos are fed to the 'match' method and filled in with command
234010f1a42e85d8c8587869e436d093d7ed40a4598skia.committer@gmail.com// information.
235ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.comstruct CommandInfo {
236ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    DrawType fActualOp;
237ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    uint32_t fOffset;
238ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    uint32_t fSize;
239ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com};
240ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
2412522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com/*
242ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * Attempt to match the provided pattern of commands starting at 'offset'
243010f1a42e85d8c8587869e436d093d7ed40a4598skia.committer@gmail.com * in the byte stream and stopping at the end of the stream. Upon success,
244ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * return true with all the pattern information filled out in the result
245ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * array (i.e., actual ops, offsets and sizes).
246ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * Note this method skips any NOOPs seen in the stream
247ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com */
248ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.comstatic bool match(SkWriter32* writer, uint32_t offset,
249ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                  int* pattern, CommandInfo* result, int numCommands) {
250003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com    SkASSERT(offset < writer->size());
251ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
252ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    uint32_t curOffset = offset;
253ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    uint32_t curSize = 0;
254003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com    int numMatched;
255003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com    for (numMatched = 0; numMatched < numCommands && curOffset < writer->size(); ++numMatched) {
256ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        DrawType op = peek_op_and_size(writer, curOffset, &curSize);
257ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        while (NOOP == op && curOffset < writer->size()) {
258ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com            curOffset += curSize;
259ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com            op = peek_op_and_size(writer, curOffset, &curSize);
260ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        }
261ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
262ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        if (curOffset >= writer->size()) {
263ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com            return false; // ran out of byte stream
264ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        }
265ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
266003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com        if (kDRAW_BITMAP_FLAVOR == pattern[numMatched]) {
267ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com            if (DRAW_BITMAP != op && DRAW_BITMAP_MATRIX != op &&
268ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                DRAW_BITMAP_NINE != op && DRAW_BITMAP_RECT_TO_RECT != op) {
269ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                return false;
270ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com            }
271003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com        } else if (op != pattern[numMatched]) {
272ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com            return false;
273ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        }
274ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
275003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com        result[numMatched].fActualOp = op;
276003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com        result[numMatched].fOffset = curOffset;
277003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com        result[numMatched].fSize = curSize;
278ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
279ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        curOffset += curSize;
280ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    }
281ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
282003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com    if (numMatched != numCommands) {
283003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com        return false;
284003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com    }
285003c9cfab8027c666586a7d46c2ac6ca0a18957brobertphillips@google.com
286ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    curOffset += curSize;
287ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    if (curOffset < writer->size()) {
288ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        // Something else between the last command and the end of the stream
289ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        return false;
290ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    }
291ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
292ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    return true;
293ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com}
294ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
295ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com// temporarily here to make code review easier
296ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.comstatic bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
297ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                                                 SkPaintDictionary* paintDict,
298ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                                                 const CommandInfo& saveLayerInfo,
299ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                                                 const CommandInfo& dbmInfo);
300ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
301ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com/*
302010f1a42e85d8c8587869e436d093d7ed40a4598skia.committer@gmail.com * Restore has just been called (but not recorded), look back at the
3036f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com * matching save* and see if we are in the configuration:
3046f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com *   SAVE_LAYER
3056f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com *       DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_RECT
3066f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com *   RESTORE
3076f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com * where the saveLayer's color can be moved into the drawBitmap*'s paint
3086f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com */
309bb6a8d87c696dade8c4730cd09b55c0ecae06462skia.committer@gmail.comstatic bool remove_save_layer1(SkWriter32* writer, int32_t offset,
3106f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com                               SkPaintDictionary* paintDict) {
3116f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // back up to the save block
3126f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // TODO: add a stack to track save*/restore offsets rather than searching backwards
3136f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    while (offset > 0) {
3146f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        offset = *writer->peek32(offset);
3156f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    }
3166f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
317ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    int pattern[] = { SAVE_LAYER, kDRAW_BITMAP_FLAVOR, /* RESTORE */ };
318ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    CommandInfo result[SK_ARRAY_COUNT(pattern)];
319ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
320ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) {
321ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        return false;
3226f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    }
3236f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
324ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    if (kSaveLayerWithBoundsSize == result[0].fSize) {
3256f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        // The saveLayer's bound can offset where the dbm is drawn
3266f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        return false;
3276f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    }
3286f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
3296f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
330ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    return merge_savelayer_paint_into_drawbitmp(writer, paintDict,
331ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                                                result[0], result[1]);
332ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com}
3336f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
334ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com/*
335ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * Convert the command code located at 'offset' to a NOOP. Leave the size
336ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * field alone so the NOOP can be skipped later.
337ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com */
338ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.comstatic void convert_command_to_noop(SkWriter32* writer, uint32_t offset) {
339ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    uint32_t* ptr = writer->peek32(offset);
340ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    *ptr = (*ptr & MASK_24) | (NOOP << 24);
341ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com}
3426f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
343ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com/*
344ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * Attempt to merge the saveLayer's paint into the drawBitmap*'s paint.
345ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * Return true on success; false otherwise.
346ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com */
347ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.comstatic bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
348ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                                                 SkPaintDictionary* paintDict,
349ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                                                 const CommandInfo& saveLayerInfo,
350ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                                                 const CommandInfo& dbmInfo) {
351ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    SkASSERT(SAVE_LAYER == saveLayerInfo.fActualOp);
352010f1a42e85d8c8587869e436d093d7ed40a4598skia.committer@gmail.com    SkASSERT(DRAW_BITMAP == dbmInfo.fActualOp ||
353ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com             DRAW_BITMAP_MATRIX == dbmInfo.fActualOp ||
354010f1a42e85d8c8587869e436d093d7ed40a4598skia.committer@gmail.com             DRAW_BITMAP_NINE == dbmInfo.fActualOp ||
355ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com             DRAW_BITMAP_RECT_TO_RECT == dbmInfo.fActualOp);
356ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
357ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    uint32_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize);
358ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    uint32_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize);
3596f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
3606f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // we have a match, now we need to get the paints involved
36144509a03478a28f60b0600a9c86223b43bbc601erobertphillips@google.com    uint32_t dbmPaintId = *writer->peek32(dbmInfo.fOffset+dbmPaintOffset);
36244509a03478a28f60b0600a9c86223b43bbc601erobertphillips@google.com    uint32_t saveLayerPaintId = *writer->peek32(saveLayerInfo.fOffset+slPaintOffset);
3636f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
3646f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    if (0 == saveLayerPaintId) {
3656f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        // In this case the saveLayer/restore isn't needed at all - just kill the saveLayer
3666f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        // and signal the caller (by returning true) to not add the RESTORE op
367ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        convert_command_to_noop(writer, saveLayerInfo.fOffset);
3686f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        return true;
369bb6a8d87c696dade8c4730cd09b55c0ecae06462skia.committer@gmail.com    }
370bb6a8d87c696dade8c4730cd09b55c0ecae06462skia.committer@gmail.com
3716f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    if (0 == dbmPaintId) {
3726f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        // In this case just make the DBM* use the saveLayer's paint, kill the saveLayer
3736f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        // and signal the caller (by returning true) to not add the RESTORE op
374ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        convert_command_to_noop(writer, saveLayerInfo.fOffset);
375ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        uint32_t* ptr = writer->peek32(dbmInfo.fOffset+dbmPaintOffset);
3766f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        SkASSERT(0 == *ptr);
3776f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        *ptr = saveLayerPaintId;
3786f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        return true;
379bb6a8d87c696dade8c4730cd09b55c0ecae06462skia.committer@gmail.com    }
3806f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
3816f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkAutoTDelete<SkPaint> saveLayerPaint(paintDict->unflatten(saveLayerPaintId));
3826f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    if (NULL == saveLayerPaint.get() || !is_simple(*saveLayerPaint)) {
3836f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        return false;
3846f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    }
3856f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
3866f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // For this optimization we only fold the saveLayer and drawBitmapRect
3876f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // together if the saveLayer's draw is simple (i.e., no fancy effects) and
3886f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // and the only difference in the colors is that the saveLayer's can have
3896f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // an alpha while the drawBitmapRect's is opaque.
3906f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // TODO: it should be possible to fold them together even if they both
3916f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // have different non-255 alphas
3926f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkColor layerColor = saveLayerPaint->getColor() | 0xFF000000; // force opaque
3936f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
3946f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkAutoTDelete<SkPaint> dbmPaint(paintDict->unflatten(dbmPaintId));
3956f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    if (NULL == dbmPaint.get() || dbmPaint->getColor() != layerColor) {
3966f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        return false;
3976f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    }
398bb6a8d87c696dade8c4730cd09b55c0ecae06462skia.committer@gmail.com
3996f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkColor newColor = SkColorSetA(dbmPaint->getColor(),
4006f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com                                   SkColorGetA(saveLayerPaint->getColor()));
4016f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    dbmPaint->setColor(newColor);
4026f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
4036f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    const SkFlatData* data = paintDict->findAndReturnFlat(*dbmPaint);
4046f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    if (NULL == data) {
4056f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        return false;
4066f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    }
4076f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
4086f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    // kill the saveLayer and alter the DBMR2R's paint to be the modified one
409ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    convert_command_to_noop(writer, saveLayerInfo.fOffset);
410ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    uint32_t* ptr = writer->peek32(dbmInfo.fOffset+dbmPaintOffset);
411ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    SkASSERT(dbmPaintId == *ptr);
4126f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    *ptr = data->index();
4136f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    return true;
4146f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com}
4156f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
416ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com/*
417010f1a42e85d8c8587869e436d093d7ed40a4598skia.committer@gmail.com * Restore has just been called (but not recorded), look back at the
418ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * matching save* and see if we are in the configuration:
4197a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com *   SAVE_LAYER (with NULL == bounds)
420ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com *      SAVE
421ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com *         CLIP_RECT
422ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com *         DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_RECT
423ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com *      RESTORE
424ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com *   RESTORE
425ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * where the saveLayer's color can be moved into the drawBitmap*'s paint
426ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com */
427ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.comstatic bool remove_save_layer2(SkWriter32* writer, int32_t offset,
428ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                               SkPaintDictionary* paintDict) {
429ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
430ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    // back up to the save block
431ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    // TODO: add a stack to track save*/restore offsets rather than searching backwards
432ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    while (offset > 0) {
433ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        offset = *writer->peek32(offset);
434ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    }
435ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
436ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE, /* RESTORE */ };
437ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    CommandInfo result[SK_ARRAY_COUNT(pattern)];
438ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
439ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) {
440ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        return false;
441ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    }
442ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
443ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    if (kSaveLayerWithBoundsSize == result[0].fSize) {
444ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        // The saveLayer's bound can offset where the dbm is drawn
445ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        return false;
446ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    }
447ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
448ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com    return merge_savelayer_paint_into_drawbitmp(writer, paintDict,
449ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                                                result[0], result[3]);
450ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com}
4516f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com
4526f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com/*
4536f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com *  Restore has just been called (but not recorded), so look back at the
4542522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com *  matching save(), and see if we can eliminate the pair of them, due to no
4552522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com *  intervening matrix/clip calls.
4562522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com *
4572522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com *  If so, update the writer and return true, in which case we won't even record
4582522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com *  the restore() call. If we still need the restore(), return false.
4592522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com */
460ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.comstatic bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset,
461ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                                       SkPaintDictionary* paintDict) {
4622522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com#ifdef TRACK_COLLAPSE_STATS
4632522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    gCollapseCalls += 1;
4642522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com#endif
4652522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com
4662522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    int32_t restoreOffset = (int32_t)writer->size();
4672522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com
4682522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    // back up to the save block
4692522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    while (offset > 0) {
4702522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com        offset = *writer->peek32(offset);
4712522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    }
4722522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com
4732522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    // now offset points to a save
4742522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    offset = -offset;
475f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t opSize;
476f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    DrawType op = peek_op_and_size(writer, offset, &opSize);
477f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (SAVE_LAYER == op) {
4782522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com        // not ready to cull these out yet (mrr)
4792522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com        return false;
4802522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    }
481f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    SkASSERT(SAVE == op);
4822522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com
4832522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    // Walk forward until we get back to either a draw-verb (abort) or we hit
4842522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    // our restore (success).
4852522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    int32_t saveOffset = offset;
4862522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com
487f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    offset += opSize;
4882522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    while (offset < restoreOffset) {
489f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        op = peek_op_and_size(writer, offset, &opSize);
490f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        if ((op > CONCAT && op < ROTATE) || (SAVE_LAYER == op)) {
4912522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com            // drawing verb, abort
4922522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com            return false;
4932522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com        }
4942522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com        offset += opSize;
4952522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    }
49669a95d1bf40aa3b197983cdb1df79b4441b31de1skia.committer@gmail.com
4972522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com#ifdef TRACK_COLLAPSE_STATS
4982522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    gCollapseCount += 1;
4992522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    SkDebugf("Collapse [%d out of %d] %g%spn", gCollapseCount, gCollapseCalls,
5002522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com             (double)gCollapseCount / gCollapseCalls, "%");
5012522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com#endif
5022522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com
5032522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    writer->rewindToOffset(saveOffset);
5042522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    return true;
5052522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com}
5062522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com
507ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.comtypedef bool (*PictureRecordOptProc)(SkWriter32* writer, int32_t offset,
508ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com                                     SkPaintDictionary* paintDict);
50947c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.orgenum PictureRecordOptType {
51047c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    kRewind_OptType,  // Optimization rewinds the command stream
51147c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    kCollapseSaveLayer_OptType,  // Optimization eliminates a save/restore pair
51247c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org};
513ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
51447c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.orgstruct PictureRecordOpt {
51547c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    PictureRecordOptProc fProc;
51647c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    PictureRecordOptType fType;
51747c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org};
518ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com/*
519ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * A list of the optimizations that are tried upon seeing a restore
520ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com * TODO: add a real API for such optimizations
521ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com *       Add the ability to fire optimizations on any op (not just RESTORE)
522ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com */
52347c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.orgstatic const PictureRecordOpt gPictureRecordOpts[] = {
52447c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    { collapse_save_clip_restore, kRewind_OptType },
52547c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    { remove_save_layer1,         kCollapseSaveLayer_OptType },
52647c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    { remove_save_layer2,         kCollapseSaveLayer_OptType }
527ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com};
528ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
52947c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org// This is called after an optimization has been applied to the command stream
53047c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org// in order to adjust the contents and state of the bounding box hierarchy and
53147c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org// state tree to reflect the optimization.
53247c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.orgstatic void apply_optimization_to_bbh(PictureRecordOptType opt, SkPictureStateTree* stateTree,
53347c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org                                      SkBBoxHierarchy* boundingHierarchy) {
53447c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    switch (opt) {
53547c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    case kCollapseSaveLayer_OptType:
53623c343d51379aa187837799d908e039a4f20d176robertphillips@google.com        if (NULL != stateTree) {
53723c343d51379aa187837799d908e039a4f20d176robertphillips@google.com            stateTree->saveCollapsed();
53823c343d51379aa187837799d908e039a4f20d176robertphillips@google.com        }
53947c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org        break;
54047c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    case kRewind_OptType:
54147c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org        if (NULL != boundingHierarchy) {
54247c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org            boundingHierarchy->rewindInserts();
54347c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org        }
54447c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org        // Note: No need to touch the state tree for this to work correctly.
54547c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org        // Unused branches do not burden the playback, and pruning the tree
54647c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org        // would be O(N^2), so it is best to leave it alone.
54747c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org        break;
54847c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    default:
54947c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org        SkASSERT(0);
55047c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org    }
55147c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org}
55247c2076e9e3b4777af036acfa5ff258a38cca586commit-bot@chromium.org
553bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::restore() {
554d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org    // FIXME: SkDeferredCanvas needs to be refactored to respect
555d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org    // save/restore balancing so that the following test can be
556d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org    // turned on permanently.
557d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org#if 0
558d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org    SkASSERT(fRestoreOffsetStack.count() > 1);
559d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org#endif
560d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org
561b2c8220d34736e284e0a226a6848698b4734e16areed@android.com    // check for underflow
562b2c8220d34736e284e0a226a6848698b4734e16areed@android.com    if (fRestoreOffsetStack.count() == 0) {
563b2c8220d34736e284e0a226a6848698b4734e16areed@android.com        return;
564b2c8220d34736e284e0a226a6848698b4734e16areed@android.com    }
565b2c8220d34736e284e0a226a6848698b4734e16areed@android.com
5666bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org    if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) {
5676bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org        fFirstSavedLayerIndex = kNoSavedLayerIndex;
5686bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org    }
5696bfd74c3d62f40c933ade44051e8a407e017b882junov@chromium.org
570f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset, size;
5716209598697a786a985fd69fefba7624adbfe9f72robertphillips@google.com    size_t opt = 0;
5727a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com    if (!(fRecordFlags & SkPicture::kDisableRecordOptimizations_RecordingFlag)) {
5737a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com        for (opt = 0; opt < SK_ARRAY_COUNT(gPictureRecordOpts); ++opt) {
5747a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com            if ((*gPictureRecordOpts[opt].fProc)(&fWriter, fRestoreOffsetStack.top(), &fPaints)) {
5757a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com                // Some optimization fired so don't add the RESTORE
5767a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com                size = 0;
5777a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com                initialOffset = fWriter.size();
5787a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com                apply_optimization_to_bbh(gPictureRecordOpts[opt].fType,
5797a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com                                          fStateTree, fBoundingHierarchy);
5807a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com                break;
5817a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com            }
582ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        }
583a43230c68078db52692a925d272d418eceb1cbf2skia.committer@gmail.com    }
584ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com
5857a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com    if ((fRecordFlags & SkPicture::kDisableRecordOptimizations_RecordingFlag) ||
5867a4d57dbf30ef4f55f1f763ebfc6a17877712c50robertphillips@google.com        SK_ARRAY_COUNT(gPictureRecordOpts) == opt) {
587ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        // No optimization fired so add the RESTORE
5882522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com        fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.size());
589ed26ab55a24455c94c5333540cf654ddea706423robertphillips@google.com        size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
590f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        initialOffset = this->addDraw(RESTORE, &size);
5912522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    }
5922522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com
593b2c8220d34736e284e0a226a6848698b4734e16areed@android.com    fRestoreOffsetStack.pop();
5944d379fa7dc3f3fc20542babdc5861cad0aef5f25reed@android.com
595f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
596bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->INHERITED::restore();
597bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
598bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
599bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPictureRecord::translate(SkScalar dx, SkScalar dy) {
600f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + dx + dy
601f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
602f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(TRANSLATE, &size);
603bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(dx);
604bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(dy);
605f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
606bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->INHERITED::translate(dx, dy);
607bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
608bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
609bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPictureRecord::scale(SkScalar sx, SkScalar sy) {
610f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + sx + sy
611f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
612f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(SCALE, &size);
613bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(sx);
614bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(sy);
615f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
616bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->INHERITED::scale(sx, sy);
617bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
618bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
619bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPictureRecord::rotate(SkScalar degrees) {
620f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + degrees
621f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 1 * kUInt32Size + sizeof(SkScalar);
622f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(ROTATE, &size);
623919114813d58933c9d9433b141e0222c34b700b1reed@google.com    addScalar(degrees);
624f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
625bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->INHERITED::rotate(degrees);
626bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
627bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
628bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPictureRecord::skew(SkScalar sx, SkScalar sy) {
629f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + sx + sy
630f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
631f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(SKEW, &size);
632bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(sx);
633bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(sy);
634f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
635bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->INHERITED::skew(sx, sy);
636bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
637bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
638bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPictureRecord::concat(const SkMatrix& matrix) {
639f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(fWriter.size(), 0);
640f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + matrix index
641f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 2 * kUInt32Size;
642f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(CONCAT, &size);
643bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addMatrix(matrix);
644f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
645bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->INHERITED::concat(matrix);
646bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
647bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
6485605182165ca299f085c4cb7b45a0bf3489cd372reed@android.comvoid SkPictureRecord::setMatrix(const SkMatrix& matrix) {
649f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(fWriter.size(), 0);
650f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + matrix index
651f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 2 * kUInt32Size;
652f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(SET_MATRIX, &size);
6535605182165ca299f085c4cb7b45a0bf3489cd372reed@android.com    addMatrix(matrix);
654f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
6555605182165ca299f085c4cb7b45a0bf3489cd372reed@android.com    this->INHERITED::setMatrix(matrix);
6565605182165ca299f085c4cb7b45a0bf3489cd372reed@android.com}
6575605182165ca299f085c4cb7b45a0bf3489cd372reed@android.com
658e4a68b51971c02effb0799213408821930adbac7reed@google.comstatic bool regionOpExpands(SkRegion::Op op) {
659e4a68b51971c02effb0799213408821930adbac7reed@google.com    switch (op) {
660e4a68b51971c02effb0799213408821930adbac7reed@google.com        case SkRegion::kUnion_Op:
661e4a68b51971c02effb0799213408821930adbac7reed@google.com        case SkRegion::kXOR_Op:
662e4a68b51971c02effb0799213408821930adbac7reed@google.com        case SkRegion::kReverseDifference_Op:
663e4a68b51971c02effb0799213408821930adbac7reed@google.com        case SkRegion::kReplace_Op:
664e4a68b51971c02effb0799213408821930adbac7reed@google.com            return true;
665e4a68b51971c02effb0799213408821930adbac7reed@google.com        case SkRegion::kIntersect_Op:
666e4a68b51971c02effb0799213408821930adbac7reed@google.com        case SkRegion::kDifference_Op:
667e4a68b51971c02effb0799213408821930adbac7reed@google.com            return false;
668e4a68b51971c02effb0799213408821930adbac7reed@google.com        default:
6692d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com            SkDEBUGFAIL("unknown region op");
670e4a68b51971c02effb0799213408821930adbac7reed@google.com            return false;
671e4a68b51971c02effb0799213408821930adbac7reed@google.com    }
672e4a68b51971c02effb0799213408821930adbac7reed@google.com}
673e4a68b51971c02effb0799213408821930adbac7reed@google.com
6746f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.comvoid SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
6752522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    int32_t offset = fRestoreOffsetStack.top();
6762522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    while (offset > 0) {
677c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org        uint32_t* peek = fWriter.peek32(offset);
678c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org        offset = *peek;
679c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org        *peek = restoreOffset;
680c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org    }
68169a95d1bf40aa3b197983cdb1df79b4441b31de1skia.committer@gmail.com
6822522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com#ifdef SK_DEBUG
6832522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    // assert that the final offset value points to a save verb
684f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t opSize;
685f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
6862522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com    SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
6872522d74ffa4a622327fb1a14c1f0e2482d2466e0reed@google.com#endif
688c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org}
689c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org
690118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.comvoid SkPictureRecord::beginRecording() {
691118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com    // we have to call this *after* our constructor, to ensure that it gets
692118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com    // recorded. This is balanced by restoreToCount() call from endRecording,
693118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com    // which in-turn calls our overridden restore(), so those get recorded too.
694118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com    fInitialSaveCount = this->save(kMatrixClip_SaveFlag);
695118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com}
696118a6d00c3089c0fcfce67919bbbeb37adda6423reed@google.com
6979aa18db116c81f6fbd563a6c28111c65bb56d742junov@chromium.orgvoid SkPictureRecord::endRecording() {
698d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org    SkASSERT(kNoInitialSave != fInitialSaveCount);
699d84ed564a00a67019a345ea545ca63ab514533f7junov@chromium.org    this->restoreToCount(fInitialSaveCount);
7009aa18db116c81f6fbd563a6c28111c65bb56d742junov@chromium.org}
7019aa18db116c81f6fbd563a6c28111c65bb56d742junov@chromium.org
702c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.orgvoid SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
70327943ec75fd82ea3c33fc15410fa032a6fcdcf98reed@google.com    if (fRestoreOffsetStack.isEmpty()) {
70427943ec75fd82ea3c33fc15410fa032a6fcdcf98reed@google.com        return;
70527943ec75fd82ea3c33fc15410fa032a6fcdcf98reed@google.com    }
70627943ec75fd82ea3c33fc15410fa032a6fcdcf98reed@google.com
707e4a68b51971c02effb0799213408821930adbac7reed@google.com    if (regionOpExpands(op)) {
708e4a68b51971c02effb0799213408821930adbac7reed@google.com        // Run back through any previous clip ops, and mark their offset to
709e4a68b51971c02effb0799213408821930adbac7reed@google.com        // be 0, disabling their ability to trigger a jump-to-restore, otherwise
710e4a68b51971c02effb0799213408821930adbac7reed@google.com        // they could hide this clips ability to expand the clip (i.e. go from
711e4a68b51971c02effb0799213408821930adbac7reed@google.com        // empty to non-empty).
712c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org        fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
713e4a68b51971c02effb0799213408821930adbac7reed@google.com    }
7148c331d260c7fe604a69b6ace405a4c6cd160cf17vandebo@chromium.org
715e4a68b51971c02effb0799213408821930adbac7reed@google.com    size_t offset = fWriter.size();
716c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org    // The RestoreOffset field is initially filled with a placeholder
717c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org    // value that points to the offset of the previous RestoreOffset
718c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org    // in the current stack level, thus forming a linked list so that
719935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    // the restore offsets can be filled in when the corresponding
720c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org    // restore command is recorded.
721e4a68b51971c02effb0799213408821930adbac7reed@google.com    addInt(fRestoreOffsetStack.top());
722e4a68b51971c02effb0799213408821930adbac7reed@google.com    fRestoreOffsetStack.top() = offset;
723e4a68b51971c02effb0799213408821930adbac7reed@google.com}
724e4a68b51971c02effb0799213408821930adbac7reed@google.com
7257e93ed91c3173a963cc17ef6e34b731b577b1250reed@google.combool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
7269484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    // id + rect + clip params
7279484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    uint32_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
728be48b20dc81e0160a0902207e1a40d042b83d237robertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
7299484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
7309484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com        // + restore offset
7319484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com        size += kUInt32Size;
7329484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    }
733f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(CLIP_RECT, &size);
734bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addRect(rect);
735c1de2b00dbdaeeb2541041ce2b0b2439fd51f80ereed@google.com    addInt(ClipParams_pack(op, doAA));
736c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org    recordRestoreOffsetPlaceholder(op);
7370edc7a59032f7f611bf6843be47564bc89f247d9skia.committer@gmail.com
738f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
7397954ac06ca868007cae83863c0ba546a85607751reed@google.com    return this->INHERITED::clipRect(rect, op, doAA);
740528d8cb43c755e51e09255afced6bd913fa2eabareed@google.com}
741528d8cb43c755e51e09255afced6bd913fa2eabareed@google.com
7427a7e655343617093a5eea37c7a556602a1bb0576reed@google.combool SkPictureRecord::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
7437a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    if (rrect.isRect()) {
7447a7e655343617093a5eea37c7a556602a1bb0576reed@google.com        return this->SkPictureRecord::clipRect(rrect.getBounds(), op, doAA);
7457a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    }
7467a7e655343617093a5eea37c7a556602a1bb0576reed@google.com
7479484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    // op + rrect + clip params
7489484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    uint32_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
749be48b20dc81e0160a0902207e1a40d042b83d237robertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
7509484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
7519484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com        // + restore offset
7529484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com        size += kUInt32Size;
7539484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    }
754f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(CLIP_RRECT, &size);
7557a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    addRRect(rrect);
7567a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    addInt(ClipParams_pack(op, doAA));
7577a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    recordRestoreOffsetPlaceholder(op);
7580edc7a59032f7f611bf6843be47564bc89f247d9skia.committer@gmail.com
759f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
7607a7e655343617093a5eea37c7a556602a1bb0576reed@google.com
7617a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
762e153aa9fb9692ec8b9834da27c6918b8900cce96junov@chromium.org        return this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
7637a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    } else {
7647a7e655343617093a5eea37c7a556602a1bb0576reed@google.com        return this->INHERITED::clipRRect(rrect, op, doAA);
7657a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    }
7667a7e655343617093a5eea37c7a556602a1bb0576reed@google.com}
7677a7e655343617093a5eea37c7a556602a1bb0576reed@google.com
7687e93ed91c3173a963cc17ef6e34b731b577b1250reed@google.combool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
76990520a50d191eaf3ca75b4ed48a3c3b2dd9ff755robertphillips@google.com
77090520a50d191eaf3ca75b4ed48a3c3b2dd9ff755robertphillips@google.com    SkRect r;
771a1654bc2d17b9eed2c20cd7d33d18f409a67e64breed@google.com    if (!path.isInverseFillType() && path.isRect(&r)) {
77290520a50d191eaf3ca75b4ed48a3c3b2dd9ff755robertphillips@google.com        return this->clipRect(r, op, doAA);
77390520a50d191eaf3ca75b4ed48a3c3b2dd9ff755robertphillips@google.com    }
77490520a50d191eaf3ca75b4ed48a3c3b2dd9ff755robertphillips@google.com
7759484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    // op + path index + clip params
7769484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    uint32_t size = 3 * kUInt32Size;
777be48b20dc81e0160a0902207e1a40d042b83d237robertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
7789484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
7799484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com        // + restore offset
7809484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com        size += kUInt32Size;
7819484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    }
782f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(CLIP_PATH, &size);
783bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPath(path);
784c1de2b00dbdaeeb2541041ce2b0b2439fd51f80ereed@google.com    addInt(ClipParams_pack(op, doAA));
785c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org    recordRestoreOffsetPlaceholder(op);
786919114813d58933c9d9433b141e0222c34b700b1reed@google.com
787f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
788919114813d58933c9d9433b141e0222c34b700b1reed@google.com
789c4a55d734d36f634765d63b9adfb69ddbc6182fereed@android.com    if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
790e153aa9fb9692ec8b9834da27c6918b8900cce96junov@chromium.org        return this->updateClipConservativelyUsingBounds(path.getBounds(), op,
7910ae46d53f7563f38a4c07085a036ac2e5490ce1cjunov@chromium.org                                                         path.isInverseFillType());
792c4a55d734d36f634765d63b9adfb69ddbc6182fereed@android.com    } else {
7937e93ed91c3173a963cc17ef6e34b731b577b1250reed@google.com        return this->INHERITED::clipPath(path, op, doAA);
794c4a55d734d36f634765d63b9adfb69ddbc6182fereed@android.com    }
795bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
796bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
797bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
7989484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    // op + region index + clip params
7999484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    uint32_t size = 3 * kUInt32Size;
800be48b20dc81e0160a0902207e1a40d042b83d237robertphillips@google.com    // recordRestoreOffsetPlaceholder doesn't always write an offset
8019484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    if (!fRestoreOffsetStack.isEmpty()) {
8029484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com        // + restore offset
8039484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com        size += kUInt32Size;
8049484f707225bfb04a436bf6ba3fdf923b0dadfearobertphillips@google.com    }
8054b7bb5ccda62759133bc13e69f5247c91ef6a61eskia.committer@gmail.com    uint32_t initialOffset = this->addDraw(CLIP_REGION, &size);
806bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addRegion(region);
807c1de2b00dbdaeeb2541041ce2b0b2439fd51f80ereed@google.com    addInt(ClipParams_pack(op, false));
808c74b2c43b91702aac3f4f7d1dae4754da3952dbbjunov@chromium.org    recordRestoreOffsetPlaceholder(op);
809919114813d58933c9d9433b141e0222c34b700b1reed@google.com
810f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
811bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->INHERITED::clipRegion(region, op);
812bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
813bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
81405e7118ee88a85f068ed6d449d46ed0a41f79320reed@google.comvoid SkPictureRecord::clear(SkColor color) {
815f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + color
816f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 2 * kUInt32Size;
817f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_CLEAR, &size);
81805e7118ee88a85f068ed6d449d46ed0a41f79320reed@google.com    addInt(color);
819f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
82005e7118ee88a85f068ed6d449d46ed0a41f79320reed@google.com}
82105e7118ee88a85f068ed6d449d46ed0a41f79320reed@google.com
822bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::drawPaint(const SkPaint& paint) {
823f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index
824f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 2 * kUInt32Size;
825f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_PAINT, &size);
8266f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_PAINT, size) == fWriter.size());
827bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaint(paint);
828f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
829bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
830bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
831bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
832f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com                                 const SkPaint& paint) {
833f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + mode + count + point data
834f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
835f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_POINTS, &size);
8366f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_POINTS, size) == fWriter.size());
837bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaint(paint);
838bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(mode);
839bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(count);
840bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fWriter.writeMul4(pts, count * sizeof(SkPoint));
841f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
842bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
843bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
8447a7e655343617093a5eea37c7a556602a1bb0576reed@google.comvoid SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) {
845f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + rect
846f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 2 * kUInt32Size + sizeof(oval);
847f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_OVAL, &size);
8486f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_OVAL, size) == fWriter.size());
8497a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    addPaint(paint);
8507a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    addRect(oval);
851f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
8527a7e655343617093a5eea37c7a556602a1bb0576reed@google.com}
8537a7e655343617093a5eea37c7a556602a1bb0576reed@google.com
854bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
855f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + rect
856f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 2 * kUInt32Size + sizeof(rect);
857f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_RECT, &size);
8586f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_RECT, size) == fWriter.size());
859bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaint(paint);
860bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addRect(rect);
861f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
862bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
863bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
8647a7e655343617093a5eea37c7a556602a1bb0576reed@google.comvoid SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
8657a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    if (rrect.isRect()) {
8669da4a363fe67d99d18d970b5bab36a8112961bbcjunov@chromium.org        this->SkPictureRecord::drawRect(rrect.getBounds(), paint);
8677a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    } else if (rrect.isOval()) {
8689da4a363fe67d99d18d970b5bab36a8112961bbcjunov@chromium.org        this->SkPictureRecord::drawOval(rrect.getBounds(), paint);
8697a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    } else {
870f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        // op + paint index + rrect
8719da4a363fe67d99d18d970b5bab36a8112961bbcjunov@chromium.org        uint32_t initialOffset, size;
872f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
873f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        initialOffset = this->addDraw(DRAW_RRECT, &size);
8746f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com        SkASSERT(initialOffset+getPaintOffset(DRAW_RRECT, size) == fWriter.size());
8757a7e655343617093a5eea37c7a556602a1bb0576reed@google.com        addPaint(paint);
8767a7e655343617093a5eea37c7a556602a1bb0576reed@google.com        addRRect(rrect);
8779da4a363fe67d99d18d970b5bab36a8112961bbcjunov@chromium.org        validate(initialOffset, size);
8787a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    }
8797a7e655343617093a5eea37c7a556602a1bb0576reed@google.com}
8807a7e655343617093a5eea37c7a556602a1bb0576reed@google.com
881bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
882f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + path index
883f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 3 * kUInt32Size;
884f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_PATH, &size);
8856f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_PATH, size) == fWriter.size());
886bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaint(paint);
887bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPath(path);
888f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
889bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
890bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
891bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
892bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        const SkPaint* paint = NULL) {
893f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + bitmap index + left + top
894f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
895f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
8966f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP, size) == fWriter.size());
897bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaintPtr(paint);
898bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addBitmap(bitmap);
899bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(left);
900bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(top);
901f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
902bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
903bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
9043b4aeaece7522f100f25bcb2214214acaf7891e8reed@google.comvoid SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
905bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                            const SkRect& dst, const SkPaint* paint) {
906f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // id + paint index + bitmap index + bool for 'src'
9074b7bb5ccda62759133bc13e69f5247c91ef6a61eskia.committer@gmail.com    uint32_t size = 4 * kUInt32Size;
908f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (NULL != src) {
909f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        size += sizeof(*src);   // + rect
910f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    }
911f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    size += sizeof(dst);        // + rect
912f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com
913f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
9146f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size) == fWriter.size());
915bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaintPtr(paint);
916bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addBitmap(bitmap);
9173b4aeaece7522f100f25bcb2214214acaf7891e8reed@google.com    addRectPtr(src);  // may be null
918bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addRect(dst);
919f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
920bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
921bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
922bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
9233f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com                                       const SkPaint* paint) {
924f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // id + paint index + bitmap index + matrix index
925f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 4 * kUInt32Size;
926f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
9276f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_MATRIX, size) == fWriter.size());
928bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaintPtr(paint);
929bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addBitmap(bitmap);
930bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addMatrix(matrix);
931f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
932bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
933bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
9343f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.comvoid SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
9353f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com                                     const SkRect& dst, const SkPaint* paint) {
936f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + bitmap id + center + dst rect
9374b7bb5ccda62759133bc13e69f5247c91ef6a61eskia.committer@gmail.com    uint32_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
938f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
9396f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_NINE, size) == fWriter.size());
9403f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com    addPaintPtr(paint);
9413f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com    addBitmap(bitmap);
9423f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com    addIRect(center);
9433f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com    addRect(dst);
944f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
9453f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com}
9463f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com
947bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
948bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        const SkPaint* paint = NULL) {
949f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + bitmap index + left + top
950f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 5 * kUInt32Size;
951f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
9526f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_SPRITE, size) == fWriter.size());
953bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaintPtr(paint);
954bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addBitmap(bitmap);
955bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(left);
956bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(top);
957f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
958bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
959bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
9608878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com// Return fontmetrics.fTop,fBottom in topbot[0,1], after they have been
9618878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com// tweaked by paint.computeFastBounds().
9628878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com//
9638878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.comstatic void computeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2]) {
964bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkPaint::FontMetrics metrics;
965bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    paint.getFontMetrics(&metrics);
966bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRect bounds;
967bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // construct a rect so we can see any adjustments from the paint.
968bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // we use 0,1 for left,right, just so the rect isn't empty
9698878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com    bounds.set(0, metrics.fTop, SK_Scalar1, metrics.fBottom);
970bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    (void)paint.computeFastBounds(bounds, &bounds);
9718878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com    topbot[0] = bounds.fTop;
9728878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com    topbot[1] = bounds.fBottom;
9738878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com}
9748878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com
975fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.orgvoid SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData& flat,
9768878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com                                              SkScalar minY, SkScalar maxY) {
97775714eee0c7480aa4787b976da221739fe5d8977junov@chromium.org    if (!flat.isTopBotWritten()) {
97875714eee0c7480aa4787b976da221739fe5d8977junov@chromium.org        computeFontMetricsTopBottom(paint, flat.writableTopBot());
97975714eee0c7480aa4787b976da221739fe5d8977junov@chromium.org        SkASSERT(flat.isTopBotWritten());
9808878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com    }
98175714eee0c7480aa4787b976da221739fe5d8977junov@chromium.org    addScalar(flat.topBot()[0] + minY);
98275714eee0c7480aa4787b976da221739fe5d8977junov@chromium.org    addScalar(flat.topBot()[1] + maxY);
983bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
984bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
985919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
986bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                      SkScalar y, const SkPaint& paint) {
9876ec9ab295d7beac041d9751b928a77501cafb46dreed@google.com    bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
988919114813d58933c9d9433b141e0222c34b700b1reed@google.com
989f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + length + 'length' worth of chars + x + y
990f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
991f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (fast) {
992f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        size += 2 * sizeof(SkScalar); // + top & bottom
993f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    }
994f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com
9956f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    DrawType op = fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT;
9966f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    uint32_t initialOffset = this->addDraw(op, &size);
9976f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.size());
998fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org    const SkFlatData* flatPaintData = addPaint(paint);
999fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org    SkASSERT(flatPaintData);
1000bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addText(text, byteLength);
1001bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(x);
1002bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(y);
1003bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (fast) {
1004fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org        addFontMetricsTopBottom(paint, *flatPaintData, y, y);
1005bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1006f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
1007bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1008bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1009919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkPictureRecord::drawPosText(const void* text, size_t byteLength,
1010bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                         const SkPoint pos[], const SkPaint& paint) {
1011bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t points = paint.countText(text, byteLength);
1012bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (0 == points)
1013bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
1014bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1015bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool canUseDrawH = true;
1016d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com    SkScalar minY = pos[0].fY;
1017d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com    SkScalar maxY = pos[0].fY;
1018bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // check if the caller really should have used drawPosTextH()
1019bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
1020bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const SkScalar firstY = pos[0].fY;
1021bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        for (size_t index = 1; index < points; index++) {
1022bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (pos[index].fY != firstY) {
1023bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                canUseDrawH = false;
1024d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com                if (pos[index].fY < minY) {
1025d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com                    minY = pos[index].fY;
1026d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com                } else if (pos[index].fY > maxY) {
1027d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com                    maxY = pos[index].fY;
1028d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com                }
1029bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
1030bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
1031bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1032919114813d58933c9d9433b141e0222c34b700b1reed@google.com
10336ec9ab295d7beac041d9751b928a77501cafb46dreed@google.com    bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds();
1034d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com    bool fast = canUseDrawH && fastBounds;
1035bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1036f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + length + 'length' worth of data + num points
1037f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
1038f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (canUseDrawH) {
1039f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        if (fast) {
1040f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com            size += 2 * sizeof(SkScalar); // + top & bottom
1041f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        }
1042f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        // + y-pos + actual x-point data
1043f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        size += sizeof(SkScalar) + points * sizeof(SkScalar);
1044f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    } else {
1045f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        // + x&y point data
1046f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        size += points * sizeof(SkPoint);
1047f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        if (fastBounds) {
1048f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com            size += 2 * sizeof(SkScalar); // + top & bottom
1049f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        }
1050f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    }
1051f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com
1052f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    DrawType op;
1053bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (fast) {
1054f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        op = DRAW_POS_TEXT_H_TOP_BOTTOM;
1055d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com    } else if (canUseDrawH) {
1056f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        op = DRAW_POS_TEXT_H;
1057d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com    } else if (fastBounds) {
1058f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        op = DRAW_POS_TEXT_TOP_BOTTOM;
1059bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    } else {
1060f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        op = DRAW_POS_TEXT;
1061bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1062f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(op, &size);
10636f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.size());
1064fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org    const SkFlatData* flatPaintData = addPaint(paint);
1065fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org    SkASSERT(flatPaintData);
1066bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addText(text, byteLength);
1067bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(points);
1068bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1069bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1070bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t start = fWriter.size();
1071bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1072bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (canUseDrawH) {
1073bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (fast) {
1074fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org            addFontMetricsTopBottom(paint, *flatPaintData, pos[0].fY, pos[0].fY);
1075bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
1076bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        addScalar(pos[0].fY);
1077bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
1078919114813d58933c9d9433b141e0222c34b700b1reed@google.com        for (size_t index = 0; index < points; index++)
1079bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            *xptr++ = pos[index].fX;
1080f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    } else {
1081bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fWriter.writeMul4(pos, points * sizeof(SkPoint));
1082d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com        if (fastBounds) {
1083fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org            addFontMetricsTopBottom(paint, *flatPaintData, minY, maxY);
1084d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com        }
1085bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1086bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1087bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPointBytes += fWriter.size() - start;
1088bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPointWrites += points;
1089bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1090f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
1091bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1092bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1093bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
1094bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                          const SkScalar xpos[], SkScalar constY,
1095bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                          const SkPaint& paint) {
1096bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t points = paint.countText(text, byteLength);
1097bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (0 == points)
1098bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
1099919114813d58933c9d9433b141e0222c34b700b1reed@google.com
11006ec9ab295d7beac041d9751b928a77501cafb46dreed@google.com    bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
1101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1102f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + length + 'length' worth of data + num points
1103f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
1104f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (fast) {
1105f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        size += 2 * sizeof(SkScalar); // + top & bottom
1106f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    }
1107f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // + y + the actual points
1108f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    size += 1 * kUInt32Size + points * sizeof(SkScalar);
1109f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com
11104b7bb5ccda62759133bc13e69f5247c91ef6a61eskia.committer@gmail.com    uint32_t initialOffset = this->addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H,
1111f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com                                           &size);
1112fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org    const SkFlatData* flatPaintData = addPaint(paint);
1113fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org    SkASSERT(flatPaintData);
1114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addText(text, byteLength);
1115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(points);
1116919114813d58933c9d9433b141e0222c34b700b1reed@google.com
1117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t start = fWriter.size();
1119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (fast) {
1121fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org        addFontMetricsTopBottom(paint, *flatPaintData, constY, constY);
1122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addScalar(constY);
1124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fWriter.writeMul4(xpos, points * sizeof(SkScalar));
1125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPointBytes += fWriter.size() - start;
1127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPointWrites += points;
1128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1129f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
1130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1132919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
1133919114813d58933c9d9433b141e0222c34b700b1reed@google.com                            const SkPath& path, const SkMatrix* matrix,
1134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                            const SkPaint& paint) {
1135f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + length + 'length' worth of data + path index + matrix index
1136f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * kUInt32Size;
1137f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
11386f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_TEXT_ON_PATH, size) == fWriter.size());
1139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaint(paint);
1140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addText(text, byteLength);
1141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPath(path);
1142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addMatrixPtr(matrix);
1143f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
1144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::drawPicture(SkPicture& picture) {
1147f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + picture index
1148f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 2 * kUInt32Size;
1149f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_PICTURE, &size);
1150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPicture(picture);
1151f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
1152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
1155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                          const SkPoint vertices[], const SkPoint texs[],
1156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                          const SkColor colors[], SkXfermode*,
1157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                          const uint16_t indices[], int indexCount,
1158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                          const SkPaint& paint) {
1159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t flags = 0;
1160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (texs) {
1161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        flags |= DRAW_VERTICES_HAS_TEXS;
1162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (colors) {
1164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        flags |= DRAW_VERTICES_HAS_COLORS;
1165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (indexCount > 0) {
1167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        flags |= DRAW_VERTICES_HAS_INDICES;
1168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1170f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + paint index + flags + vmode + vCount + vertices
1171f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
1172f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (flags & DRAW_VERTICES_HAS_TEXS) {
1173f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        size += vertexCount * sizeof(SkPoint);  // + uvs
1174f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    }
1175f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (flags & DRAW_VERTICES_HAS_COLORS) {
1176f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        size += vertexCount * sizeof(SkColor);  // + vert colors
1177f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    }
1178f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (flags & DRAW_VERTICES_HAS_INDICES) {
1179f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        // + num indices + indices
1180f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
1181f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    }
1182f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com
1183f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
11846f21d8fcd94955662af7e58c8a02d1a1136a0cf5robertphillips@google.com    SkASSERT(initialOffset+getPaintOffset(DRAW_VERTICES, size) == fWriter.size());
1185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPaint(paint);
1186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(flags);
1187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(vmode);
1188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(vertexCount);
1189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addPoints(vertices, vertexCount);
1190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (flags & DRAW_VERTICES_HAS_TEXS) {
1191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        addPoints(texs, vertexCount);
1192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (flags & DRAW_VERTICES_HAS_COLORS) {
1194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
1195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (flags & DRAW_VERTICES_HAS_INDICES) {
1197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        addInt(indexCount);
1198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fWriter.writePad(indices, indexCount * sizeof(uint16_t));
1199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1200f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
1201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
120345a0456bb1a80d41544bcab2e99aa8648b7eb6careed@android.comvoid SkPictureRecord::drawData(const void* data, size_t length) {
1204f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    // op + length + 'length' worth of data
1205f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    uint32_t size = 2 * kUInt32Size + SkAlign4(length);
12064b7bb5ccda62759133bc13e69f5247c91ef6a61eskia.committer@gmail.com    uint32_t initialOffset = this->addDraw(DRAW_DATA, &size);
120745a0456bb1a80d41544bcab2e99aa8648b7eb6careed@android.com    addInt(length);
120845a0456bb1a80d41544bcab2e99aa8648b7eb6careed@android.com    fWriter.writePad(data, length);
1209f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    validate(initialOffset, size);
121045a0456bb1a80d41544bcab2e99aa8648b7eb6careed@android.com}
121145a0456bb1a80d41544bcab2e99aa8648b7eb6careed@android.com
1212aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.comvoid SkPictureRecord::beginCommentGroup(const char* description) {
1213aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    // op/size + length of string + \0 terminated chars
1214aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    int length = strlen(description);
1215aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    uint32_t size = 2 * kUInt32Size + SkAlign4(length + 1);
1216aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    uint32_t initialOffset = this->addDraw(BEGIN_COMMENT_GROUP, &size);
1217aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    fWriter.writeString(description, length);
1218aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    validate(initialOffset, size);
1219aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com}
1220aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com
1221aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.comvoid SkPictureRecord::addComment(const char* kywd, const char* value) {
1222aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    // op/size + 2x length of string + 2x \0 terminated chars
1223aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    int kywdLen = strlen(kywd);
1224aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    int valueLen = strlen(value);
1225aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    uint32_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
1226aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    uint32_t initialOffset = this->addDraw(COMMENT, &size);
1227aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    fWriter.writeString(kywd, kywdLen);
1228aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    fWriter.writeString(value, valueLen);
1229aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    validate(initialOffset, size);
1230aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com}
1231aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com
1232aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.comvoid SkPictureRecord::endCommentGroup() {
1233aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    // op/size
1234aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    uint32_t size = 1 * kUInt32Size;
1235aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    uint32_t initialOffset = this->addDraw(END_COMMENT_GROUP, &size);
1236aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com    validate(initialOffset, size);
1237aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com}
1238aa62052fd968fb037fc17a1f2a3c1be34b4342bbrobertphillips@google.com
1239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
1240919114813d58933c9d9433b141e0222c34b700b1reed@google.com
1241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
1242735d1a2bef76d58b3fffd06136e24dc96d534f79scroggo@google.com    const int index = fBitmapHeap->insert(bitmap);
1243735d1a2bef76d58b3fffd06136e24dc96d534f79scroggo@google.com    // In debug builds, a bad return value from insert() will crash, allowing for debugging. In
1244735d1a2bef76d58b3fffd06136e24dc96d534f79scroggo@google.com    // release builds, the invalid value will be recorded so that the reader will know that there
1245735d1a2bef76d58b3fffd06136e24dc96d534f79scroggo@google.com    // was a problem.
1246735d1a2bef76d58b3fffd06136e24dc96d534f79scroggo@google.com    SkASSERT(index != SkBitmapHeap::INVALID_SLOT);
1247735d1a2bef76d58b3fffd06136e24dc96d534f79scroggo@google.com    addInt(index);
1248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addMatrix(const SkMatrix& matrix) {
1251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addMatrixPtr(&matrix);
1252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
125535e986d293340bf8cb8845e1fbf2cf13bfdac9acreed@google.com    this->addInt(matrix ? fMatrices.find(*matrix) : 0);
1256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1258fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.orgconst SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) {
1259fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org    const SkFlatData* data = paint ? fPaints.findAndReturnFlat(*paint) : NULL;
1260fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org    int index = data ? data->index() : 0;
12618878ff132d537e6bd4e682fbcc570f6a8b2ac689reed@google.com    this->addInt(index);
1262fc8ff2e8e6b71629b28b31e759f3551418f4ea13junov@chromium.org    return data;
1263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addPath(const SkPath& path) {
1266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (NULL == fPathHeap) {
1267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fPathHeap = SkNEW(SkPathHeap);
1268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(fPathHeap->append(path));
1270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addPicture(SkPicture& picture) {
1273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int index = fPictureRefs.find(&picture);
1274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (index < 0) {    // not found
1275bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        index = fPictureRefs.count();
1276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        *fPictureRefs.append() = &picture;
1277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        picture.ref();
1278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // follow the convention of recording a 1-based index
1280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(index + 1);
1281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addPoint(const SkPoint& point) {
1284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t start = fWriter.size();
1286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fWriter.writePoint(point);
1288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPointBytes += fWriter.size() - start;
1290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPointWrites++;
1291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1293919114813d58933c9d9433b141e0222c34b700b1reed@google.com
1294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addPoints(const SkPoint pts[], int count) {
1295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fWriter.writeMul4(pts, count * sizeof(SkPoint));
1296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPointBytes += count * sizeof(SkPoint);
1298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPointWrites++;
1299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addRect(const SkRect& rect) {
1303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t start = fWriter.size();
1305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fWriter.writeRect(rect);
1307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fRectBytes += fWriter.size() - start;
1309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fRectWrites++;
1310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addRectPtr(const SkRect* rect) {
1314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (fWriter.writeBool(rect != NULL)) {
1315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fWriter.writeRect(*rect);
1316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
13193f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.comvoid SkPictureRecord::addIRect(const SkIRect& rect) {
13203f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com    fWriter.write(&rect, sizeof(rect));
13213f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com}
13223f270706ca0ff7302b938355e6d481a6b5f04e4breed@google.com
1323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addIRectPtr(const SkIRect* rect) {
1324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (fWriter.writeBool(rect != NULL)) {
1325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
1326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
13297a7e655343617093a5eea37c7a556602a1bb0576reed@google.comvoid SkPictureRecord::addRRect(const SkRRect& rrect) {
13307a7e655343617093a5eea37c7a556602a1bb0576reed@google.com    fWriter.writeRRect(rrect);
13317a7e655343617093a5eea37c7a556602a1bb0576reed@google.com}
13327a7e655343617093a5eea37c7a556602a1bb0576reed@google.com
1333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addRegion(const SkRegion& region) {
133435e986d293340bf8cb8845e1fbf2cf13bfdac9acreed@google.com    addInt(fRegions.find(region));
1335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::addText(const void* text, size_t byteLength) {
1338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t start = fWriter.size();
1340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    addInt(byteLength);
1342bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fWriter.writePad(text, byteLength);
1343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fTextBytes += fWriter.size() - start;
1345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fTextWrites++;
1346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
1350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_SIZE
1352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comsize_t SkPictureRecord::size() const {
1353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t result = 0;
1354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t sizeData;
1355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bitmaps(&sizeData);
1356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    result += sizeData;
1357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    matrices(&sizeData);
1358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    result += sizeData;
1359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    paints(&sizeData);
1360bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    result += sizeData;
1361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    paths(&sizeData);
1362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    result += sizeData;
1363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    pictures(&sizeData);
1364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    result += sizeData;
1365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    regions(&sizeData);
1366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    result += sizeData;
1367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    result += streamlen();
1368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return result;
1369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkPictureRecord::bitmaps(size_t* size) const {
1372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t result = 0;
1373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int count = fBitmaps.count();
1374919114813d58933c9d9433b141e0222c34b700b1reed@google.com    for (int index = 0; index < count; index++)
1375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        result += sizeof(fBitmaps[index]) + fBitmaps[index]->size();
1376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    *size = result;
1377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return count;
1378bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkPictureRecord::matrices(size_t* size) const {
1381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int count = fMatrices.count();
1382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    *size = sizeof(fMatrices[0]) * count;
1383bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return count;
1384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1385bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkPictureRecord::paints(size_t* size) const {
1387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t result = 0;
1388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int count = fPaints.count();
1389919114813d58933c9d9433b141e0222c34b700b1reed@google.com    for (int index = 0; index < count; index++)
1390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        result += sizeof(fPaints[index]) + fPaints[index]->size();
1391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    *size = result;
1392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return count;
1393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1394bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1395bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkPictureRecord::paths(size_t* size) const {
1396bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t result = 0;
1397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int count = fPaths.count();
1398919114813d58933c9d9433b141e0222c34b700b1reed@google.com    for (int index = 0; index < count; index++)
1399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        result += sizeof(fPaths[index]) + fPaths[index]->size();
1400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    *size = result;
1401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return count;
1402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1403bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkPictureRecord::regions(size_t* size) const {
1405bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t result = 0;
1406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int count = fRegions.count();
1407919114813d58933c9d9433b141e0222c34b700b1reed@google.com    for (int index = 0; index < count; index++)
1408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        result += sizeof(fRegions[index]) + fRegions[index]->size();
1409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    *size = result;
1410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return count;
1411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comsize_t SkPictureRecord::streamlen() const {
1414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return fWriter.size();
1415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1416bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG_VALIDATE
1419f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.comvoid SkPictureRecord::validate(uint32_t initialOffset, uint32_t size) const {
1420f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    SkASSERT(fWriter.size() == initialOffset + size);
1421f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com
1422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    validateBitmaps();
1423bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    validateMatrices();
1424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    validatePaints();
1425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    validatePaths();
1426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    validateRegions();
1427bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::validateBitmaps() const {
1430f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    int count = fBitmapHeap->count();
1431bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT((unsigned) count < 0x1000);
1432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (int index = 0; index < count; index++) {
1433f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        const SkBitmap* bitPtr = fBitmapHeap->getBitmap(index);
1434bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(bitPtr);
1435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        bitPtr->validate();
1436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1439bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::validateMatrices() const {
1440bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int count = fMatrices.count();
1441bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT((unsigned) count < 0x1000);
1442bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (int index = 0; index < count; index++) {
1443f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        const SkFlatData* matrix = fMatrices[index];
1444bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(matrix);
1445f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com//        matrix->validate();
1446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1447bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1449bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::validatePaints() const {
1450bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int count = fPaints.count();
1451bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT((unsigned) count < 0x1000);
1452bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (int index = 0; index < count; index++) {
1453f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        const SkFlatData* paint = fPaints[index];
1454bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(paint);
1455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com//            paint->validate();
1456bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1457bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1458bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1459bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::validatePaths() const {
1460f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    if (NULL == fPathHeap) {
1461f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        return;
1462f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    }
1463f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com
1464f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com    int count = fPathHeap->count();
1465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT((unsigned) count < 0x1000);
1466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (int index = 0; index < count; index++) {
1467f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        const SkPath& path = (*fPathHeap)[index];
1468f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        path.validate();
1469bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1470bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1472bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPictureRecord::validateRegions() const {
1473bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int count = fRegions.count();
1474bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT((unsigned) count < 0x1000);
1475bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (int index = 0; index < count; index++) {
1476f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com        const SkFlatData* region = fRegions[index];
1477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(region);
1478f2a01d9185ed3a378410418de02dfc9fc6ecd725robertphillips@google.com//        region->validate();
1479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
1482