Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / platform / graphics / BitmapImageTest.cpp
blob5220867a3f999f2dd1c6cfb857abe5726a7b2b36
1 /*
2 * Copyright (c) 2013, Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
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.
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.
31 #include "config.h"
32 #include "platform/graphics/BitmapImage.h"
34 #include "platform/SharedBuffer.h"
35 #include "platform/graphics/DeferredImageDecoder.h"
36 #include "platform/graphics/ImageObserver.h"
37 #include "public/platform/Platform.h"
38 #include "public/platform/WebUnitTestSupport.h"
40 #include <gtest/gtest.h>
42 namespace blink {
44 class BitmapImageTest : public ::testing::Test {
45 public:
46 class FakeImageObserver : public ImageObserver {
47 public:
48 FakeImageObserver() : m_lastDecodedSizeChangedDelta(0) { }
50 virtual void decodedSizeChanged(const Image*, int delta)
52 m_lastDecodedSizeChangedDelta = delta;
54 void didDraw(const Image*) override { }
55 bool shouldPauseAnimation(const Image*) override { return false; }
56 void animationAdvanced(const Image*) override { }
58 virtual void changedInRect(const Image*, const IntRect&) { }
60 int m_lastDecodedSizeChangedDelta;
63 BitmapImageTest() : BitmapImageTest(false) { }
64 BitmapImageTest(bool enableDeferredDecoding) : m_enableDeferredDecoding(enableDeferredDecoding) { }
66 static PassRefPtr<SharedBuffer> readFile(const char* fileName)
68 String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
69 filePath.append(fileName);
70 return Platform::current()->unitTestSupport()->readFromFile(filePath);
73 // Accessors to BitmapImage's protected methods.
74 void destroyDecodedData(bool destroyAll) { m_image->destroyDecodedData(destroyAll); }
75 size_t frameCount() { return m_image->frameCount(); }
76 void frameAtIndex(size_t index)
78 m_image->frameAtIndex(index);
80 void setCurrentFrame(size_t frame) { m_image->m_currentFrame = frame; }
81 size_t frameDecodedSize(size_t frame) { return m_image->m_frames[frame].m_frameBytes; }
82 size_t decodedFramesCount() const { return m_image->m_frames.size(); }
84 void loadImage(const char* fileName, bool loadAllFrames = true)
86 RefPtr<SharedBuffer> imageData = readFile(fileName);
87 ASSERT_TRUE(imageData.get());
89 m_image->setData(imageData, true);
90 EXPECT_EQ(0u, decodedSize());
92 size_t frameCount = m_image->frameCount();
93 if (loadAllFrames) {
94 for (size_t i = 0; i < frameCount; ++i)
95 frameAtIndex(i);
99 size_t decodedSize()
101 // In the context of this test, the following loop will give the correct result, but only because the test
102 // forces all frames to be decoded in loadImage() above. There is no general guarantee that frameDecodedSize()
103 // is up-to-date. Because of how multi frame images (like GIF) work, requesting one frame to be decoded may
104 // require other previous frames to be decoded as well. In those cases frameDecodedSize() wouldn't return the
105 // correct thing for the previous frame because the decoded size wouldn't have propagated upwards to the
106 // BitmapImage frame cache.
107 size_t size = 0;
108 for (size_t i = 0; i < decodedFramesCount(); ++i)
109 size += frameDecodedSize(i);
110 return size;
113 void advanceAnimation()
115 m_image->advanceAnimation(0);
118 PassRefPtr<Image> imageForDefaultFrame()
120 return m_image->imageForDefaultFrame();
123 protected:
124 void SetUp() override
126 DeferredImageDecoder::setEnabled(m_enableDeferredDecoding);
127 m_image = BitmapImage::create(&m_imageObserver);
130 FakeImageObserver m_imageObserver;
131 RefPtr<BitmapImage> m_image;
133 private:
134 bool m_enableDeferredDecoding;
137 TEST_F(BitmapImageTest, destroyDecodedDataExceptCurrentFrame)
139 loadImage("/LayoutTests/fast/images/resources/animated-10color.gif");
140 size_t totalSize = decodedSize();
141 size_t frame = frameCount() / 2;
142 setCurrentFrame(frame);
143 size_t size = frameDecodedSize(frame);
144 destroyDecodedData(false);
145 EXPECT_LT(m_imageObserver.m_lastDecodedSizeChangedDelta, 0);
146 EXPECT_GE(m_imageObserver.m_lastDecodedSizeChangedDelta, -static_cast<int>(totalSize - size));
149 TEST_F(BitmapImageTest, destroyAllDecodedData)
151 loadImage("/LayoutTests/fast/images/resources/animated-10color.gif");
152 size_t totalSize = decodedSize();
153 EXPECT_GT(totalSize, 0u);
154 destroyDecodedData(true);
155 EXPECT_EQ(-static_cast<int>(totalSize), m_imageObserver.m_lastDecodedSizeChangedDelta);
156 EXPECT_EQ(0u, decodedSize());
159 TEST_F(BitmapImageTest, maybeAnimated)
161 loadImage("/LayoutTests/fast/images/resources/gif-loop-count.gif");
162 for (size_t i = 0; i < frameCount(); ++i) {
163 EXPECT_TRUE(m_image->maybeAnimated());
164 advanceAnimation();
166 EXPECT_FALSE(m_image->maybeAnimated());
169 TEST_F(BitmapImageTest, isAllDataReceived)
171 RefPtr<SharedBuffer> imageData = readFile("/LayoutTests/fast/images/resources/green.jpg");
172 ASSERT_TRUE(imageData.get());
174 RefPtr<BitmapImage> image = BitmapImage::create();
175 EXPECT_FALSE(image->isAllDataReceived());
177 image->setData(imageData, false);
178 EXPECT_FALSE(image->isAllDataReceived());
180 image->setData(imageData, true);
181 EXPECT_TRUE(image->isAllDataReceived());
183 image->setData(SharedBuffer::create("data", sizeof("data")), false);
184 EXPECT_FALSE(image->isAllDataReceived());
186 image->setData(imageData, true);
187 EXPECT_TRUE(image->isAllDataReceived());
190 TEST_F(BitmapImageTest, noColorProfile)
192 loadImage("/LayoutTests/fast/images/resources/green.jpg");
193 EXPECT_EQ(1u, decodedFramesCount());
194 EXPECT_EQ(1024u, decodedSize());
195 EXPECT_FALSE(m_image->hasColorProfile());
198 #if USE(QCMSLIB)
200 TEST_F(BitmapImageTest, jpegHasColorProfile)
202 loadImage("/LayoutTests/fast/images/resources/icc-v2-gbr.jpg");
203 EXPECT_EQ(1u, decodedFramesCount());
204 EXPECT_EQ(227700u, decodedSize());
205 EXPECT_TRUE(m_image->hasColorProfile());
208 TEST_F(BitmapImageTest, pngHasColorProfile)
210 loadImage("/LayoutTests/fast/images/resources/palatted-color-png-gamma-one-color-profile.png");
211 EXPECT_EQ(1u, decodedFramesCount());
212 EXPECT_EQ(65536u, decodedSize());
213 EXPECT_TRUE(m_image->hasColorProfile());
216 TEST_F(BitmapImageTest, webpHasColorProfile)
218 loadImage("/LayoutTests/fast/images/resources/webp-color-profile-lossy.webp");
219 EXPECT_EQ(1u, decodedFramesCount());
220 EXPECT_EQ(2560000u, decodedSize());
221 EXPECT_TRUE(m_image->hasColorProfile());
224 #endif // USE(QCMSLIB)
226 TEST_F(BitmapImageTest, icoHasWrongFrameDimensions)
228 loadImage("/LayoutTests/fast/images/resources/wrong-frame-dimensions.ico");
229 // This call would cause crash without fix for 408026
230 imageForDefaultFrame();
233 TEST_F(BitmapImageTest, correctDecodedDataSize)
235 // When requesting a frame of a multi-frame GIF causes another frame to be
236 // decoded as well, both frames' sizes should be included in the decoded
237 // size changed notification.
238 loadImage("/LayoutTests/fast/images/resources/anim_none.gif", false);
239 frameAtIndex(1);
240 int frameSize = static_cast<int>(m_image->size().area() * sizeof(ImageFrame::PixelData));
241 EXPECT_EQ(frameSize * 2, m_imageObserver.m_lastDecodedSizeChangedDelta);
243 // Trying to destroy all data except an undecoded frame should cause the
244 // decoder to seek backwards and preserve the most recent previous frame
245 // necessary to decode that undecoded frame, and destroy all other frames.
246 setCurrentFrame(2);
247 destroyDecodedData(false);
248 EXPECT_EQ(-frameSize, m_imageObserver.m_lastDecodedSizeChangedDelta);
251 class BitmapImageDeferredDecodingTest : public BitmapImageTest {
252 public:
253 BitmapImageDeferredDecodingTest() : BitmapImageTest(true) { }
256 TEST_F(BitmapImageDeferredDecodingTest, correctDecodedDataSize)
258 // When deferred decoding is enabled, requesting any one frame shouldn't
259 // result in decoding any other frames.
260 loadImage("/LayoutTests/fast/images/resources/anim_none.gif", false);
261 frameAtIndex(1);
262 int frameSize = static_cast<int>(m_image->size().area() * sizeof(ImageFrame::PixelData));
263 EXPECT_EQ(frameSize, m_imageObserver.m_lastDecodedSizeChangedDelta);
264 frameAtIndex(0);
266 // Trying to destroy all data except an undecoded frame should go ahead and
267 // destroy all other frames.
268 setCurrentFrame(2);
269 destroyDecodedData(false);
270 EXPECT_EQ(-frameSize * 2, m_imageObserver.m_lastDecodedSizeChangedDelta);
273 } // namespace blink