180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2010 Google Inc. 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#include "SkBitmapCache.h" 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustruct SkBitmapCache::Entry { 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Entry* fPrev; 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Entry* fNext; 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void* fBuffer; 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t fSize; 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBitmap fBitmap; 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Entry(const void* buffer, size_t size, const SkBitmap& bm) 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru : fPrev(NULL), 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fNext(NULL), 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fBitmap(bm) { 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fBuffer = sk_malloc_throw(size); 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fSize = size; 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru memcpy(fBuffer, buffer, size); 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ~Entry() { sk_free(fBuffer); } 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool equals(const void* buffer, size_t size) const { 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (fSize == size) && !memcmp(fBuffer, buffer, size); 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBitmapCache::SkBitmapCache(int max) : fMaxEntries(max) { 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fEntryCount = 0; 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fHead = fTail = NULL; 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->validate(); 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBitmapCache::~SkBitmapCache() { 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->validate(); 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Entry* entry = fHead; 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (entry) { 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Entry* next = entry->fNext; 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru delete entry; 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry = next; 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBitmapCache::Entry* SkBitmapCache::detach(Entry* entry) const { 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (entry->fPrev) { 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(fHead != entry); 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry->fPrev->fNext = entry->fNext; 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(fHead == entry); 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fHead = entry->fNext; 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (entry->fNext) { 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(fTail != entry); 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry->fNext->fPrev = entry->fPrev; 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(fTail == entry); 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fTail = entry->fPrev; 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return entry; 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBitmapCache::attachToHead(Entry* entry) const { 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry->fPrev = NULL; 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry->fNext = fHead; 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fHead) { 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fHead->fPrev = entry; 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fTail = entry; 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fHead = entry; 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const { 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru AutoValidate av(this); 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Entry* entry = fHead; 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (entry) { 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (entry->equals(buffer, size)) { 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (bm) { 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *bm = entry->fBitmap; 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // move to the head of our list, so we purge it last 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->detach(entry); 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->attachToHead(entry); 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry = entry->fNext; 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) { 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru AutoValidate av(this); 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fEntryCount == fMaxEntries) { 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(fTail); 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru delete this->detach(fTail); 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fEntryCount -= 1; 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Entry* entry = SkNEW_ARGS(Entry, (buffer, len, bm)); 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->attachToHead(entry); 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fEntryCount += 1; 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBitmapCache::validate() const { 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries); 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fEntryCount > 0) { 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(NULL == fHead->fPrev); 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(NULL == fTail->fNext); 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fEntryCount == 1) { 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(fHead == fTail); 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(fHead != fTail); 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Entry* entry = fHead; 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int count = 0; 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (entry) { 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru count += 1; 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry = entry->fNext; 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(count == fEntryCount); 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry = fTail; 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (entry) { 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru count -= 1; 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru entry = entry->fPrev; 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(0 == count); 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(NULL == fHead); 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(NULL == fTail); 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 154