initial import
[vuplus_webkit] / Source / WebCore / platform / graphics / skia / NativeImageSkia.cpp
1 /*
2  * Copyright (c) 2008, Google 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 are
6  * met:
7  * 
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  * 
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #include "skia/ext/image_operations.h"
34
35 #include "NativeImageSkia.h"
36 #include "GraphicsContext3D.h"
37 #include "SkiaUtils.h"
38
39 namespace WebCore {
40
41 NativeImageSkia::NativeImageSkia()
42     : m_resizeRequests(0),
43       m_isDataComplete(false)
44 {
45 }
46
47 NativeImageSkia::NativeImageSkia(const SkBitmap& other)
48     : m_image(other),
49       m_resizeRequests(0),
50       m_isDataComplete(false)
51 {
52 }
53
54 NativeImageSkia::~NativeImageSkia()
55 {
56 }
57
58 int NativeImageSkia::decodedSize() const
59 {
60     return m_image.getSize() + m_resizedImage.getSize();
61 }
62
63 bool NativeImageSkia::hasResizedBitmap(const SkIRect& srcSubset, int destWidth, int destHeight) const
64 {
65     return m_cachedImageInfo.isEqual(srcSubset, destWidth, destHeight) && !m_resizedImage.empty();
66 }
67
68 SkBitmap NativeImageSkia::resizedBitmap(const SkIRect& srcSubset,
69                                         int destWidth,
70                                         int destHeight,
71                                         const SkIRect& destVisibleSubset) const
72 {
73     if (!hasResizedBitmap(srcSubset, destWidth, destHeight)) {
74         bool shouldCache = m_isDataComplete
75             && shouldCacheResampling(srcSubset, destWidth, destHeight, destVisibleSubset);
76
77         SkBitmap subset;
78         m_image.extractSubset(&subset, srcSubset);
79         if (!shouldCache) {
80             // Just resize the visible subset and return it.
81             SkBitmap resizedImage = skia::ImageOperations::Resize(subset, skia::ImageOperations::RESIZE_LANCZOS3, destWidth, destHeight, destVisibleSubset);
82             return resizedImage;
83         }
84
85         m_resizedImage = skia::ImageOperations::Resize(subset, skia::ImageOperations::RESIZE_LANCZOS3, destWidth, destHeight);
86     }
87
88     SkBitmap visibleBitmap;
89     m_resizedImage.extractSubset(&visibleBitmap, destVisibleSubset);
90     return visibleBitmap;
91 }
92
93 bool NativeImageSkia::shouldCacheResampling(const SkIRect& srcSubset,
94                                             int destWidth,
95                                             int destHeight,
96                                             const SkIRect& destVisibleSubset) const
97 {
98     // Check whether the requested dimensions match previous request.
99     bool matchesPreviousRequest = m_cachedImageInfo.isEqual(srcSubset, destWidth, destHeight);
100     if (matchesPreviousRequest)
101         ++m_resizeRequests;
102     else {
103         m_cachedImageInfo.set(srcSubset, destWidth, destHeight);
104         m_resizeRequests = 0;
105         // Reset m_resizedImage now, because we don't distinguish between the
106         // last requested resize info and m_resizedImage's resize info.
107         m_resizedImage.reset();
108     }
109
110     // We can not cache incomplete frames. This might be a good optimization in
111     // the future, were we know how much of the frame has been decoded, so when
112     // we incrementally draw more of the image, we only have to resample the
113     // parts that are changed.
114     if (!m_isDataComplete)
115         return false;
116
117     // If the destination bitmap is small, we'll always allow caching, since
118     // there is not very much penalty for computing it and it may come in handy.
119     static const int kSmallBitmapSize = 4096;
120     if (destWidth * destHeight <= kSmallBitmapSize)
121         return true;
122
123     // If "too many" requests have been made for this bitmap, we assume that
124     // many more will be made as well, and we'll go ahead and cache it.
125     static const int kManyRequestThreshold = 4;
126     if (m_resizeRequests >= kManyRequestThreshold)
127         return true;
128
129     // If more than 1/4 of the resized image is visible, it's worth caching.
130     int destVisibleSize = destVisibleSubset.width() * destVisibleSubset.height();
131     return (destVisibleSize > (destWidth * destHeight) / 4);
132 }
133
134 NativeImageSkia::CachedImageInfo::CachedImageInfo()
135 {
136     srcSubset.setEmpty();
137 }
138
139 bool NativeImageSkia::CachedImageInfo::isEqual(const SkIRect& otherSrcSubset, int width, int height) const
140 {
141     return srcSubset == otherSrcSubset
142         && requestSize.width() == width
143         && requestSize.height() == height;
144 }
145
146 void NativeImageSkia::CachedImageInfo::set(const SkIRect& otherSrcSubset, int width, int height)
147 {
148     srcSubset = otherSrcSubset;
149     requestSize.setWidth(width);
150     requestSize.setHeight(height);
151 }
152
153 } // namespace WebCore