157c3a863fce929a96463ab24318006f8b2afcc7areed@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com */
8dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
10a6cac4ce3896669e1b5935def0a84b4456ec9777reed#include "SkGradientBitmapCache.h"
11dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
12a6cac4ce3896669e1b5935def0a84b4456ec9777reedstruct SkGradientBitmapCache::Entry {
13dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    Entry*      fPrev;
14dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    Entry*      fNext;
15dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
16dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    void*       fBuffer;
17dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    size_t      fSize;
18dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    SkBitmap    fBitmap;
19dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
203c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org    Entry(const void* buffer, size_t size, const SkBitmap& bm)
213c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org            : fPrev(NULL),
223c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org              fNext(NULL),
233c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org              fBitmap(bm) {
24dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fBuffer = sk_malloc_throw(size);
25dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fSize = size;
26dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        memcpy(fBuffer, buffer, size);
27dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
28dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
29dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    ~Entry() { sk_free(fBuffer); }
30dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
31dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    bool equals(const void* buffer, size_t size) const {
32dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        return (fSize == size) && !memcmp(fBuffer, buffer, size);
33dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
34dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com};
35dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
36a6cac4ce3896669e1b5935def0a84b4456ec9777reedSkGradientBitmapCache::SkGradientBitmapCache(int max) : fMaxEntries(max) {
37dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    fEntryCount = 0;
38dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    fHead = fTail = NULL;
39dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
40dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    this->validate();
41dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
42dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
43a6cac4ce3896669e1b5935def0a84b4456ec9777reedSkGradientBitmapCache::~SkGradientBitmapCache() {
44dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    this->validate();
45dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
46dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    Entry* entry = fHead;
47dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    while (entry) {
48dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        Entry* next = entry->fNext;
49dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        delete entry;
50dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        entry = next;
51dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
52dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
53dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
54a6cac4ce3896669e1b5935def0a84b4456ec9777reedSkGradientBitmapCache::Entry* SkGradientBitmapCache::detach(Entry* entry) const {
55dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    if (entry->fPrev) {
56dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(fHead != entry);
57dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        entry->fPrev->fNext = entry->fNext;
58dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    } else {
59dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(fHead == entry);
60dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fHead = entry->fNext;
61dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
62dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    if (entry->fNext) {
63dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(fTail != entry);
64dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        entry->fNext->fPrev = entry->fPrev;
65dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    } else {
66dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(fTail == entry);
67dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fTail = entry->fPrev;
68dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
69dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    return entry;
70dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
71dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
72a6cac4ce3896669e1b5935def0a84b4456ec9777reedvoid SkGradientBitmapCache::attachToHead(Entry* entry) const {
73dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    entry->fPrev = NULL;
74dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    entry->fNext = fHead;
75dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    if (fHead) {
76dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fHead->fPrev = entry;
77dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    } else {
78dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fTail = entry;
79dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
80dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    fHead = entry;
81dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
82dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
83a6cac4ce3896669e1b5935def0a84b4456ec9777reedbool SkGradientBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
84dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    AutoValidate av(this);
85dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
86dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    Entry* entry = fHead;
87dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    while (entry) {
88dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        if (entry->equals(buffer, size)) {
89dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            if (bm) {
90dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com                *bm = entry->fBitmap;
91dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            }
92dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            // move to the head of our list, so we purge it last
93dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            this->detach(entry);
94dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            this->attachToHead(entry);
95dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            return true;
96dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        }
97dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        entry = entry->fNext;
98dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
99dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    return false;
100dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
101dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
102a6cac4ce3896669e1b5935def0a84b4456ec9777reedvoid SkGradientBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
103dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    AutoValidate av(this);
104e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com
105dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    if (fEntryCount == fMaxEntries) {
106e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com        SkASSERT(fTail);
107e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com        delete this->detach(fTail);
108e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com        fEntryCount -= 1;
109dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
110dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
111060ef18d5c02029eade04961f4cf62068d72a68etomhudson@google.com    Entry* entry = SkNEW_ARGS(Entry, (buffer, len, bm));
112dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    this->attachToHead(entry);
113dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    fEntryCount += 1;
114dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
115dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
116dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com///////////////////////////////////////////////////////////////////////////////
117dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
118dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com#ifdef SK_DEBUG
119dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
120a6cac4ce3896669e1b5935def0a84b4456ec9777reedvoid SkGradientBitmapCache::validate() const {
121dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
122e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com
123dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    if (fEntryCount > 0) {
124dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(NULL == fHead->fPrev);
125dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(NULL == fTail->fNext);
126dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
127dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        if (fEntryCount == 1) {
128dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            SkASSERT(fHead == fTail);
129dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        } else {
130dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            SkASSERT(fHead != fTail);
131dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        }
132dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
133dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        Entry* entry = fHead;
134dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        int count = 0;
135dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        while (entry) {
136dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            count += 1;
137dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            entry = entry->fNext;
138dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        }
139dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(count == fEntryCount);
140e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com
141dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        entry = fTail;
142dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        while (entry) {
143dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            count -= 1;
144dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            entry = entry->fPrev;
145dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        }
146dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(0 == count);
147dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    } else {
148dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(NULL == fHead);
149dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(NULL == fTail);
150e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com    }
151dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
152dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
153dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com#endif
154