SubimageCacheWithTimer.cpp [plain text]
#include "config.h"
#include "SubimageCacheWithTimer.h"
#include <wtf/Vector.h>
#if CACHE_SUBIMAGES
namespace WebCore {
static const double subimageCacheClearDelay = 1;
static const int maxSubimageCacheSize = 300;
struct SubimageRequest {
CGImageRef image;
const FloatRect& rect;
SubimageRequest(CGImageRef image, const FloatRect& rect) : image(image), rect(rect) { }
};
struct SubimageCacheAdder {
static unsigned hash(const SubimageRequest& value)
{
return SubimageCacheWithTimer::SubimageCacheHash::hash(value.image, value.rect);
}
static bool equal(const SubimageCacheWithTimer::SubimageCacheEntry& a, const SubimageRequest& b)
{
return a.image == b.image && a.rect == b.rect;
}
static void translate(SubimageCacheWithTimer::SubimageCacheEntry& entry, const SubimageRequest& request, unsigned )
{
entry.image = request.image;
entry.rect = request.rect;
entry.subimage = adoptCF(CGImageCreateWithImageInRect(request.image, request.rect));
}
};
SubimageCacheWithTimer::SubimageCacheWithTimer()
: m_timer(this, &SubimageCacheWithTimer::invalidateCacheTimerFired, subimageCacheClearDelay)
{
}
void SubimageCacheWithTimer::invalidateCacheTimerFired(DeferrableOneShotTimer<SubimageCacheWithTimer>*)
{
m_images.clear();
m_cache.clear();
}
RetainPtr<CGImageRef> SubimageCacheWithTimer::getSubimage(CGImageRef image, const FloatRect& rect)
{
m_timer.restart();
if (m_cache.size() == maxSubimageCacheSize) {
SubimageCacheEntry entry = *m_cache.begin();
m_images.remove(entry.image.get());
m_cache.remove(entry);
}
ASSERT(m_cache.size() < maxSubimageCacheSize);
SubimageCache::AddResult result = m_cache.add<SubimageRequest, SubimageCacheAdder>(SubimageRequest(image, rect));
if (result.isNewEntry)
m_images.add(image);
return result.iterator->subimage;
}
void SubimageCacheWithTimer::clearImage(CGImageRef image)
{
if (m_images.contains(image)) {
Vector<SubimageCacheEntry> toBeRemoved;
SubimageCache::const_iterator end = m_cache.end();
for (SubimageCache::const_iterator it = m_cache.begin(); it != end; ++it) {
if (it->image.get() == image)
toBeRemoved.append(*it);
}
for (Vector<SubimageCacheEntry>::iterator removeIt = toBeRemoved.begin(); removeIt != toBeRemoved.end(); ++removeIt)
m_cache.remove(*removeIt);
m_images.removeAll(image);
}
}
SubimageCacheWithTimer& subimageCache()
{
static SubimageCacheWithTimer& cache = *new SubimageCacheWithTimer;
return cache;
}
}
#endif