OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 17 matching lines...) Expand all Loading... |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #include "platform/image-decoders/gif/GIFImageDecoder.h" | 31 #include "platform/image-decoders/gif/GIFImageDecoder.h" |
32 | 32 |
33 #include "platform/SharedBuffer.h" | 33 #include "platform/SharedBuffer.h" |
34 #include "platform/image-decoders/ImageDecoderTestHelpers.h" | 34 #include "platform/image-decoders/ImageDecoderTestHelpers.h" |
35 #include "public/platform/WebData.h" | 35 #include "public/platform/WebData.h" |
36 #include "public/platform/WebSize.h" | 36 #include "public/platform/WebSize.h" |
37 #include "testing/gtest/include/gtest/gtest.h" | 37 #include "testing/gtest/include/gtest/gtest.h" |
38 #include "wtf/OwnPtr.h" | 38 #include "wtf/PtrUtil.h" |
39 #include "wtf/PassOwnPtr.h" | |
40 #include "wtf/Vector.h" | 39 #include "wtf/Vector.h" |
| 40 #include <memory> |
41 | 41 |
42 namespace blink { | 42 namespace blink { |
43 | 43 |
44 namespace { | 44 namespace { |
45 | 45 |
46 const char decodersTestingDir[] = "Source/platform/image-decoders/testing"; | 46 const char decodersTestingDir[] = "Source/platform/image-decoders/testing"; |
47 const char layoutTestResourcesDir[] = "LayoutTests/fast/images/resources"; | 47 const char layoutTestResourcesDir[] = "LayoutTests/fast/images/resources"; |
48 | 48 |
49 PassOwnPtr<ImageDecoder> createDecoder() | 49 std::unique_ptr<ImageDecoder> createDecoder() |
50 { | 50 { |
51 return adoptPtr(new GIFImageDecoder(ImageDecoder::AlphaNotPremultiplied, Ima
geDecoder::GammaAndColorProfileApplied, ImageDecoder::noDecodedImageByteLimit)); | 51 return wrapUnique(new GIFImageDecoder(ImageDecoder::AlphaNotPremultiplied, I
mageDecoder::GammaAndColorProfileApplied, ImageDecoder::noDecodedImageByteLimit)
); |
52 } | 52 } |
53 | 53 |
54 void testRandomFrameDecode(const char* dir, const char* gifFile) | 54 void testRandomFrameDecode(const char* dir, const char* gifFile) |
55 { | 55 { |
56 SCOPED_TRACE(gifFile); | 56 SCOPED_TRACE(gifFile); |
57 | 57 |
58 RefPtr<SharedBuffer> fullData = readFile(dir, gifFile); | 58 RefPtr<SharedBuffer> fullData = readFile(dir, gifFile); |
59 ASSERT_TRUE(fullData.get()); | 59 ASSERT_TRUE(fullData.get()); |
60 Vector<unsigned> baselineHashes; | 60 Vector<unsigned> baselineHashes; |
61 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes); | 61 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes); |
62 size_t frameCount = baselineHashes.size(); | 62 size_t frameCount = baselineHashes.size(); |
63 | 63 |
64 // Random decoding should get the same results as sequential decoding. | 64 // Random decoding should get the same results as sequential decoding. |
65 OwnPtr<ImageDecoder> decoder = createDecoder(); | 65 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
66 decoder->setData(fullData.get(), true); | 66 decoder->setData(fullData.get(), true); |
67 const size_t skippingStep = 5; | 67 const size_t skippingStep = 5; |
68 for (size_t i = 0; i < skippingStep; ++i) { | 68 for (size_t i = 0; i < skippingStep; ++i) { |
69 for (size_t j = i; j < frameCount; j += skippingStep) { | 69 for (size_t j = i; j < frameCount; j += skippingStep) { |
70 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j); | 70 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j); |
71 ImageFrame* frame = decoder->frameBufferAtIndex(j); | 71 ImageFrame* frame = decoder->frameBufferAtIndex(j); |
72 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->bitmap())); | 72 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->bitmap())); |
73 } | 73 } |
74 } | 74 } |
75 | 75 |
(...skipping 10 matching lines...) Expand all Loading... |
86 void testRandomDecodeAfterClearFrameBufferCache(const char* dir, const char* gif
File) | 86 void testRandomDecodeAfterClearFrameBufferCache(const char* dir, const char* gif
File) |
87 { | 87 { |
88 SCOPED_TRACE(gifFile); | 88 SCOPED_TRACE(gifFile); |
89 | 89 |
90 RefPtr<SharedBuffer> data = readFile(dir, gifFile); | 90 RefPtr<SharedBuffer> data = readFile(dir, gifFile); |
91 ASSERT_TRUE(data.get()); | 91 ASSERT_TRUE(data.get()); |
92 Vector<unsigned> baselineHashes; | 92 Vector<unsigned> baselineHashes; |
93 createDecodingBaseline(&createDecoder, data.get(), &baselineHashes); | 93 createDecodingBaseline(&createDecoder, data.get(), &baselineHashes); |
94 size_t frameCount = baselineHashes.size(); | 94 size_t frameCount = baselineHashes.size(); |
95 | 95 |
96 OwnPtr<ImageDecoder> decoder = createDecoder(); | 96 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
97 decoder->setData(data.get(), true); | 97 decoder->setData(data.get(), true); |
98 for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExce
ptFrame) { | 98 for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExce
ptFrame) { |
99 decoder->clearCacheExceptFrame(clearExceptFrame); | 99 decoder->clearCacheExceptFrame(clearExceptFrame); |
100 const size_t skippingStep = 5; | 100 const size_t skippingStep = 5; |
101 for (size_t i = 0; i < skippingStep; ++i) { | 101 for (size_t i = 0; i < skippingStep; ++i) { |
102 for (size_t j = 0; j < frameCount; j += skippingStep) { | 102 for (size_t j = 0; j < frameCount; j += skippingStep) { |
103 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" <<
j); | 103 SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" <<
j); |
104 ImageFrame* frame = decoder->frameBufferAtIndex(j); | 104 ImageFrame* frame = decoder->frameBufferAtIndex(j); |
105 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->bitmap())); | 105 EXPECT_EQ(baselineHashes[j], hashBitmap(frame->bitmap())); |
106 } | 106 } |
107 } | 107 } |
108 } | 108 } |
109 } | 109 } |
110 | 110 |
111 } // anonymous namespace | 111 } // anonymous namespace |
112 | 112 |
113 TEST(GIFImageDecoderTest, decodeTwoFrames) | 113 TEST(GIFImageDecoderTest, decodeTwoFrames) |
114 { | 114 { |
115 OwnPtr<ImageDecoder> decoder = createDecoder(); | 115 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
116 | 116 |
117 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; | 117 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; |
118 ASSERT_TRUE(data.get()); | 118 ASSERT_TRUE(data.get()); |
119 decoder->setData(data.get(), true); | 119 decoder->setData(data.get(), true); |
120 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); | 120 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); |
121 | 121 |
122 ImageFrame* frame = decoder->frameBufferAtIndex(0); | 122 ImageFrame* frame = decoder->frameBufferAtIndex(0); |
123 uint32_t generationID0 = frame->bitmap().getGenerationID(); | 123 uint32_t generationID0 = frame->bitmap().getGenerationID(); |
124 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus()); | 124 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus()); |
125 EXPECT_EQ(16, frame->bitmap().width()); | 125 EXPECT_EQ(16, frame->bitmap().width()); |
126 EXPECT_EQ(16, frame->bitmap().height()); | 126 EXPECT_EQ(16, frame->bitmap().height()); |
127 | 127 |
128 frame = decoder->frameBufferAtIndex(1); | 128 frame = decoder->frameBufferAtIndex(1); |
129 uint32_t generationID1 = frame->bitmap().getGenerationID(); | 129 uint32_t generationID1 = frame->bitmap().getGenerationID(); |
130 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus()); | 130 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus()); |
131 EXPECT_EQ(16, frame->bitmap().width()); | 131 EXPECT_EQ(16, frame->bitmap().width()); |
132 EXPECT_EQ(16, frame->bitmap().height()); | 132 EXPECT_EQ(16, frame->bitmap().height()); |
133 EXPECT_TRUE(generationID0 != generationID1); | 133 EXPECT_TRUE(generationID0 != generationID1); |
134 | 134 |
135 EXPECT_EQ(2u, decoder->frameCount()); | 135 EXPECT_EQ(2u, decoder->frameCount()); |
136 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); | 136 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); |
137 } | 137 } |
138 | 138 |
139 TEST(GIFImageDecoderTest, parseAndDecode) | 139 TEST(GIFImageDecoderTest, parseAndDecode) |
140 { | 140 { |
141 OwnPtr<ImageDecoder> decoder = createDecoder(); | 141 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
142 | 142 |
143 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; | 143 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; |
144 ASSERT_TRUE(data.get()); | 144 ASSERT_TRUE(data.get()); |
145 decoder->setData(data.get(), true); | 145 decoder->setData(data.get(), true); |
146 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); | 146 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); |
147 | 147 |
148 // This call will parse the entire file. | 148 // This call will parse the entire file. |
149 EXPECT_EQ(2u, decoder->frameCount()); | 149 EXPECT_EQ(2u, decoder->frameCount()); |
150 | 150 |
151 ImageFrame* frame = decoder->frameBufferAtIndex(0); | 151 ImageFrame* frame = decoder->frameBufferAtIndex(0); |
152 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus()); | 152 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus()); |
153 EXPECT_EQ(16, frame->bitmap().width()); | 153 EXPECT_EQ(16, frame->bitmap().width()); |
154 EXPECT_EQ(16, frame->bitmap().height()); | 154 EXPECT_EQ(16, frame->bitmap().height()); |
155 | 155 |
156 frame = decoder->frameBufferAtIndex(1); | 156 frame = decoder->frameBufferAtIndex(1); |
157 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus()); | 157 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus()); |
158 EXPECT_EQ(16, frame->bitmap().width()); | 158 EXPECT_EQ(16, frame->bitmap().width()); |
159 EXPECT_EQ(16, frame->bitmap().height()); | 159 EXPECT_EQ(16, frame->bitmap().height()); |
160 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); | 160 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); |
161 } | 161 } |
162 | 162 |
163 TEST(GIFImageDecoderTest, parseByteByByte) | 163 TEST(GIFImageDecoderTest, parseByteByByte) |
164 { | 164 { |
165 OwnPtr<ImageDecoder> decoder = createDecoder(); | 165 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
166 | 166 |
167 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; | 167 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; |
168 ASSERT_TRUE(data.get()); | 168 ASSERT_TRUE(data.get()); |
169 | 169 |
170 size_t frameCount = 0; | 170 size_t frameCount = 0; |
171 | 171 |
172 // Pass data to decoder byte by byte. | 172 // Pass data to decoder byte by byte. |
173 for (size_t length = 1; length <= data->size(); ++length) { | 173 for (size_t length = 1; length <= data->size(); ++length) { |
174 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt
h); | 174 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt
h); |
175 decoder->setData(tempData.get(), length == data->size()); | 175 decoder->setData(tempData.get(), length == data->size()); |
176 | 176 |
177 EXPECT_LE(frameCount, decoder->frameCount()); | 177 EXPECT_LE(frameCount, decoder->frameCount()); |
178 frameCount = decoder->frameCount(); | 178 frameCount = decoder->frameCount(); |
179 } | 179 } |
180 | 180 |
181 EXPECT_EQ(2u, decoder->frameCount()); | 181 EXPECT_EQ(2u, decoder->frameCount()); |
182 | 182 |
183 decoder->frameBufferAtIndex(0); | 183 decoder->frameBufferAtIndex(0); |
184 decoder->frameBufferAtIndex(1); | 184 decoder->frameBufferAtIndex(1); |
185 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); | 185 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); |
186 } | 186 } |
187 | 187 |
188 TEST(GIFImageDecoderTest, parseAndDecodeByteByByte) | 188 TEST(GIFImageDecoderTest, parseAndDecodeByteByByte) |
189 { | 189 { |
190 OwnPtr<ImageDecoder> decoder = createDecoder(); | 190 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
191 | 191 |
192 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated-gif-w
ith-offsets.gif"); | 192 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated-gif-w
ith-offsets.gif"); |
193 ASSERT_TRUE(data.get()); | 193 ASSERT_TRUE(data.get()); |
194 | 194 |
195 size_t frameCount = 0; | 195 size_t frameCount = 0; |
196 size_t framesDecoded = 0; | 196 size_t framesDecoded = 0; |
197 | 197 |
198 // Pass data to decoder byte by byte. | 198 // Pass data to decoder byte by byte. |
199 for (size_t length = 1; length <= data->size(); ++length) { | 199 for (size_t length = 1; length <= data->size(); ++length) { |
200 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt
h); | 200 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), lengt
h); |
201 decoder->setData(tempData.get(), length == data->size()); | 201 decoder->setData(tempData.get(), length == data->size()); |
202 | 202 |
203 EXPECT_LE(frameCount, decoder->frameCount()); | 203 EXPECT_LE(frameCount, decoder->frameCount()); |
204 frameCount = decoder->frameCount(); | 204 frameCount = decoder->frameCount(); |
205 | 205 |
206 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1); | 206 ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1); |
207 if (frame && frame->getStatus() == ImageFrame::FrameComplete && framesDe
coded < frameCount) | 207 if (frame && frame->getStatus() == ImageFrame::FrameComplete && framesDe
coded < frameCount) |
208 ++framesDecoded; | 208 ++framesDecoded; |
209 } | 209 } |
210 | 210 |
211 EXPECT_EQ(5u, decoder->frameCount()); | 211 EXPECT_EQ(5u, decoder->frameCount()); |
212 EXPECT_EQ(5u, framesDecoded); | 212 EXPECT_EQ(5u, framesDecoded); |
213 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); | 213 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); |
214 } | 214 } |
215 | 215 |
216 TEST(GIFImageDecoderTest, brokenSecondFrame) | 216 TEST(GIFImageDecoderTest, brokenSecondFrame) |
217 { | 217 { |
218 OwnPtr<ImageDecoder> decoder = createDecoder(); | 218 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
219 | 219 |
220 RefPtr<SharedBuffer> data = readFile(decodersTestingDir, "broken.gif"); | 220 RefPtr<SharedBuffer> data = readFile(decodersTestingDir, "broken.gif"); |
221 ASSERT_TRUE(data.get()); | 221 ASSERT_TRUE(data.get()); |
222 decoder->setData(data.get(), true); | 222 decoder->setData(data.get(), true); |
223 | 223 |
224 // One frame is detected but cannot be decoded. | 224 // One frame is detected but cannot be decoded. |
225 EXPECT_EQ(1u, decoder->frameCount()); | 225 EXPECT_EQ(1u, decoder->frameCount()); |
226 ImageFrame* frame = decoder->frameBufferAtIndex(1); | 226 ImageFrame* frame = decoder->frameBufferAtIndex(1); |
227 EXPECT_FALSE(frame); | 227 EXPECT_FALSE(frame); |
228 } | 228 } |
229 | 229 |
230 TEST(GIFImageDecoderTest, progressiveDecode) | 230 TEST(GIFImageDecoderTest, progressiveDecode) |
231 { | 231 { |
232 RefPtr<SharedBuffer> fullData = readFile(decodersTestingDir, "radient.gif"); | 232 RefPtr<SharedBuffer> fullData = readFile(decodersTestingDir, "radient.gif"); |
233 ASSERT_TRUE(fullData.get()); | 233 ASSERT_TRUE(fullData.get()); |
234 const size_t fullLength = fullData->size(); | 234 const size_t fullLength = fullData->size(); |
235 | 235 |
236 OwnPtr<ImageDecoder> decoder; | 236 std::unique_ptr<ImageDecoder> decoder; |
237 ImageFrame* frame; | 237 ImageFrame* frame; |
238 | 238 |
239 Vector<unsigned> truncatedHashes; | 239 Vector<unsigned> truncatedHashes; |
240 Vector<unsigned> progressiveHashes; | 240 Vector<unsigned> progressiveHashes; |
241 | 241 |
242 // Compute hashes when the file is truncated. | 242 // Compute hashes when the file is truncated. |
243 const size_t increment = 1; | 243 const size_t increment = 1; |
244 for (size_t i = 1; i <= fullLength; i += increment) { | 244 for (size_t i = 1; i <= fullLength; i += increment) { |
245 decoder = createDecoder(); | 245 decoder = createDecoder(); |
246 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i); | 246 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i); |
(...skipping 26 matching lines...) Expand all Loading... |
273 if (truncatedHashes[i] != progressiveHashes[i]) { | 273 if (truncatedHashes[i] != progressiveHashes[i]) { |
274 match = false; | 274 match = false; |
275 break; | 275 break; |
276 } | 276 } |
277 } | 277 } |
278 EXPECT_TRUE(match); | 278 EXPECT_TRUE(match); |
279 } | 279 } |
280 | 280 |
281 TEST(GIFImageDecoderTest, allDataReceivedTruncation) | 281 TEST(GIFImageDecoderTest, allDataReceivedTruncation) |
282 { | 282 { |
283 OwnPtr<ImageDecoder> decoder = createDecoder(); | 283 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
284 | 284 |
285 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; | 285 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; |
286 ASSERT_TRUE(data.get()); | 286 ASSERT_TRUE(data.get()); |
287 | 287 |
288 ASSERT_GE(data->size(), 10u); | 288 ASSERT_GE(data->size(), 10u); |
289 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz
e() - 10); | 289 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz
e() - 10); |
290 decoder->setData(tempData.get(), true); | 290 decoder->setData(tempData.get(), true); |
291 | 291 |
292 EXPECT_EQ(2u, decoder->frameCount()); | 292 EXPECT_EQ(2u, decoder->frameCount()); |
293 EXPECT_FALSE(decoder->failed()); | 293 EXPECT_FALSE(decoder->failed()); |
294 | 294 |
295 decoder->frameBufferAtIndex(0); | 295 decoder->frameBufferAtIndex(0); |
296 EXPECT_FALSE(decoder->failed()); | 296 EXPECT_FALSE(decoder->failed()); |
297 decoder->frameBufferAtIndex(1); | 297 decoder->frameBufferAtIndex(1); |
298 EXPECT_TRUE(decoder->failed()); | 298 EXPECT_TRUE(decoder->failed()); |
299 } | 299 } |
300 | 300 |
301 TEST(GIFImageDecoderTest, frameIsComplete) | 301 TEST(GIFImageDecoderTest, frameIsComplete) |
302 { | 302 { |
303 OwnPtr<ImageDecoder> decoder = createDecoder(); | 303 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
304 | 304 |
305 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; | 305 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; |
306 ASSERT_TRUE(data.get()); | 306 ASSERT_TRUE(data.get()); |
307 decoder->setData(data.get(), true); | 307 decoder->setData(data.get(), true); |
308 | 308 |
309 EXPECT_EQ(2u, decoder->frameCount()); | 309 EXPECT_EQ(2u, decoder->frameCount()); |
310 EXPECT_FALSE(decoder->failed()); | 310 EXPECT_FALSE(decoder->failed()); |
311 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); | 311 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); |
312 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1)); | 312 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1)); |
313 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); | 313 EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); |
314 } | 314 } |
315 | 315 |
316 TEST(GIFImageDecoderTest, frameIsCompleteLoading) | 316 TEST(GIFImageDecoderTest, frameIsCompleteLoading) |
317 { | 317 { |
318 OwnPtr<ImageDecoder> decoder = createDecoder(); | 318 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
319 | 319 |
320 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; | 320 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "animated.gif")
; |
321 ASSERT_TRUE(data.get()); | 321 ASSERT_TRUE(data.get()); |
322 | 322 |
323 ASSERT_GE(data->size(), 10u); | 323 ASSERT_GE(data->size(), 10u); |
324 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz
e() - 10); | 324 RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->siz
e() - 10); |
325 decoder->setData(tempData.get(), false); | 325 decoder->setData(tempData.get(), false); |
326 | 326 |
327 EXPECT_EQ(2u, decoder->frameCount()); | 327 EXPECT_EQ(2u, decoder->frameCount()); |
328 EXPECT_FALSE(decoder->failed()); | 328 EXPECT_FALSE(decoder->failed()); |
329 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); | 329 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); |
330 EXPECT_FALSE(decoder->frameIsCompleteAtIndex(1)); | 330 EXPECT_FALSE(decoder->frameIsCompleteAtIndex(1)); |
331 | 331 |
332 decoder->setData(data.get(), true); | 332 decoder->setData(data.get(), true); |
333 EXPECT_EQ(2u, decoder->frameCount()); | 333 EXPECT_EQ(2u, decoder->frameCount()); |
334 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); | 334 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0)); |
335 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1)); | 335 EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1)); |
336 } | 336 } |
337 | 337 |
338 TEST(GIFImageDecoderTest, badTerminator) | 338 TEST(GIFImageDecoderTest, badTerminator) |
339 { | 339 { |
340 RefPtr<SharedBuffer> referenceData = readFile(decodersTestingDir, "radient.g
if"); | 340 RefPtr<SharedBuffer> referenceData = readFile(decodersTestingDir, "radient.g
if"); |
341 RefPtr<SharedBuffer> testData = readFile(decodersTestingDir, "radient-bad-te
rminator.gif"); | 341 RefPtr<SharedBuffer> testData = readFile(decodersTestingDir, "radient-bad-te
rminator.gif"); |
342 ASSERT_TRUE(referenceData.get()); | 342 ASSERT_TRUE(referenceData.get()); |
343 ASSERT_TRUE(testData.get()); | 343 ASSERT_TRUE(testData.get()); |
344 | 344 |
345 OwnPtr<ImageDecoder> referenceDecoder = createDecoder(); | 345 std::unique_ptr<ImageDecoder> referenceDecoder = createDecoder(); |
346 referenceDecoder->setData(referenceData.get(), true); | 346 referenceDecoder->setData(referenceData.get(), true); |
347 EXPECT_EQ(1u, referenceDecoder->frameCount()); | 347 EXPECT_EQ(1u, referenceDecoder->frameCount()); |
348 ImageFrame* referenceFrame = referenceDecoder->frameBufferAtIndex(0); | 348 ImageFrame* referenceFrame = referenceDecoder->frameBufferAtIndex(0); |
349 ASSERT(referenceFrame); | 349 ASSERT(referenceFrame); |
350 | 350 |
351 OwnPtr<ImageDecoder> testDecoder = createDecoder(); | 351 std::unique_ptr<ImageDecoder> testDecoder = createDecoder(); |
352 testDecoder->setData(testData.get(), true); | 352 testDecoder->setData(testData.get(), true); |
353 EXPECT_EQ(1u, testDecoder->frameCount()); | 353 EXPECT_EQ(1u, testDecoder->frameCount()); |
354 ImageFrame* testFrame = testDecoder->frameBufferAtIndex(0); | 354 ImageFrame* testFrame = testDecoder->frameBufferAtIndex(0); |
355 ASSERT(testFrame); | 355 ASSERT(testFrame); |
356 | 356 |
357 EXPECT_EQ(hashBitmap(referenceFrame->bitmap()), hashBitmap(testFrame->bitmap
())); | 357 EXPECT_EQ(hashBitmap(referenceFrame->bitmap()), hashBitmap(testFrame->bitmap
())); |
358 } | 358 } |
359 | 359 |
360 TEST(GIFImageDecoderTest, updateRequiredPreviousFrameAfterFirstDecode) | 360 TEST(GIFImageDecoderTest, updateRequiredPreviousFrameAfterFirstDecode) |
361 { | 361 { |
362 OwnPtr<ImageDecoder> decoder = createDecoder(); | 362 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
363 | 363 |
364 RefPtr<SharedBuffer> fullData = readFile(layoutTestResourcesDir, "animated-1
0color.gif"); | 364 RefPtr<SharedBuffer> fullData = readFile(layoutTestResourcesDir, "animated-1
0color.gif"); |
365 ASSERT_TRUE(fullData.get()); | 365 ASSERT_TRUE(fullData.get()); |
366 | 366 |
367 // Give it data that is enough to parse but not decode in order to check the
status | 367 // Give it data that is enough to parse but not decode in order to check the
status |
368 // of requiredPreviousFrameIndex before decoding. | 368 // of requiredPreviousFrameIndex before decoding. |
369 size_t partialSize = 1; | 369 size_t partialSize = 1; |
370 do { | 370 do { |
371 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti
alSize); | 371 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti
alSize); |
372 decoder->setData(data.get(), false); | 372 decoder->setData(data.get(), false); |
(...skipping 29 matching lines...) Expand all Loading... |
402 } | 402 } |
403 | 403 |
404 TEST(GIFImageDecoderTest, resumePartialDecodeAfterClearFrameBufferCache) | 404 TEST(GIFImageDecoderTest, resumePartialDecodeAfterClearFrameBufferCache) |
405 { | 405 { |
406 RefPtr<SharedBuffer> fullData = readFile(layoutTestResourcesDir, "animated-1
0color.gif"); | 406 RefPtr<SharedBuffer> fullData = readFile(layoutTestResourcesDir, "animated-1
0color.gif"); |
407 ASSERT_TRUE(fullData.get()); | 407 ASSERT_TRUE(fullData.get()); |
408 Vector<unsigned> baselineHashes; | 408 Vector<unsigned> baselineHashes; |
409 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes); | 409 createDecodingBaseline(&createDecoder, fullData.get(), &baselineHashes); |
410 size_t frameCount = baselineHashes.size(); | 410 size_t frameCount = baselineHashes.size(); |
411 | 411 |
412 OwnPtr<ImageDecoder> decoder = createDecoder(); | 412 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
413 | 413 |
414 // Let frame 0 be partially decoded. | 414 // Let frame 0 be partially decoded. |
415 size_t partialSize = 1; | 415 size_t partialSize = 1; |
416 do { | 416 do { |
417 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti
alSize); | 417 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), parti
alSize); |
418 decoder->setData(data.get(), false); | 418 decoder->setData(data.get(), false); |
419 ++partialSize; | 419 ++partialSize; |
420 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->getStatus
() == ImageFrame::FrameEmpty); | 420 } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->getStatus
() == ImageFrame::FrameEmpty); |
421 | 421 |
422 // Skip to the last frame and clear. | 422 // Skip to the last frame and clear. |
423 decoder->setData(fullData.get(), true); | 423 decoder->setData(fullData.get(), true); |
424 EXPECT_EQ(frameCount, decoder->frameCount()); | 424 EXPECT_EQ(frameCount, decoder->frameCount()); |
425 ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1); | 425 ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1); |
426 EXPECT_EQ(baselineHashes[frameCount - 1], hashBitmap(lastFrame->bitmap())); | 426 EXPECT_EQ(baselineHashes[frameCount - 1], hashBitmap(lastFrame->bitmap())); |
427 decoder->clearCacheExceptFrame(kNotFound); | 427 decoder->clearCacheExceptFrame(kNotFound); |
428 | 428 |
429 // Resume decoding of the first frame. | 429 // Resume decoding of the first frame. |
430 ImageFrame* firstFrame = decoder->frameBufferAtIndex(0); | 430 ImageFrame* firstFrame = decoder->frameBufferAtIndex(0); |
431 EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->getStatus()); | 431 EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->getStatus()); |
432 EXPECT_EQ(baselineHashes[0], hashBitmap(firstFrame->bitmap())); | 432 EXPECT_EQ(baselineHashes[0], hashBitmap(firstFrame->bitmap())); |
433 } | 433 } |
434 | 434 |
435 // The first LZW codes in the image are invalid values that try to create a loop | 435 // The first LZW codes in the image are invalid values that try to create a loop |
436 // in the dictionary. Decoding should fail, but not infinitely loop or corrupt m
emory. | 436 // in the dictionary. Decoding should fail, but not infinitely loop or corrupt m
emory. |
437 TEST(GIFImageDecoderTest, badInitialCode) | 437 TEST(GIFImageDecoderTest, badInitialCode) |
438 { | 438 { |
439 RefPtr<SharedBuffer> testData = readFile(decodersTestingDir, "bad-initial-co
de.gif"); | 439 RefPtr<SharedBuffer> testData = readFile(decodersTestingDir, "bad-initial-co
de.gif"); |
440 ASSERT_TRUE(testData.get()); | 440 ASSERT_TRUE(testData.get()); |
441 | 441 |
442 OwnPtr<ImageDecoder> testDecoder = createDecoder(); | 442 std::unique_ptr<ImageDecoder> testDecoder = createDecoder(); |
443 testDecoder->setData(testData.get(), true); | 443 testDecoder->setData(testData.get(), true); |
444 EXPECT_EQ(1u, testDecoder->frameCount()); | 444 EXPECT_EQ(1u, testDecoder->frameCount()); |
445 ASSERT_TRUE(testDecoder->frameBufferAtIndex(0)); | 445 ASSERT_TRUE(testDecoder->frameBufferAtIndex(0)); |
446 EXPECT_TRUE(testDecoder->failed()); | 446 EXPECT_TRUE(testDecoder->failed()); |
447 } | 447 } |
448 | 448 |
449 // The image has an invalid LZW code that exceeds dictionary size. Decoding shou
ld fail. | 449 // The image has an invalid LZW code that exceeds dictionary size. Decoding shou
ld fail. |
450 TEST(GIFImageDecoderTest, badCode) | 450 TEST(GIFImageDecoderTest, badCode) |
451 { | 451 { |
452 RefPtr<SharedBuffer> testData = readFile(decodersTestingDir, "bad-code.gif")
; | 452 RefPtr<SharedBuffer> testData = readFile(decodersTestingDir, "bad-code.gif")
; |
453 ASSERT_TRUE(testData.get()); | 453 ASSERT_TRUE(testData.get()); |
454 | 454 |
455 OwnPtr<ImageDecoder> testDecoder = createDecoder(); | 455 std::unique_ptr<ImageDecoder> testDecoder = createDecoder(); |
456 testDecoder->setData(testData.get(), true); | 456 testDecoder->setData(testData.get(), true); |
457 EXPECT_EQ(1u, testDecoder->frameCount()); | 457 EXPECT_EQ(1u, testDecoder->frameCount()); |
458 ASSERT_TRUE(testDecoder->frameBufferAtIndex(0)); | 458 ASSERT_TRUE(testDecoder->frameBufferAtIndex(0)); |
459 EXPECT_TRUE(testDecoder->failed()); | 459 EXPECT_TRUE(testDecoder->failed()); |
460 } | 460 } |
461 | 461 |
462 TEST(GIFImageDecoderTest, invalidDisposalMethod) | 462 TEST(GIFImageDecoderTest, invalidDisposalMethod) |
463 { | 463 { |
464 OwnPtr<ImageDecoder> decoder = createDecoder(); | 464 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
465 | 465 |
466 // The image has 2 frames, with disposal method 4 and 5, respectively. | 466 // The image has 2 frames, with disposal method 4 and 5, respectively. |
467 RefPtr<SharedBuffer> data = readFile(decodersTestingDir, "invalid-disposal-m
ethod.gif"); | 467 RefPtr<SharedBuffer> data = readFile(decodersTestingDir, "invalid-disposal-m
ethod.gif"); |
468 ASSERT_TRUE(data.get()); | 468 ASSERT_TRUE(data.get()); |
469 decoder->setData(data.get(), true); | 469 decoder->setData(data.get(), true); |
470 | 470 |
471 EXPECT_EQ(2u, decoder->frameCount()); | 471 EXPECT_EQ(2u, decoder->frameCount()); |
472 // Disposal method 4 is converted to ImageFrame::DisposeOverwritePrevious. | 472 // Disposal method 4 is converted to ImageFrame::DisposeOverwritePrevious. |
473 EXPECT_EQ(ImageFrame::DisposeOverwritePrevious, decoder->frameBufferAtIndex(
0)->getDisposalMethod()); | 473 EXPECT_EQ(ImageFrame::DisposeOverwritePrevious, decoder->frameBufferAtIndex(
0)->getDisposalMethod()); |
474 // Disposal method 5 is ignored. | 474 // Disposal method 5 is ignored. |
475 EXPECT_EQ(ImageFrame::DisposeNotSpecified, decoder->frameBufferAtIndex(1)->g
etDisposalMethod()); | 475 EXPECT_EQ(ImageFrame::DisposeNotSpecified, decoder->frameBufferAtIndex(1)->g
etDisposalMethod()); |
476 } | 476 } |
477 | 477 |
478 TEST(GIFImageDecoderTest, firstFrameHasGreaterSizeThanScreenSize) | 478 TEST(GIFImageDecoderTest, firstFrameHasGreaterSizeThanScreenSize) |
479 { | 479 { |
480 RefPtr<SharedBuffer> fullData = readFile(decodersTestingDir, "first-frame-ha
s-greater-size-than-screen-size.gif"); | 480 RefPtr<SharedBuffer> fullData = readFile(decodersTestingDir, "first-frame-ha
s-greater-size-than-screen-size.gif"); |
481 ASSERT_TRUE(fullData.get()); | 481 ASSERT_TRUE(fullData.get()); |
482 | 482 |
483 OwnPtr<ImageDecoder> decoder; | 483 std::unique_ptr<ImageDecoder> decoder; |
484 IntSize frameSize; | 484 IntSize frameSize; |
485 | 485 |
486 // Compute hashes when the file is truncated. | 486 // Compute hashes when the file is truncated. |
487 for (size_t i = 1; i <= fullData->size(); ++i) { | 487 for (size_t i = 1; i <= fullData->size(); ++i) { |
488 decoder = createDecoder(); | 488 decoder = createDecoder(); |
489 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i); | 489 RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i); |
490 decoder->setData(data.get(), i == fullData->size()); | 490 decoder->setData(data.get(), i == fullData->size()); |
491 | 491 |
492 if (decoder->isSizeAvailable() && !frameSize.width() && !frameSize.heigh
t()) { | 492 if (decoder->isSizeAvailable() && !frameSize.width() && !frameSize.heigh
t()) { |
493 frameSize = decoder->decodedSize(); | 493 frameSize = decoder->decodedSize(); |
494 continue; | 494 continue; |
495 } | 495 } |
496 | 496 |
497 ASSERT_EQ(frameSize.width(), decoder->decodedSize().width()); | 497 ASSERT_EQ(frameSize.width(), decoder->decodedSize().width()); |
498 ASSERT_EQ(frameSize.height(), decoder->decodedSize().height()); | 498 ASSERT_EQ(frameSize.height(), decoder->decodedSize().height()); |
499 } | 499 } |
500 } | 500 } |
501 | 501 |
502 TEST(GIFImageDecoderTest, verifyRepetitionCount) | 502 TEST(GIFImageDecoderTest, verifyRepetitionCount) |
503 { | 503 { |
504 const int expectedRepetitionCount = 2; | 504 const int expectedRepetitionCount = 2; |
505 OwnPtr<ImageDecoder> decoder = createDecoder(); | 505 std::unique_ptr<ImageDecoder> decoder = createDecoder(); |
506 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "full2loop.gif"
); | 506 RefPtr<SharedBuffer> data = readFile(layoutTestResourcesDir, "full2loop.gif"
); |
507 ASSERT_TRUE(data.get()); | 507 ASSERT_TRUE(data.get()); |
508 decoder->setData(data.get(), true); | 508 decoder->setData(data.get(), true); |
509 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); // Default value
before decode. | 509 EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount()); // Default value
before decode. |
510 | 510 |
511 for (size_t i = 0; i < decoder->frameCount(); ++i) { | 511 for (size_t i = 0; i < decoder->frameCount(); ++i) { |
512 ImageFrame* frame = decoder->frameBufferAtIndex(i); | 512 ImageFrame* frame = decoder->frameBufferAtIndex(i); |
513 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus()); | 513 EXPECT_EQ(ImageFrame::FrameComplete, frame->getStatus()); |
514 } | 514 } |
515 | 515 |
516 EXPECT_EQ(expectedRepetitionCount, decoder->repetitionCount()); // Expected
value after decode. | 516 EXPECT_EQ(expectedRepetitionCount, decoder->repetitionCount()); // Expected
value after decode. |
517 } | 517 } |
518 | 518 |
519 TEST(GIFImageDecoderTest, bitmapAlphaType) | 519 TEST(GIFImageDecoderTest, bitmapAlphaType) |
520 { | 520 { |
521 RefPtr<SharedBuffer> fullData = readFile(decodersTestingDir, "radient.gif"); | 521 RefPtr<SharedBuffer> fullData = readFile(decodersTestingDir, "radient.gif"); |
522 ASSERT_TRUE(fullData.get()); | 522 ASSERT_TRUE(fullData.get()); |
523 | 523 |
524 // Empirically chosen truncation size: | 524 // Empirically chosen truncation size: |
525 // a) large enough to produce a partial frame && | 525 // a) large enough to produce a partial frame && |
526 // b) small enough to not fully decode the frame | 526 // b) small enough to not fully decode the frame |
527 const size_t kTruncateSize = 800; | 527 const size_t kTruncateSize = 800; |
528 ASSERT_TRUE(kTruncateSize < fullData->size()); | 528 ASSERT_TRUE(kTruncateSize < fullData->size()); |
529 RefPtr<SharedBuffer> partialData = SharedBuffer::create(fullData->data(), kT
runcateSize); | 529 RefPtr<SharedBuffer> partialData = SharedBuffer::create(fullData->data(), kT
runcateSize); |
530 | 530 |
531 OwnPtr<ImageDecoder> premulDecoder = adoptPtr(new GIFImageDecoder( | 531 std::unique_ptr<ImageDecoder> premulDecoder = wrapUnique(new GIFImageDecoder
( |
532 ImageDecoder::AlphaPremultiplied, | 532 ImageDecoder::AlphaPremultiplied, |
533 ImageDecoder::GammaAndColorProfileApplied, | 533 ImageDecoder::GammaAndColorProfileApplied, |
534 ImageDecoder::noDecodedImageByteLimit)); | 534 ImageDecoder::noDecodedImageByteLimit)); |
535 OwnPtr<ImageDecoder> unpremulDecoder = adoptPtr(new GIFImageDecoder( | 535 std::unique_ptr<ImageDecoder> unpremulDecoder = wrapUnique(new GIFImageDecod
er( |
536 ImageDecoder::AlphaNotPremultiplied, | 536 ImageDecoder::AlphaNotPremultiplied, |
537 ImageDecoder::GammaAndColorProfileApplied, | 537 ImageDecoder::GammaAndColorProfileApplied, |
538 ImageDecoder::noDecodedImageByteLimit)); | 538 ImageDecoder::noDecodedImageByteLimit)); |
539 | 539 |
540 // Partially decoded frame => the frame alpha type is unknown and should ref
lect the requested format. | 540 // Partially decoded frame => the frame alpha type is unknown and should ref
lect the requested format. |
541 premulDecoder->setData(partialData.get(), false); | 541 premulDecoder->setData(partialData.get(), false); |
542 ASSERT_TRUE(premulDecoder->frameCount()); | 542 ASSERT_TRUE(premulDecoder->frameCount()); |
543 unpremulDecoder->setData(partialData.get(), false); | 543 unpremulDecoder->setData(partialData.get(), false); |
544 ASSERT_TRUE(unpremulDecoder->frameCount()); | 544 ASSERT_TRUE(unpremulDecoder->frameCount()); |
545 ImageFrame* premulFrame = premulDecoder->frameBufferAtIndex(0); | 545 ImageFrame* premulFrame = premulDecoder->frameBufferAtIndex(0); |
(...skipping 10 matching lines...) Expand all Loading... |
556 ASSERT_TRUE(unpremulDecoder->frameCount()); | 556 ASSERT_TRUE(unpremulDecoder->frameCount()); |
557 premulFrame = premulDecoder->frameBufferAtIndex(0); | 557 premulFrame = premulDecoder->frameBufferAtIndex(0); |
558 EXPECT_TRUE(premulFrame && premulFrame->getStatus() == ImageFrame::FrameComp
lete); | 558 EXPECT_TRUE(premulFrame && premulFrame->getStatus() == ImageFrame::FrameComp
lete); |
559 EXPECT_EQ(premulFrame->bitmap().alphaType(), kOpaque_SkAlphaType); | 559 EXPECT_EQ(premulFrame->bitmap().alphaType(), kOpaque_SkAlphaType); |
560 unpremulFrame = unpremulDecoder->frameBufferAtIndex(0); | 560 unpremulFrame = unpremulDecoder->frameBufferAtIndex(0); |
561 EXPECT_TRUE(unpremulFrame && unpremulFrame->getStatus() == ImageFrame::Frame
Complete); | 561 EXPECT_TRUE(unpremulFrame && unpremulFrame->getStatus() == ImageFrame::Frame
Complete); |
562 EXPECT_EQ(unpremulFrame->bitmap().alphaType(), kOpaque_SkAlphaType); | 562 EXPECT_EQ(unpremulFrame->bitmap().alphaType(), kOpaque_SkAlphaType); |
563 } | 563 } |
564 | 564 |
565 } // namespace blink | 565 } // namespace blink |
OLD | NEW |