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