OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ui/gfx/image/image_skia.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "base/logging.h" | |
9 #include "base/threading/simple_thread.h" | |
10 #include "testing/gtest/include/gtest/gtest.h" | |
11 #include "third_party/skia/include/core/SkBitmap.h" | |
12 #include "ui/gfx/image/image_skia_rep.h" | |
13 #include "ui/gfx/image/image_skia_source.h" | |
14 #include "ui/gfx/size.h" | |
15 #include "ui/gfx/switches.h" | |
16 | |
17 // Duplicated from base/threading/non_thread_safe.h so that we can be | |
18 // good citizens there and undef the macro. | |
19 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) | |
20 #define ENABLE_NON_THREAD_SAFE 1 | |
21 #else | |
22 #define ENABLE_NON_THREAD_SAFE 0 | |
23 #endif | |
24 | |
25 namespace gfx { | |
26 | |
27 namespace { | |
28 | |
29 class FixedSource : public ImageSkiaSource { | |
30 public: | |
31 explicit FixedSource(const ImageSkiaRep& image) : image_(image) {} | |
32 | |
33 ~FixedSource() override {} | |
34 | |
35 ImageSkiaRep GetImageForScale(float scale) override { return image_; } | |
36 | |
37 private: | |
38 ImageSkiaRep image_; | |
39 | |
40 DISALLOW_COPY_AND_ASSIGN(FixedSource); | |
41 }; | |
42 | |
43 class FixedScaleSource : public ImageSkiaSource { | |
44 public: | |
45 explicit FixedScaleSource(const ImageSkiaRep& image) : image_(image) {} | |
46 | |
47 ~FixedScaleSource() override {} | |
48 | |
49 ImageSkiaRep GetImageForScale(float scale) override { | |
50 if (!image_.unscaled() && image_.scale() != scale) | |
51 return ImageSkiaRep(); | |
52 return image_; | |
53 } | |
54 | |
55 private: | |
56 ImageSkiaRep image_; | |
57 | |
58 DISALLOW_COPY_AND_ASSIGN(FixedScaleSource); | |
59 }; | |
60 | |
61 class DynamicSource : public ImageSkiaSource { | |
62 public: | |
63 explicit DynamicSource(const gfx::Size& size) | |
64 : size_(size), | |
65 last_requested_scale_(0.0f) {} | |
66 | |
67 ~DynamicSource() override {} | |
68 | |
69 ImageSkiaRep GetImageForScale(float scale) override { | |
70 last_requested_scale_ = scale; | |
71 return gfx::ImageSkiaRep(size_, scale); | |
72 } | |
73 | |
74 float GetLastRequestedScaleAndReset() { | |
75 float result = last_requested_scale_; | |
76 last_requested_scale_ = 0.0f; | |
77 return result; | |
78 } | |
79 | |
80 private: | |
81 gfx::Size size_; | |
82 float last_requested_scale_; | |
83 | |
84 DISALLOW_COPY_AND_ASSIGN(DynamicSource); | |
85 }; | |
86 | |
87 class NullSource: public ImageSkiaSource { | |
88 public: | |
89 NullSource() { | |
90 } | |
91 | |
92 ~NullSource() override {} | |
93 | |
94 ImageSkiaRep GetImageForScale(float scale) override { | |
95 return gfx::ImageSkiaRep(); | |
96 } | |
97 | |
98 private: | |
99 DISALLOW_COPY_AND_ASSIGN(NullSource); | |
100 }; | |
101 | |
102 } // namespace | |
103 | |
104 namespace test { | |
105 class TestOnThread : public base::SimpleThread { | |
106 public: | |
107 explicit TestOnThread(ImageSkia* image_skia) | |
108 : SimpleThread("image_skia_on_thread"), | |
109 image_skia_(image_skia), | |
110 can_read_(false), | |
111 can_modify_(false) { | |
112 } | |
113 | |
114 void Run() override { | |
115 can_read_ = image_skia_->CanRead(); | |
116 can_modify_ = image_skia_->CanModify(); | |
117 if (can_read_) | |
118 image_skia_->image_reps(); | |
119 } | |
120 | |
121 void StartAndJoin() { | |
122 Start(); | |
123 Join(); | |
124 } | |
125 | |
126 bool can_read() const { return can_read_; } | |
127 | |
128 bool can_modify() const { return can_modify_; } | |
129 | |
130 private: | |
131 ImageSkia* image_skia_; | |
132 | |
133 bool can_read_; | |
134 bool can_modify_; | |
135 | |
136 DISALLOW_COPY_AND_ASSIGN(TestOnThread); | |
137 }; | |
138 | |
139 } // namespace test | |
140 | |
141 class ImageSkiaTest : public testing::Test { | |
142 public: | |
143 ImageSkiaTest() { | |
144 // In the test, we assume that we support 1.0f and 2.0f DSFs. | |
145 old_scales_ = ImageSkia::GetSupportedScales(); | |
146 | |
147 // Sets the list of scale factors supported by resource bundle. | |
148 std::vector<float> supported_scales; | |
149 supported_scales.push_back(1.0f); | |
150 supported_scales.push_back(2.0f); | |
151 ImageSkia::SetSupportedScales(supported_scales); | |
152 } | |
153 virtual ~ImageSkiaTest() { | |
154 ImageSkia::SetSupportedScales(old_scales_); | |
155 } | |
156 | |
157 private: | |
158 std::vector<float> old_scales_; | |
159 DISALLOW_COPY_AND_ASSIGN(ImageSkiaTest); | |
160 }; | |
161 | |
162 TEST_F(ImageSkiaTest, FixedSource) { | |
163 ImageSkiaRep image(Size(100, 200), 1.0f); | |
164 ImageSkia image_skia(new FixedSource(image), Size(100, 200)); | |
165 EXPECT_EQ(0U, image_skia.image_reps().size()); | |
166 | |
167 const ImageSkiaRep& result_100p = image_skia.GetRepresentation(1.0f); | |
168 EXPECT_EQ(100, result_100p.GetWidth()); | |
169 EXPECT_EQ(200, result_100p.GetHeight()); | |
170 EXPECT_EQ(1.0f, result_100p.scale()); | |
171 EXPECT_EQ(1U, image_skia.image_reps().size()); | |
172 | |
173 const ImageSkiaRep& result_200p = image_skia.GetRepresentation(2.0f); | |
174 | |
175 EXPECT_EQ(100, result_200p.GetWidth()); | |
176 EXPECT_EQ(200, result_200p.GetHeight()); | |
177 EXPECT_EQ(100, result_200p.pixel_width()); | |
178 EXPECT_EQ(200, result_200p.pixel_height()); | |
179 EXPECT_EQ(1.0f, result_200p.scale()); | |
180 EXPECT_EQ(1U, image_skia.image_reps().size()); | |
181 | |
182 // Get the representation again and make sure it doesn't | |
183 // generate new image skia rep. | |
184 image_skia.GetRepresentation(1.0f); | |
185 image_skia.GetRepresentation(2.0f); | |
186 EXPECT_EQ(1U, image_skia.image_reps().size()); | |
187 } | |
188 | |
189 TEST_F(ImageSkiaTest, FixedScaledSource) { | |
190 ImageSkiaRep image(Size(100, 200), 1.0f); | |
191 ImageSkia image_skia(new FixedScaleSource(image), Size(100, 200)); | |
192 EXPECT_EQ(0U, image_skia.image_reps().size()); | |
193 | |
194 const ImageSkiaRep& result_100p = image_skia.GetRepresentation(1.0f); | |
195 EXPECT_EQ(100, result_100p.GetWidth()); | |
196 EXPECT_EQ(200, result_100p.GetHeight()); | |
197 EXPECT_EQ(1.0f, result_100p.scale()); | |
198 EXPECT_EQ(1U, image_skia.image_reps().size()); | |
199 | |
200 // 2.0f data doesn't exist, then it falls back to 1.0f and rescale it. | |
201 const ImageSkiaRep& result_200p = image_skia.GetRepresentation(2.0f); | |
202 | |
203 EXPECT_EQ(100, result_200p.GetWidth()); | |
204 EXPECT_EQ(200, result_200p.GetHeight()); | |
205 EXPECT_EQ(200, result_200p.pixel_width()); | |
206 EXPECT_EQ(400, result_200p.pixel_height()); | |
207 EXPECT_EQ(2.0f, result_200p.scale()); | |
208 EXPECT_EQ(2U, image_skia.image_reps().size()); | |
209 | |
210 // Get the representation again and make sure it doesn't | |
211 // generate new image skia rep. | |
212 image_skia.GetRepresentation(1.0f); | |
213 image_skia.GetRepresentation(2.0f); | |
214 EXPECT_EQ(2U, image_skia.image_reps().size()); | |
215 } | |
216 | |
217 TEST_F(ImageSkiaTest, FixedUnscaledSource) { | |
218 ImageSkiaRep image(Size(100, 200), 0.0f); | |
219 ImageSkia image_skia(new FixedScaleSource(image), Size(100, 200)); | |
220 EXPECT_EQ(0U, image_skia.image_reps().size()); | |
221 | |
222 const ImageSkiaRep& result_100p = image_skia.GetRepresentation(1.0f); | |
223 EXPECT_EQ(100, result_100p.pixel_width()); | |
224 EXPECT_EQ(200, result_100p.pixel_height()); | |
225 EXPECT_TRUE(result_100p.unscaled()); | |
226 EXPECT_EQ(1U, image_skia.image_reps().size()); | |
227 | |
228 // 2.0f data doesn't exist, but unscaled ImageSkiaRep shouldn't be rescaled. | |
229 const ImageSkiaRep& result_200p = image_skia.GetRepresentation(2.0f); | |
230 | |
231 EXPECT_EQ(100, result_200p.pixel_width()); | |
232 EXPECT_EQ(200, result_200p.pixel_height()); | |
233 EXPECT_TRUE(result_200p.unscaled()); | |
234 EXPECT_EQ(1U, image_skia.image_reps().size()); | |
235 | |
236 // Get the representation again and make sure it doesn't | |
237 // generate new image skia rep. | |
238 image_skia.GetRepresentation(1.0f); | |
239 image_skia.GetRepresentation(2.0f); | |
240 EXPECT_EQ(1U, image_skia.image_reps().size()); | |
241 } | |
242 | |
243 TEST_F(ImageSkiaTest, DynamicSource) { | |
244 ImageSkia image_skia(new DynamicSource(Size(100, 200)), Size(100, 200)); | |
245 EXPECT_EQ(0U, image_skia.image_reps().size()); | |
246 const ImageSkiaRep& result_100p = image_skia.GetRepresentation(1.0f); | |
247 EXPECT_EQ(100, result_100p.GetWidth()); | |
248 EXPECT_EQ(200, result_100p.GetHeight()); | |
249 EXPECT_EQ(1.0f, result_100p.scale()); | |
250 EXPECT_EQ(1U, image_skia.image_reps().size()); | |
251 | |
252 const ImageSkiaRep& result_200p = | |
253 image_skia.GetRepresentation(2.0f); | |
254 EXPECT_EQ(100, result_200p.GetWidth()); | |
255 EXPECT_EQ(200, result_200p.GetHeight()); | |
256 EXPECT_EQ(200, result_200p.pixel_width()); | |
257 EXPECT_EQ(400, result_200p.pixel_height()); | |
258 EXPECT_EQ(2.0f, result_200p.scale()); | |
259 EXPECT_EQ(2U, image_skia.image_reps().size()); | |
260 | |
261 // Get the representation again and make sure it doesn't | |
262 // generate new image skia rep. | |
263 image_skia.GetRepresentation(1.0f); | |
264 EXPECT_EQ(2U, image_skia.image_reps().size()); | |
265 image_skia.GetRepresentation(2.0f); | |
266 EXPECT_EQ(2U, image_skia.image_reps().size()); | |
267 } | |
268 | |
269 // Tests that image_reps returns all of the representations in the | |
270 // image when there are multiple representations for a scale factor. | |
271 // This currently is the case with ImageLoader::LoadImages. | |
272 TEST_F(ImageSkiaTest, ManyRepsPerScaleFactor) { | |
273 const int kSmallIcon1x = 16; | |
274 const int kSmallIcon2x = 32; | |
275 const int kLargeIcon1x = 32; | |
276 | |
277 ImageSkia image(new NullSource(), gfx::Size(kSmallIcon1x, kSmallIcon1x)); | |
278 // Simulate a source which loads images on a delay. Upon | |
279 // GetImageForScaleFactor, it immediately returns null and starts loading | |
280 // image reps slowly. | |
281 image.GetRepresentation(1.0f); | |
282 image.GetRepresentation(2.0f); | |
283 | |
284 // After a lengthy amount of simulated time, finally loaded image reps. | |
285 image.AddRepresentation(ImageSkiaRep( | |
286 gfx::Size(kSmallIcon1x, kSmallIcon1x), 1.0f)); | |
287 image.AddRepresentation(ImageSkiaRep( | |
288 gfx::Size(kSmallIcon2x, kSmallIcon2x), 2.0f)); | |
289 image.AddRepresentation(ImageSkiaRep( | |
290 gfx::Size(kLargeIcon1x, kLargeIcon1x), 1.0f)); | |
291 | |
292 std::vector<ImageSkiaRep> image_reps = image.image_reps(); | |
293 EXPECT_EQ(3u, image_reps.size()); | |
294 | |
295 int num_1x = 0; | |
296 int num_2x = 0; | |
297 for (size_t i = 0; i < image_reps.size(); ++i) { | |
298 if (image_reps[i].scale() == 1.0f) | |
299 num_1x++; | |
300 else if (image_reps[i].scale() == 2.0f) | |
301 num_2x++; | |
302 } | |
303 EXPECT_EQ(2, num_1x); | |
304 EXPECT_EQ(1, num_2x); | |
305 } | |
306 | |
307 TEST_F(ImageSkiaTest, GetBitmap) { | |
308 ImageSkia image_skia(new DynamicSource(Size(100, 200)), Size(100, 200)); | |
309 const SkBitmap* bitmap = image_skia.bitmap(); | |
310 EXPECT_NE(static_cast<SkBitmap*>(NULL), bitmap); | |
311 EXPECT_FALSE(bitmap->isNull()); | |
312 } | |
313 | |
314 TEST_F(ImageSkiaTest, GetBitmapFromEmpty) { | |
315 // Create an image with 1 representation and remove it so the ImageSkiaStorage | |
316 // is left with no representations. | |
317 ImageSkia empty_image(ImageSkiaRep(Size(100, 200), 1.0f)); | |
318 ImageSkia empty_image_copy(empty_image); | |
319 empty_image.RemoveRepresentation(1.0f); | |
320 | |
321 // Check that ImageSkia::bitmap() still returns a valid SkBitmap pointer for | |
322 // the image and all its copies. | |
323 const SkBitmap* bitmap = empty_image_copy.bitmap(); | |
324 ASSERT_NE(static_cast<SkBitmap*>(NULL), bitmap); | |
325 EXPECT_TRUE(bitmap->isNull()); | |
326 EXPECT_TRUE(bitmap->empty()); | |
327 } | |
328 | |
329 TEST_F(ImageSkiaTest, BackedBySameObjectAs) { | |
330 // Null images should all be backed by the same object (NULL). | |
331 ImageSkia image; | |
332 ImageSkia unrelated; | |
333 EXPECT_TRUE(image.BackedBySameObjectAs(unrelated)); | |
334 | |
335 image.AddRepresentation(gfx::ImageSkiaRep(gfx::Size(10, 10), | |
336 1.0f)); | |
337 ImageSkia copy = image; | |
338 copy.AddRepresentation(gfx::ImageSkiaRep(gfx::Size(10, 10), | |
339 2.0f)); | |
340 unrelated.AddRepresentation(gfx::ImageSkiaRep(gfx::Size(10, 10), | |
341 1.0f)); | |
342 EXPECT_TRUE(image.BackedBySameObjectAs(copy)); | |
343 EXPECT_FALSE(image.BackedBySameObjectAs(unrelated)); | |
344 EXPECT_FALSE(copy.BackedBySameObjectAs(unrelated)); | |
345 } | |
346 | |
347 #if ENABLE_NON_THREAD_SAFE | |
348 TEST_F(ImageSkiaTest, EmptyOnThreadTest) { | |
349 ImageSkia empty; | |
350 test::TestOnThread empty_on_thread(&empty); | |
351 empty_on_thread.Start(); | |
352 empty_on_thread.Join(); | |
353 EXPECT_TRUE(empty_on_thread.can_read()); | |
354 EXPECT_TRUE(empty_on_thread.can_modify()); | |
355 } | |
356 | |
357 TEST_F(ImageSkiaTest, StaticOnThreadTest) { | |
358 ImageSkia image(ImageSkiaRep(Size(100, 200), 1.0f)); | |
359 EXPECT_FALSE(image.IsThreadSafe()); | |
360 | |
361 test::TestOnThread image_on_thread(&image); | |
362 // an image that was never accessed on this thread can be | |
363 // read by other thread. | |
364 image_on_thread.StartAndJoin(); | |
365 EXPECT_TRUE(image_on_thread.can_read()); | |
366 EXPECT_TRUE(image_on_thread.can_modify()); | |
367 EXPECT_FALSE(image.CanRead()); | |
368 EXPECT_FALSE(image.CanModify()); | |
369 | |
370 image.DetachStorageFromThread(); | |
371 // An image is accessed by this thread, | |
372 // so other thread cannot read/modify it. | |
373 image.image_reps(); | |
374 test::TestOnThread image_on_thread2(&image); | |
375 image_on_thread2.StartAndJoin(); | |
376 EXPECT_FALSE(image_on_thread2.can_read()); | |
377 EXPECT_FALSE(image_on_thread2.can_modify()); | |
378 EXPECT_TRUE(image.CanRead()); | |
379 EXPECT_TRUE(image.CanModify()); | |
380 | |
381 image.DetachStorageFromThread(); | |
382 scoped_ptr<ImageSkia> deep_copy(image.DeepCopy()); | |
383 EXPECT_FALSE(deep_copy->IsThreadSafe()); | |
384 test::TestOnThread deepcopy_on_thread(deep_copy.get()); | |
385 deepcopy_on_thread.StartAndJoin(); | |
386 EXPECT_TRUE(deepcopy_on_thread.can_read()); | |
387 EXPECT_TRUE(deepcopy_on_thread.can_modify()); | |
388 EXPECT_FALSE(deep_copy->CanRead()); | |
389 EXPECT_FALSE(deep_copy->CanModify()); | |
390 | |
391 scoped_ptr<ImageSkia> deep_copy2(image.DeepCopy()); | |
392 EXPECT_EQ(1U, deep_copy2->image_reps().size()); | |
393 // Access it from current thread so that it can't be | |
394 // accessed from another thread. | |
395 deep_copy2->image_reps(); | |
396 EXPECT_FALSE(deep_copy2->IsThreadSafe()); | |
397 test::TestOnThread deepcopy2_on_thread(deep_copy2.get()); | |
398 deepcopy2_on_thread.StartAndJoin(); | |
399 EXPECT_FALSE(deepcopy2_on_thread.can_read()); | |
400 EXPECT_FALSE(deepcopy2_on_thread.can_modify()); | |
401 EXPECT_TRUE(deep_copy2->CanRead()); | |
402 EXPECT_TRUE(deep_copy2->CanModify()); | |
403 | |
404 image.DetachStorageFromThread(); | |
405 image.SetReadOnly(); | |
406 // A read-only ImageSkia with no source is thread safe. | |
407 EXPECT_TRUE(image.IsThreadSafe()); | |
408 test::TestOnThread readonly_on_thread(&image); | |
409 readonly_on_thread.StartAndJoin(); | |
410 EXPECT_TRUE(readonly_on_thread.can_read()); | |
411 EXPECT_FALSE(readonly_on_thread.can_modify()); | |
412 EXPECT_TRUE(image.CanRead()); | |
413 EXPECT_FALSE(image.CanModify()); | |
414 | |
415 image.DetachStorageFromThread(); | |
416 image.MakeThreadSafe(); | |
417 EXPECT_TRUE(image.IsThreadSafe()); | |
418 test::TestOnThread threadsafe_on_thread(&image); | |
419 threadsafe_on_thread.StartAndJoin(); | |
420 EXPECT_TRUE(threadsafe_on_thread.can_read()); | |
421 EXPECT_FALSE(threadsafe_on_thread.can_modify()); | |
422 EXPECT_TRUE(image.CanRead()); | |
423 EXPECT_FALSE(image.CanModify()); | |
424 } | |
425 | |
426 TEST_F(ImageSkiaTest, SourceOnThreadTest) { | |
427 ImageSkia image(new DynamicSource(Size(100, 200)), Size(100, 200)); | |
428 EXPECT_FALSE(image.IsThreadSafe()); | |
429 | |
430 test::TestOnThread image_on_thread(&image); | |
431 image_on_thread.StartAndJoin(); | |
432 // an image that was never accessed on this thread can be | |
433 // read by other thread. | |
434 EXPECT_TRUE(image_on_thread.can_read()); | |
435 EXPECT_TRUE(image_on_thread.can_modify()); | |
436 EXPECT_FALSE(image.CanRead()); | |
437 EXPECT_FALSE(image.CanModify()); | |
438 | |
439 image.DetachStorageFromThread(); | |
440 // An image is accessed by this thread, | |
441 // so other thread cannot read/modify it. | |
442 image.image_reps(); | |
443 test::TestOnThread image_on_thread2(&image); | |
444 image_on_thread2.StartAndJoin(); | |
445 EXPECT_FALSE(image_on_thread2.can_read()); | |
446 EXPECT_FALSE(image_on_thread2.can_modify()); | |
447 EXPECT_TRUE(image.CanRead()); | |
448 EXPECT_TRUE(image.CanModify()); | |
449 | |
450 image.DetachStorageFromThread(); | |
451 image.SetReadOnly(); | |
452 EXPECT_FALSE(image.IsThreadSafe()); | |
453 test::TestOnThread readonly_on_thread(&image); | |
454 readonly_on_thread.StartAndJoin(); | |
455 EXPECT_TRUE(readonly_on_thread.can_read()); | |
456 EXPECT_FALSE(readonly_on_thread.can_modify()); | |
457 EXPECT_FALSE(image.CanRead()); | |
458 EXPECT_FALSE(image.CanModify()); | |
459 | |
460 image.DetachStorageFromThread(); | |
461 image.MakeThreadSafe(); | |
462 EXPECT_TRUE(image.IsThreadSafe()); | |
463 // Check if image reps are generated for supported scale factors. | |
464 EXPECT_EQ(ImageSkia::GetSupportedScales().size(), | |
465 image.image_reps().size()); | |
466 test::TestOnThread threadsafe_on_thread(&image); | |
467 threadsafe_on_thread.StartAndJoin(); | |
468 EXPECT_TRUE(threadsafe_on_thread.can_read()); | |
469 EXPECT_FALSE(threadsafe_on_thread.can_modify()); | |
470 EXPECT_TRUE(image.CanRead()); | |
471 EXPECT_FALSE(image.CanModify()); | |
472 } | |
473 #endif // ENABLE_NON_THREAD_SAFE | |
474 | |
475 // Just in case we ever get lumped together with other compilation units. | |
476 #undef ENABLE_NON_THREAD_SAFE | |
477 | |
478 TEST_F(ImageSkiaTest, Unscaled) { | |
479 SkBitmap bitmap; | |
480 | |
481 // An ImageSkia created with 1x bitmap is unscaled. | |
482 ImageSkia image_skia = ImageSkia::CreateFrom1xBitmap(bitmap); | |
483 EXPECT_TRUE(image_skia.GetRepresentation(1.0f).unscaled()); | |
484 ImageSkiaRep rep_2x(Size(100, 100), 2.0f); | |
485 | |
486 // When reps for other scales are added, the unscaled image | |
487 // becomes scaled. | |
488 image_skia.AddRepresentation(rep_2x); | |
489 EXPECT_FALSE(image_skia.GetRepresentation(1.0f).unscaled()); | |
490 EXPECT_FALSE(image_skia.GetRepresentation(2.0f).unscaled()); | |
491 } | |
492 | |
493 namespace { | |
494 | |
495 std::vector<float> GetSortedScaleFactors(const gfx::ImageSkia& image) { | |
496 const std::vector<ImageSkiaRep>& image_reps = image.image_reps(); | |
497 std::vector<float> scale_factors; | |
498 for (size_t i = 0; i < image_reps.size(); ++i) { | |
499 scale_factors.push_back(image_reps[i].scale()); | |
500 } | |
501 std::sort(scale_factors.begin(), scale_factors.end()); | |
502 return scale_factors; | |
503 } | |
504 | |
505 } // namespace | |
506 | |
507 TEST_F(ImageSkiaTest, ArbitraryScaleFactor) { | |
508 // source is owned by |image| | |
509 DynamicSource* source = new DynamicSource(Size(100, 200)); | |
510 ImageSkia image(source, gfx::Size(100, 200)); | |
511 | |
512 image.GetRepresentation(1.5f); | |
513 EXPECT_EQ(2.0f, source->GetLastRequestedScaleAndReset()); | |
514 std::vector<ImageSkiaRep> image_reps = image.image_reps(); | |
515 EXPECT_EQ(2u, image_reps.size()); | |
516 | |
517 std::vector<float> scale_factors = GetSortedScaleFactors(image); | |
518 EXPECT_EQ(1.5f, scale_factors[0]); | |
519 EXPECT_EQ(2.0f, scale_factors[1]); | |
520 | |
521 // Requesting 1.75 scale factor also falls back to 2.0f and rescale. | |
522 // However, the image already has the 2.0f data, so it won't fetch again. | |
523 image.GetRepresentation(1.75f); | |
524 EXPECT_EQ(0.0f, source->GetLastRequestedScaleAndReset()); | |
525 image_reps = image.image_reps(); | |
526 EXPECT_EQ(3u, image_reps.size()); | |
527 | |
528 scale_factors = GetSortedScaleFactors(image); | |
529 EXPECT_EQ(1.5f, scale_factors[0]); | |
530 EXPECT_EQ(1.75f, scale_factors[1]); | |
531 EXPECT_EQ(2.0f, scale_factors[2]); | |
532 | |
533 // Requesting 1.25 scale factor also falls back to 2.0f and rescale. | |
534 // However, the image already has the 2.0f data, so it won't fetch again. | |
535 image.GetRepresentation(1.25f); | |
536 EXPECT_EQ(0.0f, source->GetLastRequestedScaleAndReset()); | |
537 image_reps = image.image_reps(); | |
538 EXPECT_EQ(4u, image_reps.size()); | |
539 scale_factors = GetSortedScaleFactors(image); | |
540 EXPECT_EQ(1.25f, scale_factors[0]); | |
541 EXPECT_EQ(1.5f, scale_factors[1]); | |
542 EXPECT_EQ(1.75f, scale_factors[2]); | |
543 EXPECT_EQ(2.0f, scale_factors[3]); | |
544 | |
545 // 1.20 is falled back to 1.0. | |
546 image.GetRepresentation(1.20f); | |
547 EXPECT_EQ(1.0f, source->GetLastRequestedScaleAndReset()); | |
548 image_reps = image.image_reps(); | |
549 EXPECT_EQ(6u, image_reps.size()); | |
550 scale_factors = GetSortedScaleFactors(image); | |
551 EXPECT_EQ(1.0f, scale_factors[0]); | |
552 EXPECT_EQ(1.2f, scale_factors[1]); | |
553 EXPECT_EQ(1.25f, scale_factors[2]); | |
554 EXPECT_EQ(1.5f, scale_factors[3]); | |
555 EXPECT_EQ(1.75f, scale_factors[4]); | |
556 EXPECT_EQ(2.0f, scale_factors[5]); | |
557 | |
558 // Scale factor less than 1.0f will be falled back to 1.0f | |
559 image.GetRepresentation(0.75f); | |
560 EXPECT_EQ(0.0f, source->GetLastRequestedScaleAndReset()); | |
561 image_reps = image.image_reps(); | |
562 EXPECT_EQ(7u, image_reps.size()); | |
563 | |
564 scale_factors = GetSortedScaleFactors(image); | |
565 EXPECT_EQ(0.75f, scale_factors[0]); | |
566 EXPECT_EQ(1.0f, scale_factors[1]); | |
567 EXPECT_EQ(1.2f, scale_factors[2]); | |
568 EXPECT_EQ(1.25f, scale_factors[3]); | |
569 EXPECT_EQ(1.5f, scale_factors[4]); | |
570 EXPECT_EQ(1.75f, scale_factors[5]); | |
571 EXPECT_EQ(2.0f, scale_factors[6]); | |
572 | |
573 // Scale factor greater than 2.0f is falled back to 2.0f because it's not | |
574 // supported. | |
575 image.GetRepresentation(3.0f); | |
576 EXPECT_EQ(0.0f, source->GetLastRequestedScaleAndReset()); | |
577 image_reps = image.image_reps(); | |
578 EXPECT_EQ(8u, image_reps.size()); | |
579 } | |
580 | |
581 TEST_F(ImageSkiaTest, ArbitraryScaleFactorWithMissingResource) { | |
582 ImageSkia image(new FixedScaleSource( | |
583 ImageSkiaRep(Size(100, 200), 1.0f)), Size(100, 200)); | |
584 | |
585 // Requesting 1.5f -- falls back to 2.0f, but couldn't find. It should | |
586 // look up 1.0f and then rescale it. Note that the rescaled ImageSkiaRep will | |
587 // have 2.0f scale. | |
588 const ImageSkiaRep& rep = image.GetRepresentation(1.5f); | |
589 EXPECT_EQ(1.5f, rep.scale()); | |
590 EXPECT_EQ(2U, image.image_reps().size()); | |
591 EXPECT_EQ(2.0f, image.image_reps()[0].scale()); | |
592 EXPECT_EQ(1.5f, image.image_reps()[1].scale()); | |
593 } | |
594 | |
595 TEST_F(ImageSkiaTest, UnscaledImageForArbitraryScaleFactor) { | |
596 // 0.0f means unscaled. | |
597 ImageSkia image(new FixedScaleSource( | |
598 ImageSkiaRep(Size(100, 200), 0.0f)), Size(100, 200)); | |
599 | |
600 // Requesting 2.0f, which should return 1.0f unscaled image. | |
601 const ImageSkiaRep& rep = image.GetRepresentation(2.0f); | |
602 EXPECT_EQ(1.0f, rep.scale()); | |
603 EXPECT_EQ("100x200", rep.pixel_size().ToString()); | |
604 EXPECT_TRUE(rep.unscaled()); | |
605 EXPECT_EQ(1U, image.image_reps().size()); | |
606 | |
607 // Same for any other scale factors. | |
608 const ImageSkiaRep& rep15 = image.GetRepresentation(1.5f); | |
609 EXPECT_EQ(1.0f, rep15.scale()); | |
610 EXPECT_EQ("100x200", rep15.pixel_size().ToString()); | |
611 EXPECT_TRUE(rep15.unscaled()); | |
612 EXPECT_EQ(1U, image.image_reps().size()); | |
613 | |
614 const ImageSkiaRep& rep12 = image.GetRepresentation(1.2f); | |
615 EXPECT_EQ(1.0f, rep12.scale()); | |
616 EXPECT_EQ("100x200", rep12.pixel_size().ToString()); | |
617 EXPECT_TRUE(rep12.unscaled()); | |
618 EXPECT_EQ(1U, image.image_reps().size()); | |
619 } | |
620 | |
621 } // namespace gfx | |
OLD | NEW |