blob: 20b87e02cad834ec26828f366b2a2d1dd39b7f84 [file] [log] [blame]
reed@google.comdc731fd2010-12-23 15:19:47 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2010 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@google.comdc731fd2010-12-23 15:19:47 +00006 */
7
epoger@google.comec3ed6a2011-07-28 14:26:00 +00008
reeda6cac4c2014-08-21 10:50:25 -07009#include "SkGradientBitmapCache.h"
reed@google.comdc731fd2010-12-23 15:19:47 +000010
reeda6cac4c2014-08-21 10:50:25 -070011struct SkGradientBitmapCache::Entry {
reed@google.comdc731fd2010-12-23 15:19:47 +000012 Entry* fPrev;
13 Entry* fNext;
14
15 void* fBuffer;
16 size_t fSize;
17 SkBitmap fBitmap;
18
vandebo@chromium.org3c898182011-06-22 05:01:28 +000019 Entry(const void* buffer, size_t size, const SkBitmap& bm)
halcanary96fcdcc2015-08-27 07:41:13 -070020 : fPrev(nullptr),
21 fNext(nullptr),
vandebo@chromium.org3c898182011-06-22 05:01:28 +000022 fBitmap(bm) {
reed@google.comdc731fd2010-12-23 15:19:47 +000023 fBuffer = sk_malloc_throw(size);
24 fSize = size;
25 memcpy(fBuffer, buffer, size);
26 }
27
28 ~Entry() { sk_free(fBuffer); }
29
30 bool equals(const void* buffer, size_t size) const {
31 return (fSize == size) && !memcmp(fBuffer, buffer, size);
32 }
33};
34
reeda6cac4c2014-08-21 10:50:25 -070035SkGradientBitmapCache::SkGradientBitmapCache(int max) : fMaxEntries(max) {
reed@google.comdc731fd2010-12-23 15:19:47 +000036 fEntryCount = 0;
halcanary96fcdcc2015-08-27 07:41:13 -070037 fHead = fTail = nullptr;
reed@google.comdc731fd2010-12-23 15:19:47 +000038
39 this->validate();
40}
41
reeda6cac4c2014-08-21 10:50:25 -070042SkGradientBitmapCache::~SkGradientBitmapCache() {
reed@google.comdc731fd2010-12-23 15:19:47 +000043 this->validate();
44
45 Entry* entry = fHead;
46 while (entry) {
47 Entry* next = entry->fNext;
48 delete entry;
49 entry = next;
50 }
51}
52
mtklein18300a32016-03-16 13:53:35 -070053SkGradientBitmapCache::Entry* SkGradientBitmapCache::release(Entry* entry) const {
reed@google.comdc731fd2010-12-23 15:19:47 +000054 if (entry->fPrev) {
55 SkASSERT(fHead != entry);
56 entry->fPrev->fNext = entry->fNext;
57 } else {
58 SkASSERT(fHead == entry);
59 fHead = entry->fNext;
60 }
61 if (entry->fNext) {
62 SkASSERT(fTail != entry);
63 entry->fNext->fPrev = entry->fPrev;
64 } else {
65 SkASSERT(fTail == entry);
66 fTail = entry->fPrev;
67 }
68 return entry;
69}
70
reeda6cac4c2014-08-21 10:50:25 -070071void SkGradientBitmapCache::attachToHead(Entry* entry) const {
halcanary96fcdcc2015-08-27 07:41:13 -070072 entry->fPrev = nullptr;
reed@google.comdc731fd2010-12-23 15:19:47 +000073 entry->fNext = fHead;
74 if (fHead) {
75 fHead->fPrev = entry;
76 } else {
77 fTail = entry;
78 }
79 fHead = entry;
80}
81
reeda6cac4c2014-08-21 10:50:25 -070082bool SkGradientBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
reed@google.comdc731fd2010-12-23 15:19:47 +000083 AutoValidate av(this);
84
85 Entry* entry = fHead;
86 while (entry) {
87 if (entry->equals(buffer, size)) {
88 if (bm) {
89 *bm = entry->fBitmap;
90 }
91 // move to the head of our list, so we purge it last
mtklein18300a32016-03-16 13:53:35 -070092 this->release(entry);
reed@google.comdc731fd2010-12-23 15:19:47 +000093 this->attachToHead(entry);
94 return true;
95 }
96 entry = entry->fNext;
97 }
98 return false;
99}
100
reeda6cac4c2014-08-21 10:50:25 -0700101void SkGradientBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
reed@google.comdc731fd2010-12-23 15:19:47 +0000102 AutoValidate av(this);
reed@google.come49d5712011-01-19 14:30:26 +0000103
reed@google.comdc731fd2010-12-23 15:19:47 +0000104 if (fEntryCount == fMaxEntries) {
reed@google.come49d5712011-01-19 14:30:26 +0000105 SkASSERT(fTail);
mtklein18300a32016-03-16 13:53:35 -0700106 delete this->release(fTail);
reed@google.come49d5712011-01-19 14:30:26 +0000107 fEntryCount -= 1;
reed@google.comdc731fd2010-12-23 15:19:47 +0000108 }
109
halcanary385fe4d2015-08-26 13:07:48 -0700110 Entry* entry = new Entry(buffer, len, bm);
reed@google.comdc731fd2010-12-23 15:19:47 +0000111 this->attachToHead(entry);
112 fEntryCount += 1;
113}
114
115///////////////////////////////////////////////////////////////////////////////
116
117#ifdef SK_DEBUG
118
reeda6cac4c2014-08-21 10:50:25 -0700119void SkGradientBitmapCache::validate() const {
reed@google.comdc731fd2010-12-23 15:19:47 +0000120 SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
reed@google.come49d5712011-01-19 14:30:26 +0000121
reed@google.comdc731fd2010-12-23 15:19:47 +0000122 if (fEntryCount > 0) {
halcanary96fcdcc2015-08-27 07:41:13 -0700123 SkASSERT(nullptr == fHead->fPrev);
124 SkASSERT(nullptr == fTail->fNext);
reed@google.comdc731fd2010-12-23 15:19:47 +0000125
126 if (fEntryCount == 1) {
127 SkASSERT(fHead == fTail);
128 } else {
129 SkASSERT(fHead != fTail);
130 }
131
132 Entry* entry = fHead;
133 int count = 0;
134 while (entry) {
135 count += 1;
136 entry = entry->fNext;
137 }
138 SkASSERT(count == fEntryCount);
reed@google.come49d5712011-01-19 14:30:26 +0000139
reed@google.comdc731fd2010-12-23 15:19:47 +0000140 entry = fTail;
141 while (entry) {
142 count -= 1;
143 entry = entry->fPrev;
144 }
145 SkASSERT(0 == count);
146 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700147 SkASSERT(nullptr == fHead);
148 SkASSERT(nullptr == fTail);
reed@google.come49d5712011-01-19 14:30:26 +0000149 }
reed@google.comdc731fd2010-12-23 15:19:47 +0000150}
151
152#endif