140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2010 Google Inc. 41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger */ 840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkBitmapCache.h" 1140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstruct SkBitmapCache::Entry { 1340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger Entry* fPrev; 1440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger Entry* fNext; 1540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger void* fBuffer; 1740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger size_t fSize; 1840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkBitmap fBitmap; 1940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger Entry(const void* buffer, size_t size, const SkBitmap& bm) 211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger : fPrev(NULL), 221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fNext(NULL), 231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fBitmap(bm) { 2440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fBuffer = sk_malloc_throw(size); 2540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fSize = size; 2640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger memcpy(fBuffer, buffer, size); 2740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 2840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 2940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger ~Entry() { sk_free(fBuffer); } 3040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 3140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger bool equals(const void* buffer, size_t size) const { 3240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return (fSize == size) && !memcmp(fBuffer, buffer, size); 3340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 3440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}; 3540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 3640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkBitmapCache::SkBitmapCache(int max) : fMaxEntries(max) { 3740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fEntryCount = 0; 3840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fHead = fTail = NULL; 3940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger this->validate(); 4140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 4240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkBitmapCache::~SkBitmapCache() { 4440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger this->validate(); 4540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger Entry* entry = fHead; 4740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger while (entry) { 4840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger Entry* next = entry->fNext; 4940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger delete entry; 5040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger entry = next; 5140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 5240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 5340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 5440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkBitmapCache::Entry* SkBitmapCache::detach(Entry* entry) const { 5540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (entry->fPrev) { 5640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(fHead != entry); 5740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger entry->fPrev->fNext = entry->fNext; 5840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 5940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(fHead == entry); 6040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fHead = entry->fNext; 6140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 6240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (entry->fNext) { 6340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(fTail != entry); 6440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger entry->fNext->fPrev = entry->fPrev; 6540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 6640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(fTail == entry); 6740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fTail = entry->fPrev; 6840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 6940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return entry; 7040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 7140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 7240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkBitmapCache::attachToHead(Entry* entry) const { 7340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger entry->fPrev = NULL; 7440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger entry->fNext = fHead; 7540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fHead) { 7640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fHead->fPrev = entry; 7740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 7840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fTail = entry; 7940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 8040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fHead = entry; 8140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 8240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 8340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerbool SkBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const { 8440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger AutoValidate av(this); 8540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 8640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger Entry* entry = fHead; 8740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger while (entry) { 8840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (entry->equals(buffer, size)) { 8940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (bm) { 9040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger *bm = entry->fBitmap; 9140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 9240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // move to the head of our list, so we purge it last 9340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger this->detach(entry); 9440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger this->attachToHead(entry); 9540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return true; 9640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 9740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger entry = entry->fNext; 9840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 9940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return false; 10040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 10140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 10240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) { 10340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger AutoValidate av(this); 10440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 10540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fEntryCount == fMaxEntries) { 10640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(fTail); 10740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger delete this->detach(fTail); 10840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fEntryCount -= 1; 10940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 11040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 11140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger Entry* entry = new Entry(buffer, len, bm); 11240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger this->attachToHead(entry); 11340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fEntryCount += 1; 11440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 11540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 11640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 11740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 11840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#ifdef SK_DEBUG 11940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 12040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkBitmapCache::validate() const { 12140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries); 12240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 12340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fEntryCount > 0) { 12440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(NULL == fHead->fPrev); 12540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(NULL == fTail->fNext); 12640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 12740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fEntryCount == 1) { 12840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(fHead == fTail); 12940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 13040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(fHead != fTail); 13140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 13240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 13340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger Entry* entry = fHead; 13440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger int count = 0; 13540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger while (entry) { 13640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger count += 1; 13740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger entry = entry->fNext; 13840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 13940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(count == fEntryCount); 14040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 14140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger entry = fTail; 14240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger while (entry) { 14340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger count -= 1; 14440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger entry = entry->fPrev; 14540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 14640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(0 == count); 14740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 14840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(NULL == fHead); 14940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(NULL == fTail); 15040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 15140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 15240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 15340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#endif 15440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 155