86714e32881cc3c88e523337ef69fced93d7354f
[WebKit-https.git] / Source / WebCore / platform / graphics / cg / SubimageCacheWithTimer.cpp
1 /*
2  * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "SubimageCacheWithTimer.h"
28
29 #include <wtf/Vector.h>
30
31 #if CACHE_SUBIMAGES
32
33 namespace WebCore {
34
35 static const auto subimageCacheClearDelay = std::chrono::seconds { 1 };
36 static const int maxSubimageCacheSize = 300;
37
38 struct SubimageRequest {
39     CGImageRef image;
40     const FloatRect& rect;
41     SubimageRequest(CGImageRef image, const FloatRect& rect) : image(image), rect(rect) { }
42 };
43
44 struct SubimageCacheAdder {
45     static unsigned hash(const SubimageRequest& value)
46     {
47         return SubimageCacheWithTimer::SubimageCacheHash::hash(value.image, value.rect);
48     }
49
50     static bool equal(const SubimageCacheWithTimer::SubimageCacheEntry& a, const SubimageRequest& b)
51     {
52         return a.image == b.image && a.rect == b.rect;
53     }
54
55     static void translate(SubimageCacheWithTimer::SubimageCacheEntry& entry, const SubimageRequest& request, unsigned /*hashCode*/)
56     {
57         entry.image = request.image;
58         entry.rect = request.rect;
59         entry.subimage = adoptCF(CGImageCreateWithImageInRect(request.image, request.rect));
60     }
61 };
62
63 SubimageCacheWithTimer::SubimageCacheWithTimer()
64     : m_timer(this, &SubimageCacheWithTimer::invalidateCacheTimerFired, subimageCacheClearDelay)
65 {
66 }
67
68 void SubimageCacheWithTimer::invalidateCacheTimerFired()
69 {
70     m_images.clear();
71     m_cache.clear();
72 }
73
74 RetainPtr<CGImageRef> SubimageCacheWithTimer::getSubimage(CGImageRef image, const FloatRect& rect)
75 {
76     m_timer.restart();
77     if (m_cache.size() == maxSubimageCacheSize) {
78         SubimageCacheEntry entry = *m_cache.begin();
79         m_images.remove(entry.image.get());
80         m_cache.remove(entry);
81     }
82
83     ASSERT(m_cache.size() < maxSubimageCacheSize);
84     SubimageCache::AddResult result = m_cache.add<SubimageCacheAdder>(SubimageRequest(image, rect));
85     if (result.isNewEntry)
86         m_images.add(image);
87
88     return result.iterator->subimage;
89 }
90
91 void SubimageCacheWithTimer::clearImage(CGImageRef image)
92 {
93     if (m_images.contains(image)) {
94         Vector<SubimageCacheEntry> toBeRemoved;
95         SubimageCache::const_iterator end = m_cache.end();
96         for (SubimageCache::const_iterator it = m_cache.begin(); it != end; ++it) {
97             if (it->image.get() == image)
98                 toBeRemoved.append(*it);
99         }
100
101         for (Vector<SubimageCacheEntry>::iterator removeIt = toBeRemoved.begin(); removeIt != toBeRemoved.end(); ++removeIt)
102             m_cache.remove(*removeIt);
103
104         m_images.removeAll(image);
105     }
106 }
107
108 SubimageCacheWithTimer& subimageCache()
109 {
110     static SubimageCacheWithTimer& cache = *new SubimageCacheWithTimer;
111     return cache;
112 }
113
114 }
115
116 #endif