180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SkDescriptor_DEFINED
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkDescriptor_DEFINED
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkChecksum.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTypes.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkDescriptor : SkNoncopyable {
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static size_t ComputeOverhead(int entryCount) {
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(entryCount >= 0);
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return sizeof(SkDescriptor) + entryCount * sizeof(Entry);
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static SkDescriptor* Alloc(size_t length) {
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkAlign4(length) == length);
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDescriptor* desc = (SkDescriptor*)sk_malloc_throw(length);
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return desc;
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static void Free(SkDescriptor* desc) {
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_free(desc);
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void init() {
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fLength = sizeof(SkDescriptor);
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fCount  = 0;
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t getLength() const { return fLength; }
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void* addEntry(uint32_t tag, uint32_t length, const void* data = NULL) {
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(tag);
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkAlign4(length) == length);
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(this->findEntry(tag, NULL) == NULL);
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Entry*  entry = (Entry*)((char*)this + fLength);
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        entry->fTag = tag;
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        entry->fLen = length;
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (data) {
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            memcpy(entry + 1, data, length);
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fCount += 1;
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fLength += sizeof(Entry) + length;
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return (entry + 1); // return its data
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void computeChecksum() {
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fChecksum = SkDescriptor::ComputeChecksum(this);
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void assertChecksum() const {
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkDescriptor::ComputeChecksum(this) == fChecksum);
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const void* findEntry(uint32_t tag, uint32_t* length) const {
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const Entry* entry = (const Entry*)(this + 1);
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int          count = fCount;
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (--count >= 0) {
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (entry->fTag == tag) {
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (length) {
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    *length = entry->fLen;
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return entry + 1;
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            entry = (const Entry*)((const char*)(entry + 1) + entry->fLen);
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDescriptor* copy() const {
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDescriptor* desc = SkDescriptor::Alloc(fLength);
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(desc, this, fLength);
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return desc;
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool equals(const SkDescriptor& other) const {
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // probe to see if we have a good checksum algo
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//        SkASSERT(a.fChecksum != b.fChecksum || memcmp(&a, &b, a.fLength) == 0);
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // the first value we should look at is the checksum, so this loop
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // should terminate early if they descriptors are different.
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // NOTE: if we wrote a sentinel value at the end of each, we chould
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        //       remove the aa < stop test in the loop...
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint32_t* aa = (const uint32_t*)this;
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint32_t* bb = (const uint32_t*)&other;
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength);
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (*aa++ != *bb++)
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (aa < stop);
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t getChecksum() const { return fChecksum; }
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct Entry {
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint32_t fTag;
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint32_t fLen;
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t getCount() const { return fCount; }
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t fChecksum;  // must be first
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t fLength;    // must be second
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t fCount;
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static uint32_t ComputeChecksum(const SkDescriptor* desc) {
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t len = desc->fLength - sizeof(uint32_t);
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkChecksum::Compute(ptr, len);
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // private so no one can create one except our factories
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDescriptor() {}
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkScalerContext.h"
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkAutoDescriptor : SkNoncopyable {
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoDescriptor(size_t size) {
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (size <= sizeof(fStorage)) {
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fDesc = (SkDescriptor*)(void*)fStorage;
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fDesc = SkDescriptor::Alloc(size);
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~SkAutoDescriptor() {
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fDesc != (SkDescriptor*)(void*)fStorage) {
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDescriptor::Free(fDesc);
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDescriptor* getDesc() const { return fDesc; }
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    enum {
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kStorageSize =  sizeof(SkDescriptor)
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContext::Rec)    // for rec
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        + sizeof(SkDescriptor::Entry) + sizeof(void*)                   // for typeface
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        + 32   // slop for occational small extras
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDescriptor*   fDesc;
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t        fStorage[(kStorageSize + 3) >> 2];
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
162910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#define SkAutoDescriptor(...) SK_REQUIRE_LOCAL_VAR(SkAutoDescriptor)
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
166