SkFlattenable.cpp revision 13649ce32f41774a49760e50083c13c349cb0b5c
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "SkFlattenable.h"
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypeface.h"
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMatrix.h"
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "SkRegion.h"
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkReadMatrix(SkReader32* reader, SkMatrix* matrix) {
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t size = matrix->unflatten(reader->peek());
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com    SkASSERT(SkAlign4(size) == size);
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (void)reader->skip(size);
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkWriteMatrix(SkWriter32* writer, const SkMatrix& matrix) {
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t size = matrix.flatten(NULL);
157ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.org    SkASSERT(SkAlign4(size) == size);
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.flatten(writer->reserve(size));
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkReadRegion(SkReader32* reader, SkRegion* rgn) {
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t size = rgn->unflatten(reader->peek());
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(SkAlign4(size) == size);
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (void)reader->skip(size);
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkWriteRegion(SkWriter32* writer, const SkRegion& rgn) {
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t size = rgn.flatten(NULL);
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(SkAlign4(size) == size);
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rgn.flatten(writer->reserve(size));
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenable::flatten(SkFlattenableWriteBuffer&)
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  we don't write anything at the moment, but this allows our subclasses
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to not know that, since we want them to always call INHERITED::flatten()
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        in their code.
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenableReadBuffer::SkFlattenableReadBuffer() {
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCArray = NULL;
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCCount = 0;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFArray = NULL;
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFCount = 0;
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryTDArray = NULL;
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryArray = NULL;
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryCount = 0;
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) :
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        INHERITED(data, 1024 * 1024) {
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCArray = NULL;
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCCount = 0;
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFArray = NULL;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFCount = 0;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryTDArray = NULL;
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryArray = NULL;
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryCount = 0;
67b530ef5869c5c64af8f3b3c62ed7711fe4325c9creed@google.com}
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size)
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(data, size) {
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCArray = NULL;
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCCount = 0;
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFArray = NULL;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFCount = 0;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryTDArray = NULL;
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryArray = NULL;
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactoryCount = 0;
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
820da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.comSkTypeface* SkFlattenableReadBuffer::readTypeface() {
830da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.com    uint32_t index = this->readU32();
840da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.com    if (0 == index || index > (unsigned)fTFCount) {
850da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.com        if (index) {
860da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.com            SkDebugf("====== typeface index %d\n", index);
870da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.com        }
880da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.com        return NULL;
890da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.com    } else {
900da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.com        SkASSERT(fTFArray);
910da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.com        return fTFArray[index - 1];
920da41dbf5bdf9614a3d2f1d3ebd959221bbac44breed@android.com    }
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
941271d78e8ff4cda0622a24dcec6063b50f6be051reed@google.com
951271d78e8ff4cda0622a24dcec6063b50f6be051reed@google.comSkRefCnt* SkFlattenableReadBuffer::readRefCnt() {
961271d78e8ff4cda0622a24dcec6063b50f6be051reed@google.com    uint32_t index = this->readU32();
971271d78e8ff4cda0622a24dcec6063b50f6be051reed@google.com    if (0 == index || index > (unsigned)fRCCount) {
98b158a82bc18b5535224e3ca315ee6d80c7ad899breed@google.com        return NULL;
991271d78e8ff4cda0622a24dcec6063b50f6be051reed@google.com    } else {
1001271d78e8ff4cda0622a24dcec6063b50f6be051reed@google.com        SkASSERT(fRCArray);
1011271d78e8ff4cda0622a24dcec6063b50f6be051reed@google.com        return fRCArray[index - 1];
1021271d78e8ff4cda0622a24dcec6063b50f6be051reed@google.com    }
1031271d78e8ff4cda0622a24dcec6063b50f6be051reed@google.com}
1041271d78e8ff4cda0622a24dcec6063b50f6be051reed@google.com
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenable* SkFlattenableReadBuffer::readFlattenable() {
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFlattenable::Factory factory = NULL;
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fFactoryCount > 0) {
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int32_t index = this->readU32();
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == index) {
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return NULL; // writer failed to give us the flattenable
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        index = -index; // we stored the negative of the index
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        index -= 1;     // we stored the index-base-1
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(index < fFactoryCount);
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        factory = fFactoryArray[index];
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else if (fFactoryTDArray) {
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const int32_t* peek = (const int32_t*)this->peek();
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (*peek <= 0) {
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int32_t index = this->readU32();
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (0 == index) {
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return NULL; // writer failed to give us the flattenable
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
124fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            index = -index; // we stored the negative of the index
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            index -= 1;     // we stored the index-base-1
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            factory = (*fFactoryTDArray)[index];
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const char* name = this->readString();
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            factory = SkFlattenable::NameToFactory(name);
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (factory) {
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT(fFactoryTDArray->find(factory) < 0);
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *fFactoryTDArray->append() = factory;
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//                SkDebugf("can't find factory for [%s]\n", name);
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // if we didn't find a factory, that's our failure, not the writer's,
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // so we fall through, so we can skip the sizeRecorded data.
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        factory = (SkFlattenable::Factory)readFunctionPtr();
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == factory) {
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return NULL; // writer failed to give us the flattenable
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we get here, factory may still be null, but if that is the case, the
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // failure was ours, not the writer.
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFlattenable* obj = NULL;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t sizeRecorded = this->readU32();
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (factory) {
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t offset = this->offset();
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        obj = (*factory)(*this);
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // check that we read the amount we expected
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t sizeRead = this->offset() - offset;
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (sizeRecorded != sizeRead) {
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // we could try to fix up the offset...
157ffe39bd3b66eb5090684959e7f2409346ab72d93tomhudson@google.com            sk_throw();
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we must skip the remaining data
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->skip(sizeRecorded);
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return obj;
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid* SkFlattenableReadBuffer::readFunctionPtr() {
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void* proc;
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->read(&proc, sizeof(proc));
169fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    return proc;
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
171fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) :
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        INHERITED(minSize) {
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFlags = (Flags)0;
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRCSet = NULL;
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTFSet = NULL;
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFactorySet = NULL;
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
182ffe39bd3b66eb5090684959e7f2409346ab72d93tomhudson@google.comSkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSafeUnref(fRCSet);
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSafeUnref(fTFSet);
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSafeUnref(fFactorySet);
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fRCSet, rec);
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec;
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fTFSet, rec);
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec;
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fFactorySet, rec);
200ffe39bd3b66eb5090684959e7f2409346ab72d93tomhudson@google.com    return rec;
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == obj || NULL == fTFSet) {
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->write32(0);
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->write32(fTFSet->add(obj));
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == obj || NULL == fRCSet) {
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->write32(0);
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->write32(fRCSet->add(obj));
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     *  If we have a factoryset, then the first 32bits tell us...
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     *       0: failure to write the flattenable
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     *      <0: we store the negative of the (1-based) index
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     *      >0: the length of the name
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     *  If we don't have a factoryset, then the first "ptr" is either the
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     *  factory, or null for failure.
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     *
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     *  The distinction is important, since 0-index is 32bits (always), but a
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     *  0-functionptr might be 32 or 64 bits.
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
231df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com
232af07d065d19ec387b783b6dfdc3deafd7c614b69epoger@google.com    SkFlattenable::Factory factory = NULL;
233af07d065d19ec387b783b6dfdc3deafd7c614b69epoger@google.com    if (flattenable) {
234af07d065d19ec387b783b6dfdc3deafd7c614b69epoger@google.com        factory = flattenable->getFactory();
235af07d065d19ec387b783b6dfdc3deafd7c614b69epoger@google.com    }
236af07d065d19ec387b783b6dfdc3deafd7c614b69epoger@google.com    if (NULL == factory) {
237af07d065d19ec387b783b6dfdc3deafd7c614b69epoger@google.com        if (fFactorySet) {
238af07d065d19ec387b783b6dfdc3deafd7c614b69epoger@google.com            this->write32(0);
239df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        } else {
240df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com            this->writeFunctionPtr(NULL);
241df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        }
242df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        return;
243df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com    }
244df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com
245df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com    /*
246df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *  We can write 1 of 3 versions of the flattenable:
247df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *  1.  function-ptr : this is the fastest for the reader, but assumes that
248df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *      the writer and reader are in the same process.
249df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *  2.  index into fFactorySet : This is assumes the writer will later
250df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *      resolve the function-ptrs into strings for its reader. SkPicture
251df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *      does exactly this, by writing a table of names (matching the indices)
252df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *      up front in its serialized form.
253df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *  3.  names : Reuse fFactorySet to store indices, but only after we've
254df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *      written the name the first time. SkGPipe uses this technique, as it
255df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *      doesn't require the reader to be told to know the table of names
256df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     *      up front.
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fFactorySet) {
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (this->inlineFactoryNames()) {
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int index = fFactorySet->find(factory);
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (index) {
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                // we write the negative of the index, to distinguish it from
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                // the length of a string
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this->write32(-index);
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const char* name = SkFlattenable::FactoryToName(factory);
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (NULL == name) {
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    this->write32(0);
269c51db02181982fbcb8888e2a89132363a7d9371cscroggo                    return;
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this->writeString(name);
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                index = fFactorySet->add(factory);
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // we write the negative of the index, to distinguish it from
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // the length of a string
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->write32(-(int)fFactorySet->add(factory));
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->writeFunctionPtr((void*)factory);
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // make room for the size of the flatttened object
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (void)this->reserve(sizeof(uint32_t));
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // record the current size, so we can subtract after the object writes.
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t offset = this->size();
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now flatten the object
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    flattenable->flatten(*this);
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t objSize = this->size() - offset;
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // record the obj's size
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *this->peek32(offset - sizeof(uint32_t)) = objSize;
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2948433b5db1a0f94cd92d2606817d5374ab899b87areed@android.comvoid SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) {
2958433b5db1a0f94cd92d2606817d5374ab899b87areed@android.com    *(void**)this->reserve(sizeof(void*)) = proc;
2968433b5db1a0f94cd92d2606817d5374ab899b87areed@android.com}
2978433b5db1a0f94cd92d2606817d5374ab899b87areed@android.com
2988433b5db1a0f94cd92d2606817d5374ab899b87areed@android.com///////////////////////////////////////////////////////////////////////////////
2998433b5db1a0f94cd92d2606817d5374ab899b87areed@android.com
3008433b5db1a0f94cd92d2606817d5374ab899b87areed@android.comSkRefCntSet::~SkRefCntSet() {
3018433b5db1a0f94cd92d2606817d5374ab899b87areed@android.com    // call this now, while our decPtr() is sill in scope
3028433b5db1a0f94cd92d2606817d5374ab899b87areed@android.com    this->reset();
3038433b5db1a0f94cd92d2606817d5374ab899b87areed@android.com}
3048433b5db1a0f94cd92d2606817d5374ab899b87areed@android.com
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRefCntSet::incPtr(void* ptr) {
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ((SkRefCnt*)ptr)->ref();
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRefCntSet::decPtr(void* ptr) {
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ((SkRefCnt*)ptr)->unref();
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MAX_PAIR_COUNT  64
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct Pair {
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char*             fName;
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFlattenable::Factory  fFactory;
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int gCount;
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic Pair gPairs[MAX_PAIR_COUNT];
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFlattenable::Register(const char name[], Factory factory) {
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(name);
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(factory);
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static bool gOnce;
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!gOnce) {
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        gCount = 0;
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        gOnce = true;
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(gCount < MAX_PAIR_COUNT);
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    gPairs[gCount].fName = name;
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    gPairs[gCount].fFactory = factory;
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    gCount += 1;
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
343
344SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
345    const Pair* pairs = gPairs;
346    for (int i = gCount - 1; i >= 0; --i) {
347        if (strcmp(pairs[i].fName, name) == 0) {
348            return pairs[i].fFactory;
349        }
350    }
351    return NULL;
352}
353
354const char* SkFlattenable::FactoryToName(Factory fact) {
355    const Pair* pairs = gPairs;
356    for (int i = gCount - 1; i >= 0; --i) {
357        if (pairs[i].fFactory == fact) {
358            return pairs[i].fName;
359        }
360    }
361    return NULL;
362}
363
364bool SkFlattenable::toDumpString(SkString* str) const {
365    return false;
366}
367
368