SkFlattenable.cpp revision ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976e
17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch/*
37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Copyright 2011 Google Inc.
47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *
57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Use of this source code is governed by a BSD-style license that can be
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * found in the LICENSE file.
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "SkFlattenable.h"
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "SkTypeface.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "SkMatrix.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "SkRegion.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SkReadMatrix(SkReader32* reader, SkMatrix* matrix) {
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size_t size = matrix->unflatten(reader->peek());
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkASSERT(SkAlign4(size) == size);
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    (void)reader->skip(size);
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SkWriteMatrix(SkWriter32* writer, const SkMatrix& matrix) {
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size_t size = matrix.flatten(NULL);
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkASSERT(SkAlign4(size) == size);
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    matrix.flatten(writer->reserve(size));
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SkReadRegion(SkReader32* reader, SkRegion* rgn) {
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size_t size = rgn->unflatten(reader->peek());
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkASSERT(SkAlign4(size) == size);
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    (void)reader->skip(size);
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SkWriteRegion(SkWriter32* writer, const SkRegion& rgn) {
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size_t size = rgn.flatten(NULL);
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkASSERT(SkAlign4(size) == size);
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    rgn.flatten(writer->reserve(size));
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch///////////////////////////////////////////////////////////////////////////////
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SkFlattenable::flatten(SkFlattenableWriteBuffer&)
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch{
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    /*  we don't write anything at the moment, but this allows our subclasses
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        to not know that, since we want them to always call INHERITED::flatten()
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        in their code.
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    */
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch///////////////////////////////////////////////////////////////////////////////
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch///////////////////////////////////////////////////////////////////////////////
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSkFlattenableReadBuffer::SkFlattenableReadBuffer() {
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fRCArray = NULL;
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fRCCount = 0;
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fTFArray = NULL;
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fTFCount = 0;
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFactoryTDArray = NULL;
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFactoryArray = NULL;
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFactoryCount = 0;
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) :
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        INHERITED(data, 1024 * 1024) {
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fRCArray = NULL;
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fRCCount = 0;
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fTFArray = NULL;
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fTFCount = 0;
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFactoryTDArray = NULL;
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFactoryArray = NULL;
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFactoryCount = 0;
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size)
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        : INHERITED(data, size) {
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    fRCArray = NULL;
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    fRCCount = 0;
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    fTFArray = NULL;
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    fTFCount = 0;
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFactoryTDArray = NULL;
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFactoryArray = NULL;
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFactoryCount = 0;
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSkTypeface* SkFlattenableReadBuffer::readTypeface() {
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    uint32_t index = this->readU32();
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (0 == index || index > (unsigned)fTFCount) {
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (index) {
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            SkDebugf("====== typeface index %d\n", index);
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        return NULL;
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        SkASSERT(fTFArray);
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        return fTFArray[index - 1];
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)SkRefCnt* SkFlattenableReadBuffer::readRefCnt() {
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    uint32_t index = this->readU32();
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (0 == index || index > (unsigned)fRCCount) {
105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        return NULL;
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        SkASSERT(fRCArray);
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        return fRCArray[index - 1];
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSkFlattenable* SkFlattenableReadBuffer::readFlattenable() {
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkFlattenable::Factory factory = NULL;
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (fFactoryCount > 0) {
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        int32_t index = this->readU32();
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (0 == index) {
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            return NULL; // writer failed to give us the flattenable
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }
120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        index = -index; // we stored the negative of the index
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        index -= 1;     // we stored the index-base-1
122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        SkASSERT(index < fFactoryCount);
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        factory = fFactoryArray[index];
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else if (fFactoryTDArray) {
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        const int32_t* peek = (const int32_t*)this->peek();
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (*peek <= 0) {
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            int32_t index = this->readU32();
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            if (0 == index) {
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                return NULL; // writer failed to give us the flattenable
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            }
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            index = -index; // we stored the negative of the index
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            index -= 1;     // we stored the index-base-1
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            factory = (*fFactoryTDArray)[index];
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        } else {
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            const char* name = this->readString();
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            factory = SkFlattenable::NameToFactory(name);
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            if (factory) {
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                SkASSERT(fFactoryTDArray->find(factory) < 0);
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                *fFactoryTDArray->append() = factory;
140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            } else {
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch//                SkDebugf("can't find factory for [%s]\n", name);
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            }
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            // if we didn't find a factory, that's our failure, not the writer's,
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            // so we fall through, so we can skip the sizeRecorded data.
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        factory = (SkFlattenable::Factory)readFunctionPtr();
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (NULL == factory) {
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            return NULL; // writer failed to give us the flattenable
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // if we get here, factory may still be null, but if that is the case, the
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // failure was ours, not the writer.
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkFlattenable* obj = NULL;
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    uint32_t sizeRecorded = this->readU32();
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (factory) {
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        uint32_t offset = this->offset();
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        obj = (*factory)(*this);
1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // check that we read the amount we expected
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        uint32_t sizeRead = this->offset() - offset;
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (sizeRecorded != sizeRead) {
1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            // we could try to fix up the offset...
1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            sk_throw();
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // we must skip the remaining data
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        this->skip(sizeRecorded);
1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return obj;
1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid* SkFlattenableReadBuffer::readFunctionPtr() {
1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    void* proc;
1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    this->read(&proc, sizeof(proc));
1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return proc;
1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch///////////////////////////////////////////////////////////////////////////////
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) :
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        INHERITED(minSize) {
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFlags = (Flags)0;
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fRCSet = NULL;
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fTFSet = NULL;
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    fFactorySet = NULL;
187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SkSafeUnref(fRCSet);
191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SkSafeUnref(fTFSet);
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SkSafeUnref(fFactorySet);
1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkRefCnt_SafeAssign(fRCSet, rec);
1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return rec;
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkRefCnt_SafeAssign(fTFSet, rec);
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return rec;
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkRefCnt_SafeAssign(fFactorySet, rec);
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return rec;
2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (NULL == obj || NULL == fTFSet) {
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        this->write32(0);
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        this->write32(fTFSet->add(obj));
2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (NULL == obj || NULL == fRCSet) {
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        this->write32(0);
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        this->write32(fRCSet->add(obj));
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    /*
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch     *  If we have a factoryset, then the first 32bits tell us...
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch     *       0: failure to write the flattenable
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch     *      <0: we store the negative of the (1-based) index
231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)     *      >0: the length of the name
232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)     *  If we don't have a factoryset, then the first "ptr" is either the
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch     *  factory, or null for failure.
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch     *
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch     *  The distinction is important, since 0-index is 32bits (always), but a
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch     *  0-functionptr might be 32 or 64 bits.
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch     */
2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkFlattenable::Factory factory = NULL;
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (flattenable) {
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        factory = flattenable->getFactory();
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (NULL == factory) {
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (fFactorySet) {
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            this->write32(0);
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        } else {
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            this->writeFunctionPtr(NULL);
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        return;
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    /*
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch     *  We can write 1 of 3 versions of the flattenable:
254     *  1.  function-ptr : this is the fastest for the reader, but assumes that
255     *      the writer and reader are in the same process.
256     *  2.  index into fFactorySet : This is assumes the writer will later
257     *      resolve the function-ptrs into strings for its reader. SkPicture
258     *      does exactly this, by writing a table of names (matching the indices)
259     *      up front in its serialized form.
260     *  3.  names : Reuse fFactorySet to store indices, but only after we've
261     *      written the name the first time. SkGPipe uses this technique, as it
262     *      doesn't require the reader to be told to know the table of names
263     *      up front.
264     */
265    if (fFactorySet) {
266        if (this->inlineFactoryNames()) {
267            int index = fFactorySet->find(factory);
268            if (index) {
269                // we write the negative of the index, to distinguish it from
270                // the length of a string
271                this->write32(-index);
272            } else {
273                const char* name = SkFlattenable::FactoryToName(factory);
274                if (NULL == name) {
275                    this->write32(0);
276                    return;
277                }
278                this->writeString(name);
279                index = fFactorySet->add(factory);
280            }
281        } else {
282            // we write the negative of the index, to distinguish it from
283            // the length of a string
284            this->write32(-(int)fFactorySet->add(factory));
285        }
286    } else {
287        this->writeFunctionPtr((void*)factory);
288    }
289
290    // make room for the size of the flatttened object
291    (void)this->reserve(sizeof(uint32_t));
292    // record the current size, so we can subtract after the object writes.
293    uint32_t offset = this->size();
294    // now flatten the object
295    flattenable->flatten(*this);
296    uint32_t objSize = this->size() - offset;
297    // record the obj's size
298    *this->peek32(offset - sizeof(uint32_t)) = objSize;
299}
300
301void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) {
302    *(void**)this->reserve(sizeof(void*)) = proc;
303}
304
305///////////////////////////////////////////////////////////////////////////////
306
307SkRefCntSet::~SkRefCntSet() {
308    // call this now, while our decPtr() is sill in scope
309    this->reset();
310}
311
312void SkRefCntSet::incPtr(void* ptr) {
313    ((SkRefCnt*)ptr)->ref();
314}
315
316void SkRefCntSet::decPtr(void* ptr) {
317    ((SkRefCnt*)ptr)->unref();
318}
319
320///////////////////////////////////////////////////////////////////////////////
321///////////////////////////////////////////////////////////////////////////////
322///////////////////////////////////////////////////////////////////////////////
323
324#define MAX_PAIR_COUNT  64
325
326struct Pair {
327    const char*             fName;
328    SkFlattenable::Factory  fFactory;
329};
330
331static int gCount;
332static Pair gPairs[MAX_PAIR_COUNT];
333
334void SkFlattenable::Register(const char name[], Factory factory) {
335    SkASSERT(name);
336    SkASSERT(factory);
337
338    static bool gOnce;
339    if (!gOnce) {
340        gCount = 0;
341        gOnce = true;
342    }
343
344    SkASSERT(gCount < MAX_PAIR_COUNT);
345
346    gPairs[gCount].fName = name;
347    gPairs[gCount].fFactory = factory;
348    gCount += 1;
349}
350
351SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
352    const Pair* pairs = gPairs;
353    for (int i = gCount - 1; i >= 0; --i) {
354        if (strcmp(pairs[i].fName, name) == 0) {
355            return pairs[i].fFactory;
356        }
357    }
358    return NULL;
359}
360
361const char* SkFlattenable::FactoryToName(Factory fact) {
362    const Pair* pairs = gPairs;
363    for (int i = gCount - 1; i >= 0; --i) {
364        if (pairs[i].fFactory == fact) {
365            return pairs[i].fName;
366        }
367    }
368    return NULL;
369}
370
371bool SkFlattenable::toDumpString(SkString* str) const {
372    return false;
373}
374
375