1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkDescriptor.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,165 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#ifndef SkDescriptor_DEFINED 1.14 +#define SkDescriptor_DEFINED 1.15 + 1.16 +#include "SkChecksum.h" 1.17 +#include "SkTypes.h" 1.18 + 1.19 +class SkDescriptor : SkNoncopyable { 1.20 +public: 1.21 + static size_t ComputeOverhead(int entryCount) { 1.22 + SkASSERT(entryCount >= 0); 1.23 + return sizeof(SkDescriptor) + entryCount * sizeof(Entry); 1.24 + } 1.25 + 1.26 + static SkDescriptor* Alloc(size_t length) { 1.27 + SkASSERT(SkAlign4(length) == length); 1.28 + SkDescriptor* desc = (SkDescriptor*)sk_malloc_throw(length); 1.29 + return desc; 1.30 + } 1.31 + 1.32 + static void Free(SkDescriptor* desc) { 1.33 + sk_free(desc); 1.34 + } 1.35 + 1.36 + void init() { 1.37 + fLength = sizeof(SkDescriptor); 1.38 + fCount = 0; 1.39 + } 1.40 + 1.41 + uint32_t getLength() const { return fLength; } 1.42 + 1.43 + void* addEntry(uint32_t tag, uint32_t length, const void* data = NULL) { 1.44 + SkASSERT(tag); 1.45 + SkASSERT(SkAlign4(length) == length); 1.46 + SkASSERT(this->findEntry(tag, NULL) == NULL); 1.47 + 1.48 + Entry* entry = (Entry*)((char*)this + fLength); 1.49 + entry->fTag = tag; 1.50 + entry->fLen = length; 1.51 + if (data) { 1.52 + memcpy(entry + 1, data, length); 1.53 + } 1.54 + 1.55 + fCount += 1; 1.56 + fLength += sizeof(Entry) + length; 1.57 + return (entry + 1); // return its data 1.58 + } 1.59 + 1.60 + void computeChecksum() { 1.61 + fChecksum = SkDescriptor::ComputeChecksum(this); 1.62 + } 1.63 + 1.64 +#ifdef SK_DEBUG 1.65 + void assertChecksum() const { 1.66 + SkASSERT(SkDescriptor::ComputeChecksum(this) == fChecksum); 1.67 + } 1.68 +#endif 1.69 + 1.70 + const void* findEntry(uint32_t tag, uint32_t* length) const { 1.71 + const Entry* entry = (const Entry*)(this + 1); 1.72 + int count = fCount; 1.73 + 1.74 + while (--count >= 0) { 1.75 + if (entry->fTag == tag) { 1.76 + if (length) { 1.77 + *length = entry->fLen; 1.78 + } 1.79 + return entry + 1; 1.80 + } 1.81 + entry = (const Entry*)((const char*)(entry + 1) + entry->fLen); 1.82 + } 1.83 + return NULL; 1.84 + } 1.85 + 1.86 + SkDescriptor* copy() const { 1.87 + SkDescriptor* desc = SkDescriptor::Alloc(fLength); 1.88 + memcpy(desc, this, fLength); 1.89 + return desc; 1.90 + } 1.91 + 1.92 + bool equals(const SkDescriptor& other) const { 1.93 + // probe to see if we have a good checksum algo 1.94 +// SkASSERT(a.fChecksum != b.fChecksum || memcmp(&a, &b, a.fLength) == 0); 1.95 + 1.96 + // the first value we should look at is the checksum, so this loop 1.97 + // should terminate early if they descriptors are different. 1.98 + // NOTE: if we wrote a sentinel value at the end of each, we chould 1.99 + // remove the aa < stop test in the loop... 1.100 + const uint32_t* aa = (const uint32_t*)this; 1.101 + const uint32_t* bb = (const uint32_t*)&other; 1.102 + const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength); 1.103 + do { 1.104 + if (*aa++ != *bb++) 1.105 + return false; 1.106 + } while (aa < stop); 1.107 + return true; 1.108 + } 1.109 + 1.110 + uint32_t getChecksum() const { return fChecksum; } 1.111 + 1.112 + struct Entry { 1.113 + uint32_t fTag; 1.114 + uint32_t fLen; 1.115 + }; 1.116 + 1.117 +#ifdef SK_DEBUG 1.118 + uint32_t getCount() const { return fCount; } 1.119 +#endif 1.120 + 1.121 +private: 1.122 + uint32_t fChecksum; // must be first 1.123 + uint32_t fLength; // must be second 1.124 + uint32_t fCount; 1.125 + 1.126 + static uint32_t ComputeChecksum(const SkDescriptor* desc) { 1.127 + const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field 1.128 + size_t len = desc->fLength - sizeof(uint32_t); 1.129 + return SkChecksum::Compute(ptr, len); 1.130 + } 1.131 + 1.132 + // private so no one can create one except our factories 1.133 + SkDescriptor() {} 1.134 +}; 1.135 + 1.136 +#include "SkScalerContext.h" 1.137 + 1.138 +class SkAutoDescriptor : SkNoncopyable { 1.139 +public: 1.140 + SkAutoDescriptor(size_t size) { 1.141 + if (size <= sizeof(fStorage)) { 1.142 + fDesc = (SkDescriptor*)(void*)fStorage; 1.143 + } else { 1.144 + fDesc = SkDescriptor::Alloc(size); 1.145 + } 1.146 + } 1.147 + 1.148 + ~SkAutoDescriptor() { 1.149 + if (fDesc != (SkDescriptor*)(void*)fStorage) { 1.150 + SkDescriptor::Free(fDesc); 1.151 + } 1.152 + } 1.153 + 1.154 + SkDescriptor* getDesc() const { return fDesc; } 1.155 +private: 1.156 + enum { 1.157 + kStorageSize = sizeof(SkDescriptor) 1.158 + + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContext::Rec) // for rec 1.159 + + sizeof(SkDescriptor::Entry) + sizeof(void*) // for typeface 1.160 + + 32 // slop for occational small extras 1.161 + }; 1.162 + SkDescriptor* fDesc; 1.163 + uint32_t fStorage[(kStorageSize + 3) >> 2]; 1.164 +}; 1.165 +#define SkAutoDescriptor(...) SK_REQUIRE_LOCAL_VAR(SkAutoDescriptor) 1.166 + 1.167 + 1.168 +#endif