1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkDescriptor_DEFINED 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDescriptor_DEFINED 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13ef76060cbf36032a5bef9cd8d18138704349c3aejunov@chromium.org#include "SkChecksum.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypes.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDescriptor : SkNoncopyable { 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 18142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com static size_t ComputeOverhead(int entryCount) { 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(entryCount >= 0); 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return sizeof(SkDescriptor) + entryCount * sizeof(Entry); 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com static SkDescriptor* Alloc(size_t length) { 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkAlign4(length) == length); 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDescriptor* desc = (SkDescriptor*)sk_malloc_throw(length); 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return desc; 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 29142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com static void Free(SkDescriptor* desc) { 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_free(desc); 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 33142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com void init() { 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLength = sizeof(SkDescriptor); 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCount = 0; 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t getLength() const { return fLength; } 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 402cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org void* addEntry(uint32_t tag, size_t length, const void* data = NULL) { 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(tag); 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkAlign4(length) == length); 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(this->findEntry(tag, NULL) == NULL); 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Entry* entry = (Entry*)((char*)this + fLength); 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com entry->fTag = tag; 472cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org entry->fLen = SkToU32(length); 48142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com if (data) { 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(entry + 1, data, length); 50142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com } 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCount += 1; 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLength += sizeof(Entry) + length; 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (entry + 1); // return its data 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 57142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com void computeChecksum() { 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fChecksum = SkDescriptor::ComputeChecksum(this); 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 62142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com void assertChecksum() const { 63142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com SkASSERT(SkDescriptor::ComputeChecksum(this) == fChecksum); 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 67142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com const void* findEntry(uint32_t tag, uint32_t* length) const { 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Entry* entry = (const Entry*)(this + 1); 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = fCount; 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 71142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com while (--count >= 0) { 72142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com if (entry->fTag == tag) { 73142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com if (length) { 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *length = entry->fLen; 75142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com } 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return entry + 1; 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com entry = (const Entry*)((const char*)(entry + 1) + entry->fLen); 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 83142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com SkDescriptor* copy() const { 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDescriptor* desc = SkDescriptor::Alloc(fLength); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(desc, this, fLength); 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return desc; 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 89142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com bool equals(const SkDescriptor& other) const { 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // probe to see if we have a good checksum algo 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkASSERT(a.fChecksum != b.fChecksum || memcmp(&a, &b, a.fLength) == 0); 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the first value we should look at is the checksum, so this loop 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // should terminate early if they descriptors are different. 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // NOTE: if we wrote a sentinel value at the end of each, we chould 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // remove the aa < stop test in the loop... 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint32_t* aa = (const uint32_t*)this; 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint32_t* bb = (const uint32_t*)&other; 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength); 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (*aa++ != *bb++) 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (aa < stop); 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 107f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com uint32_t getChecksum() const { return fChecksum; } 108f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com struct Entry { 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fTag; 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fLen; 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t getCount() const { return fCount; } 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fChecksum; // must be first 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fLength; // must be second 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fCount; 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 123142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com static uint32_t ComputeChecksum(const SkDescriptor* desc) { 124ef76060cbf36032a5bef9cd8d18138704349c3aejunov@chromium.org const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field 125142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com size_t len = desc->fLength - sizeof(uint32_t); 126142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com return SkChecksum::Compute(ptr, len); 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 128fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // private so no one can create one except our factories 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDescriptor() {} 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalerContext.h" 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoDescriptor : SkNoncopyable { 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 137142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com SkAutoDescriptor(size_t size) { 138142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com if (size <= sizeof(fStorage)) { 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDesc = (SkDescriptor*)(void*)fStorage; 140142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com } else { 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDesc = SkDescriptor::Alloc(size); 142142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com } 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 144142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com 145142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com ~SkAutoDescriptor() { 146142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com if (fDesc != (SkDescriptor*)(void*)fStorage) { 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDescriptor::Free(fDesc); 148142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com } 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 150142e1fe7cf5dc82e5d4c107b06756302f0cbf96dreed@google.com 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDescriptor* getDesc() const { return fDesc; } 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com enum { 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kStorageSize = sizeof(SkDescriptor) 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContext::Rec) // for rec 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com + sizeof(SkDescriptor::Entry) + sizeof(void*) // for typeface 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com + 32 // slop for occational small extras 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDescriptor* fDesc; 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fStorage[(kStorageSize + 3) >> 2]; 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 162e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoDescriptor(...) SK_REQUIRE_LOCAL_VAR(SkAutoDescriptor) 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 166