blob: 63d708bad0f5096a86cf3171b73f082f110d1cb8 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comdc731fd2010-12-23 15:19:47 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@google.comdc731fd2010-12-23 15:19:47 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reeda6cac4c2014-08-21 10:50:25 -070010#include "SkGradientBitmapCache.h"
reed@google.comdc731fd2010-12-23 15:19:47 +000011
reeda6cac4c2014-08-21 10:50:25 -070012struct SkGradientBitmapCache::Entry {
reed@google.comdc731fd2010-12-23 15:19:47 +000013 Entry* fPrev;
14 Entry* fNext;
15
16 void* fBuffer;
17 size_t fSize;
18 SkBitmap fBitmap;
19
vandebo@chromium.org3c898182011-06-22 05:01:28 +000020 Entry(const void* buffer, size_t size, const SkBitmap& bm)
21 : fPrev(NULL),
22 fNext(NULL),
23 fBitmap(bm) {
reed@google.comdc731fd2010-12-23 15:19:47 +000024 fBuffer = sk_malloc_throw(size);
25 fSize = size;
26 memcpy(fBuffer, buffer, size);
27 }
28
29 ~Entry() { sk_free(fBuffer); }
30
31 bool equals(const void* buffer, size_t size) const {
32 return (fSize == size) && !memcmp(fBuffer, buffer, size);
33 }
34};
35
reeda6cac4c2014-08-21 10:50:25 -070036SkGradientBitmapCache::SkGradientBitmapCache(int max) : fMaxEntries(max) {
reed@google.comdc731fd2010-12-23 15:19:47 +000037 fEntryCount = 0;
38 fHead = fTail = NULL;
39
40 this->validate();
41}
42
reeda6cac4c2014-08-21 10:50:25 -070043SkGradientBitmapCache::~SkGradientBitmapCache() {
reed@google.comdc731fd2010-12-23 15:19:47 +000044 this->validate();
45
46 Entry* entry = fHead;
47 while (entry) {
48 Entry* next = entry->fNext;
49 delete entry;
50 entry = next;
51 }
52}
53
reeda6cac4c2014-08-21 10:50:25 -070054SkGradientBitmapCache::Entry* SkGradientBitmapCache::detach(Entry* entry) const {
reed@google.comdc731fd2010-12-23 15:19:47 +000055 if (entry->fPrev) {
56 SkASSERT(fHead != entry);
57 entry->fPrev->fNext = entry->fNext;
58 } else {
59 SkASSERT(fHead == entry);
60 fHead = entry->fNext;
61 }
62 if (entry->fNext) {
63 SkASSERT(fTail != entry);
64 entry->fNext->fPrev = entry->fPrev;
65 } else {
66 SkASSERT(fTail == entry);
67 fTail = entry->fPrev;
68 }
69 return entry;
70}
71
reeda6cac4c2014-08-21 10:50:25 -070072void SkGradientBitmapCache::attachToHead(Entry* entry) const {
reed@google.comdc731fd2010-12-23 15:19:47 +000073 entry->fPrev = NULL;
74 entry->fNext = fHead;
75 if (fHead) {
76 fHead->fPrev = entry;
77 } else {
78 fTail = entry;
79 }
80 fHead = entry;
81}
82
reeda6cac4c2014-08-21 10:50:25 -070083bool SkGradientBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
reed@google.comdc731fd2010-12-23 15:19:47 +000084 AutoValidate av(this);
85
86 Entry* entry = fHead;
87 while (entry) {
88 if (entry->equals(buffer, size)) {
89 if (bm) {
90 *bm = entry->fBitmap;
91 }
92 // move to the head of our list, so we purge it last
93 this->detach(entry);
94 this->attachToHead(entry);
95 return true;
96 }
97 entry = entry->fNext;
98 }
99 return false;
100}
101
reeda6cac4c2014-08-21 10:50:25 -0700102void SkGradientBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
reed@google.comdc731fd2010-12-23 15:19:47 +0000103 AutoValidate av(this);
reed@google.come49d5712011-01-19 14:30:26 +0000104
reed@google.comdc731fd2010-12-23 15:19:47 +0000105 if (fEntryCount == fMaxEntries) {
reed@google.come49d5712011-01-19 14:30:26 +0000106 SkASSERT(fTail);
107 delete this->detach(fTail);
108 fEntryCount -= 1;
reed@google.comdc731fd2010-12-23 15:19:47 +0000109 }
110
tomhudson@google.com060ef182012-07-24 12:22:40 +0000111 Entry* entry = SkNEW_ARGS(Entry, (buffer, len, bm));
reed@google.comdc731fd2010-12-23 15:19:47 +0000112 this->attachToHead(entry);
113 fEntryCount += 1;
114}
115
116///////////////////////////////////////////////////////////////////////////////
117
118#ifdef SK_DEBUG
119
reeda6cac4c2014-08-21 10:50:25 -0700120void SkGradientBitmapCache::validate() const {
reed@google.comdc731fd2010-12-23 15:19:47 +0000121 SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
reed@google.come49d5712011-01-19 14:30:26 +0000122
reed@google.comdc731fd2010-12-23 15:19:47 +0000123 if (fEntryCount > 0) {
124 SkASSERT(NULL == fHead->fPrev);
125 SkASSERT(NULL == fTail->fNext);
126
127 if (fEntryCount == 1) {
128 SkASSERT(fHead == fTail);
129 } else {
130 SkASSERT(fHead != fTail);
131 }
132
133 Entry* entry = fHead;
134 int count = 0;
135 while (entry) {
136 count += 1;
137 entry = entry->fNext;
138 }
139 SkASSERT(count == fEntryCount);
reed@google.come49d5712011-01-19 14:30:26 +0000140
reed@google.comdc731fd2010-12-23 15:19:47 +0000141 entry = fTail;
142 while (entry) {
143 count -= 1;
144 entry = entry->fPrev;
145 }
146 SkASSERT(0 == count);
147 } else {
148 SkASSERT(NULL == fHead);
149 SkASSERT(NULL == fTail);
reed@google.come49d5712011-01-19 14:30:26 +0000150 }
reed@google.comdc731fd2010-12-23 15:19:47 +0000151}
152
153#endif