Home | History | Annotate | Download | only in effects
      1 /*
      2     Copyright 2010 Google Inc.
      3 
      4     Licensed under the Apache License, Version 2.0 (the "License");
      5     you may not use this file except in compliance with the License.
      6     You may obtain a copy of the License at
      7 
      8     http://www.apache.org/licenses/LICENSE-2.0
      9 
     10     Unless required by applicable law or agreed to in writing, software
     11     distributed under the License is distributed on an "AS IS" BASIS,
     12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13     See the License for the specific language governing permissions and
     14     limitations under the License.
     15  */
     16 
     17 #include "SkBitmapCache.h"
     18 
     19 struct SkBitmapCache::Entry {
     20     Entry*      fPrev;
     21     Entry*      fNext;
     22 
     23     void*       fBuffer;
     24     size_t      fSize;
     25     SkBitmap    fBitmap;
     26 
     27     Entry(const void* buffer, size_t size, const SkBitmap& bm) : fBitmap(bm) {
     28         fBuffer = sk_malloc_throw(size);
     29         fSize = size;
     30         memcpy(fBuffer, buffer, size);
     31     }
     32 
     33     ~Entry() { sk_free(fBuffer); }
     34 
     35     bool equals(const void* buffer, size_t size) const {
     36         return (fSize == size) && !memcmp(fBuffer, buffer, size);
     37     }
     38 };
     39 
     40 SkBitmapCache::SkBitmapCache(int max) : fMaxEntries(max) {
     41     fEntryCount = 0;
     42     fHead = fTail = NULL;
     43 
     44     this->validate();
     45 }
     46 
     47 SkBitmapCache::~SkBitmapCache() {
     48     this->validate();
     49 
     50     Entry* entry = fHead;
     51     while (entry) {
     52         Entry* next = entry->fNext;
     53         delete entry;
     54         entry = next;
     55     }
     56 }
     57 
     58 SkBitmapCache::Entry* SkBitmapCache::detach(Entry* entry) const {
     59     if (entry->fPrev) {
     60         SkASSERT(fHead != entry);
     61         entry->fPrev->fNext = entry->fNext;
     62     } else {
     63         SkASSERT(fHead == entry);
     64         fHead = entry->fNext;
     65     }
     66     if (entry->fNext) {
     67         SkASSERT(fTail != entry);
     68         entry->fNext->fPrev = entry->fPrev;
     69     } else {
     70         SkASSERT(fTail == entry);
     71         fTail = entry->fPrev;
     72     }
     73     return entry;
     74 }
     75 
     76 void SkBitmapCache::attachToHead(Entry* entry) const {
     77     entry->fPrev = NULL;
     78     entry->fNext = fHead;
     79     if (fHead) {
     80         fHead->fPrev = entry;
     81     } else {
     82         fTail = entry;
     83     }
     84     fHead = entry;
     85 }
     86 
     87 bool SkBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
     88     AutoValidate av(this);
     89 
     90     Entry* entry = fHead;
     91     while (entry) {
     92         if (entry->equals(buffer, size)) {
     93             if (bm) {
     94                 *bm = entry->fBitmap;
     95             }
     96             // move to the head of our list, so we purge it last
     97             this->detach(entry);
     98             this->attachToHead(entry);
     99             return true;
    100         }
    101         entry = entry->fNext;
    102     }
    103     return false;
    104 }
    105 
    106 void SkBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
    107     AutoValidate av(this);
    108 
    109     if (fEntryCount == fMaxEntries) {
    110         SkASSERT(fTail);
    111         delete this->detach(fTail);
    112         fEntryCount -= 1;
    113     }
    114 
    115     Entry* entry = new Entry(buffer, len, bm);
    116     this->attachToHead(entry);
    117     fEntryCount += 1;
    118 }
    119 
    120 ///////////////////////////////////////////////////////////////////////////////
    121 
    122 #ifdef SK_DEBUG
    123 
    124 void SkBitmapCache::validate() const {
    125     SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
    126 
    127     if (fEntryCount > 0) {
    128         SkASSERT(NULL == fHead->fPrev);
    129         SkASSERT(NULL == fTail->fNext);
    130 
    131         if (fEntryCount == 1) {
    132             SkASSERT(fHead == fTail);
    133         } else {
    134             SkASSERT(fHead != fTail);
    135         }
    136 
    137         Entry* entry = fHead;
    138         int count = 0;
    139         while (entry) {
    140             count += 1;
    141             entry = entry->fNext;
    142         }
    143         SkASSERT(count == fEntryCount);
    144 
    145         entry = fTail;
    146         while (entry) {
    147             count -= 1;
    148             entry = entry->fPrev;
    149         }
    150         SkASSERT(0 == count);
    151     } else {
    152         SkASSERT(NULL == fHead);
    153         SkASSERT(NULL == fTail);
    154     }
    155 }
    156 
    157 #endif
    158 
    159