11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkDescriptor_DEFINED
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkDescriptor_DEFINED
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTypes.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkDescriptor : SkNoncopyable {
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static size_t ComputeOverhead(int entryCount)
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(entryCount >= 0);
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return sizeof(SkDescriptor) + entryCount * sizeof(Entry);
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static SkDescriptor* Alloc(size_t length)
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(SkAlign4(length) == length);
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkDescriptor* desc = (SkDescriptor*)sk_malloc_throw(length);
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return desc;
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static void Free(SkDescriptor* desc)
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_free(desc);
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void init()
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fLength = sizeof(SkDescriptor);
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fCount  = 0;
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t getLength() const { return fLength; }
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void* addEntry(uint32_t tag, uint32_t length, const void* data = NULL)
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(tag);
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(SkAlign4(length) == length);
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(this->findEntry(tag, NULL) == NULL);
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Entry*  entry = (Entry*)((char*)this + fLength);
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        entry->fTag = tag;
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        entry->fLen = length;
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (data)
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            memcpy(entry + 1, data, length);
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fCount += 1;
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fLength += sizeof(Entry) + length;
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return (entry + 1); // return its data
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void computeChecksum()
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fChecksum = SkDescriptor::ComputeChecksum(this);
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void assertChecksum() const
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(fChecksum == SkDescriptor::ComputeChecksum(this));
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const void* findEntry(uint32_t tag, uint32_t* length) const
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const Entry* entry = (const Entry*)(this + 1);
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int          count = fCount;
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        while (--count >= 0)
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (entry->fTag == tag)
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (length)
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    *length = entry->fLen;
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                return entry + 1;
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            entry = (const Entry*)((const char*)(entry + 1) + entry->fLen);
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return NULL;
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDescriptor* copy() const
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkDescriptor* desc = SkDescriptor::Alloc(fLength);
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        memcpy(desc, this, fLength);
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return desc;
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool equals(const SkDescriptor& other) const
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // probe to see if we have a good checksum algo
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//        SkASSERT(a.fChecksum != b.fChecksum || memcmp(&a, &b, a.fLength) == 0);
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // the first value we should look at is the checksum, so this loop
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // should terminate early if they descriptors are different.
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // NOTE: if we wrote a sentinel value at the end of each, we chould
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        //       remove the aa < stop test in the loop...
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const uint32_t* aa = (const uint32_t*)this;
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const uint32_t* bb = (const uint32_t*)&other;
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength);
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        do {
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (*aa++ != *bb++)
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                return false;
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } while (aa < stop);
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    uint32_t getChecksum() const { return fChecksum; }
11740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    struct Entry {
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        uint32_t fTag;
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        uint32_t fLen;
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t getCount() const { return fCount; }
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t fChecksum;  // must be first
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t fLength;    // must be second
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t fCount;
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static uint32_t ComputeChecksum(const SkDescriptor* desc)
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const uint32_t*  ptr = (const uint32_t*)desc + 1; // skip the checksum field
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const uint32_t*  stop = (const uint32_t*)((const char*)desc + desc->fLength);
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        uint32_t         sum = 0;
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(ptr < stop);
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        do {
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            sum = (sum << 1) | (sum >> 31);
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            sum ^= *ptr++;
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } while (ptr < stop);
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return sum;
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // private so no one can create one except our factories
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDescriptor() {}
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScalerContext.h"
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkAutoDescriptor : SkNoncopyable {
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoDescriptor(size_t size)
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (size <= sizeof(fStorage))
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fDesc = (SkDescriptor*)(void*)fStorage;
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fDesc = SkDescriptor::Alloc(size);
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ~SkAutoDescriptor()
1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fDesc != (SkDescriptor*)(void*)fStorage)
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkDescriptor::Free(fDesc);
1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDescriptor* getDesc() const { return fDesc; }
1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    enum {
1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kStorageSize =  sizeof(SkDescriptor)
1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContext::Rec)    // for rec
1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        + sizeof(SkDescriptor::Entry) + sizeof(void*)                   // for typeface
1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        + 32   // slop for occational small extras
1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDescriptor*   fDesc;
1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t        fStorage[(kStorageSize + 3) >> 2];
1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
182