SkFlattenable.cpp revision d26147adbbdca85f07dff432025afee0c8614387
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFlattenable.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypeface.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com#include "SkMatrix.h"
12f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com#include "SkRegion.h"
13f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com
14f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.comvoid SkReadMatrix(SkReader32* reader, SkMatrix* matrix) {
15f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    size_t size = matrix->unflatten(reader->peek());
16f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    SkASSERT(SkAlign4(size) == size);
17f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    (void)reader->skip(size);
18f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com}
19f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com
20f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.comvoid SkWriteMatrix(SkWriter32* writer, const SkMatrix& matrix) {
21f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    size_t size = matrix.flatten(NULL);
22f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    SkASSERT(SkAlign4(size) == size);
23f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    matrix.flatten(writer->reserve(size));
24f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com}
25f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com
26f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.comvoid SkReadRegion(SkReader32* reader, SkRegion* rgn) {
27f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    size_t size = rgn->unflatten(reader->peek());
28f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    SkASSERT(SkAlign4(size) == size);
29f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    (void)reader->skip(size);
30f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com}
31f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com
32f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.comvoid SkWriteRegion(SkWriter32* writer, const SkRegion& rgn) {
33f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    size_t size = rgn.flatten(NULL);
34f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    SkASSERT(SkAlign4(size) == size);
35f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com    rgn.flatten(writer->reserve(size));
36f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com}
37f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com
38f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com///////////////////////////////////////////////////////////////////////////////
39f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenable::flatten(SkFlattenableWriteBuffer&)
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  we don't write anything at the moment, but this allows our subclasses
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to not know that, since we want them to always call INHERITED::flatten()
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        in their code.
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenableReadBuffer::SkFlattenableReadBuffer() {
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCArray = NULL;
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCCount = 0;
5482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFArray = NULL;
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFCount = 0;
5782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
586bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    fFactoryTDArray = NULL;
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryArray = NULL;
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryCount = 0;
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) :
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        INHERITED(data, 1024 * 1024) {
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCArray = NULL;
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCCount = 0;
6782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFArray = NULL;
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFCount = 0;
7082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
716bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    fFactoryTDArray = NULL;
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryArray = NULL;
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryCount = 0;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size)
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(data, size) {
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCArray = NULL;
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCCount = 0;
8082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFArray = NULL;
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFCount = 0;
8382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
846bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    fFactoryTDArray = NULL;
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryArray = NULL;
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryCount = 0;
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkTypeface* SkFlattenableReadBuffer::readTypeface() {
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t index = this->readU32();
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0 == index || index > (unsigned)fTFCount) {
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (index) {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf("====== typeface index %d\n", index);
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fTFArray);
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fTFArray[index - 1];
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRefCnt* SkFlattenableReadBuffer::readRefCnt() {
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t index = this->readU32();
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0 == index || index > (unsigned)fRCCount) {
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fRCArray);
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fRCArray[index - 1];
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenable* SkFlattenableReadBuffer::readFlattenable() {
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFlattenable::Factory factory = NULL;
11482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fFactoryCount > 0) {
1166bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        int32_t index = this->readU32();
1176bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        if (0 == index) {
1186bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            return NULL; // writer failed to give us the flattenable
1196bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        }
1206bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        index = -index; // we stored the negative of the index
1216bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        index -= 1;     // we stored the index-base-1
12213649ce32f41774a49760e50083c13c349cb0b5creed@google.com        SkASSERT(index < fFactoryCount);
1236bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        factory = fFactoryArray[index];
1246bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    } else if (fFactoryTDArray) {
1256bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        const int32_t* peek = (const int32_t*)this->peek();
1266bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        if (*peek <= 0) {
1276bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            int32_t index = this->readU32();
1286bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            if (0 == index) {
1296bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                return NULL; // writer failed to give us the flattenable
1306bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            }
1316bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            index = -index; // we stored the negative of the index
1326bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            index -= 1;     // we stored the index-base-1
1336bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            factory = (*fFactoryTDArray)[index];
1346bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        } else {
1356bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            const char* name = this->readString();
1366bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            factory = SkFlattenable::NameToFactory(name);
1376bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            if (factory) {
1386bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                SkASSERT(fFactoryTDArray->find(factory) < 0);
1396bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                *fFactoryTDArray->append() = factory;
1406bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            } else {
1416bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com//                SkDebugf("can't find factory for [%s]\n", name);
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1436bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            // if we didn't find a factory, that's our failure, not the writer's,
1446bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            // so we fall through, so we can skip the sizeRecorded data.
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        factory = (SkFlattenable::Factory)readFunctionPtr();
1486bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        if (NULL == factory) {
1496bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            return NULL; // writer failed to give us the flattenable
1506bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        }
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1536bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    // if we get here, factory may still be null, but if that is the case, the
1546bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    // failure was ours, not the writer.
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFlattenable* obj = NULL;
1566bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    uint32_t sizeRecorded = this->readU32();
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (factory) {
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t offset = this->offset();
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        obj = (*factory)(*this);
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // check that we read the amount we expected
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t sizeRead = this->offset() - offset;
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (sizeRecorded != sizeRead) {
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // we could try to fix up the offset...
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sk_throw();
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1666bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    } else {
1676bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        // we must skip the remaining data
1686bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        this->skip(sizeRecorded);
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return obj;
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid* SkFlattenableReadBuffer::readFunctionPtr() {
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void* proc;
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->read(&proc, sizeof(proc));
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return proc;
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) :
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        INHERITED(minSize) {
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFlags = (Flags)0;
184e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    fRCSet = NULL;
185e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    fTFSet = NULL;
186e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    fFactorySet = NULL;
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
190e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    SkSafeUnref(fRCSet);
191e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    SkSafeUnref(fTFSet);
192e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    SkSafeUnref(fFactorySet);
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
195e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.orgSkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
196e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    SkRefCnt_SafeAssign(fRCSet, rec);
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec;
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
200e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.orgSkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
201e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    SkRefCnt_SafeAssign(fTFSet, rec);
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec;
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
205e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.orgSkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
206e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    SkRefCnt_SafeAssign(fFactorySet, rec);
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec;
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
211e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    if (NULL == obj || NULL == fTFSet) {
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->write32(0);
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
214e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org        this->write32(fTFSet->add(obj));
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
219e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    if (NULL == obj || NULL == fRCSet) {
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->write32(0);
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
222e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org        this->write32(fRCSet->add(obj));
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
2276bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    /*
2286bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *  If we have a factoryset, then the first 32bits tell us...
2296bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *       0: failure to write the flattenable
2306bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *      <0: we store the negative of the (1-based) index
2316bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *      >0: the length of the name
2326bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *  If we don't have a factoryset, then the first "ptr" is either the
2336bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *  factory, or null for failure.
2346bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *
2356bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *  The distinction is important, since 0-index is 32bits (always), but a
2366bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *  0-functionptr might be 32 or 64 bits.
2376bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     */
2386bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFlattenable::Factory factory = NULL;
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (flattenable) {
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        factory = flattenable->getFactory();
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2436bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    if (NULL == factory) {
2446bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        if (fFactorySet) {
2456bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            this->write32(0);
2466bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        } else {
2476bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            this->writeFunctionPtr(NULL);
2486bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        }
2496bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        return;
2506bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    }
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2526bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    /*
2536bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *  We can write 1 of 3 versions of the flattenable:
2546bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *  1.  function-ptr : this is the fastest for the reader, but assumes that
2556bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *      the writer and reader are in the same process.
2566bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *  2.  index into fFactorySet : This is assumes the writer will later
2576bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *      resolve the function-ptrs into strings for its reader. SkPicture
2586bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *      does exactly this, by writing a table of names (matching the indices)
2596bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *      up front in its serialized form.
2606bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *  3.  names : Reuse fFactorySet to store indices, but only after we've
2616bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *      written the name the first time. SkGPipe uses this technique, as it
2626bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *      doesn't require the reader to be told to know the table of names
2636bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     *      up front.
2646bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com     */
265e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org    if (fFactorySet) {
2666bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        if (this->inlineFactoryNames()) {
2676bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            int index = fFactorySet->find(factory);
2686bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            if (index) {
2696bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                // we write the negative of the index, to distinguish it from
2706bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                // the length of a string
2716bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                this->write32(-index);
2726bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            } else {
2736bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                const char* name = SkFlattenable::FactoryToName(factory);
2746bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                if (NULL == name) {
2756bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                    this->write32(0);
2766bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                    return;
2776bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                }
2786bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                this->writeString(name);
2796bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                index = fFactorySet->add(factory);
2806bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            }
2816bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        } else {
2826bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            // we write the negative of the index, to distinguish it from
2836bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com            // the length of a string
28413649ce32f41774a49760e50083c13c349cb0b5creed@google.com            this->write32(-(int)fFactorySet->add(factory));
2856bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com        }
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->writeFunctionPtr((void*)factory);
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2906bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    // make room for the size of the flatttened object
2916bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    (void)this->reserve(sizeof(uint32_t));
2926bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    // record the current size, so we can subtract after the object writes.
2936bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    uint32_t offset = this->size();
2946bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    // now flatten the object
2956bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    flattenable->flatten(*this);
2966bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    uint32_t objSize = this->size() - offset;
2976bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    // record the obj's size
2986bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com    *this->peek32(offset - sizeof(uint32_t)) = objSize;
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) {
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *(void**)this->reserve(sizeof(void*)) = proc;
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
307e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.orgSkRefCntSet::~SkRefCntSet() {
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // call this now, while our decPtr() is sill in scope
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->reset();
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
312e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.orgvoid SkRefCntSet::incPtr(void* ptr) {
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ((SkRefCnt*)ptr)->ref();
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
316e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.orgvoid SkRefCntSet::decPtr(void* ptr) {
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ((SkRefCnt*)ptr)->unref();
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MAX_PAIR_COUNT  64
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct Pair {
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char*             fName;
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFlattenable::Factory  fFactory;
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int gCount;
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic Pair gPairs[MAX_PAIR_COUNT];
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenable::Register(const char name[], Factory factory) {
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(name);
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(factory);
33782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static bool gOnce;
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!gOnce) {
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        gCount = 0;
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        gOnce = true;
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
34382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(gCount < MAX_PAIR_COUNT);
34582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    gPairs[gCount].fName = name;
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    gPairs[gCount].fFactory = factory;
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    gCount += 1;
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
351d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
352d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comstatic void report_no_entries(const char* functionName) {
353d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com    if (!gCount) {
354d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com        SkDebugf("%s has no registered name/factory pairs."
355d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com            " Call SkGraphics::InitializeGlobals() at process initialization"
356d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com            " time.", functionName);
357d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com    }
358d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com}
359d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com#endif
360d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
362d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
363d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com    report_no_entries(__FUNCTION__);
364d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com#endif
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const Pair* pairs = gPairs;
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int i = gCount - 1; i >= 0; --i) {
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (strcmp(pairs[i].fName, name) == 0) {
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return pairs[i].fFactory;
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst char* SkFlattenable::FactoryToName(Factory fact) {
375d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
376d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com    report_no_entries(__FUNCTION__);
377d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com#endif
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const Pair* pairs = gPairs;
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int i = gCount - 1; i >= 0; --i) {
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (pairs[i].fFactory == fact) {
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return pairs[i].fName;
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkFlattenable::toDumpString(SkString* str) const {
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
390