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/base/resource/resource_bundle.h" | |
6 | |
7 #include "base/base_paths.h" | |
8 #include "base/big_endian.h" | |
9 #include "base/files/file_path.h" | |
10 #include "base/files/file_util.h" | |
11 #include "base/files/scoped_temp_dir.h" | |
12 #include "base/logging.h" | |
13 #include "base/memory/ref_counted_memory.h" | |
14 #include "base/path_service.h" | |
15 #include "base/strings/utf_string_conversions.h" | |
16 #include "testing/gmock/include/gmock/gmock.h" | |
17 #include "testing/gtest/include/gtest/gtest.h" | |
18 #include "third_party/skia/include/core/SkBitmap.h" | |
19 #include "ui/base/layout.h" | |
20 #include "ui/base/resource/data_pack.h" | |
21 #include "ui/gfx/codec/png_codec.h" | |
22 #include "ui/gfx/image/image_skia.h" | |
23 #include "ui/resources/grit/ui_resources.h" | |
24 | |
25 #if defined(OS_WIN) | |
26 #include "ui/gfx/win/dpi.h" | |
27 #endif | |
28 | |
29 using ::testing::_; | |
30 using ::testing::Between; | |
31 using ::testing::Property; | |
32 using ::testing::Return; | |
33 using ::testing::ReturnArg; | |
34 | |
35 namespace ui { | |
36 | |
37 extern const char kSamplePakContents[]; | |
38 extern const size_t kSamplePakSize; | |
39 extern const char kSamplePakContents2x[]; | |
40 extern const size_t kSamplePakSize2x; | |
41 extern const char kEmptyPakContents[]; | |
42 extern const size_t kEmptyPakSize; | |
43 | |
44 namespace { | |
45 | |
46 const unsigned char kPngMagic[8] = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 }; | |
47 const size_t kPngChunkMetadataSize = 12; | |
48 const unsigned char kPngIHDRChunkType[4] = { 'I', 'H', 'D', 'R' }; | |
49 | |
50 // Custom chunk that GRIT adds to PNG to indicate that it could not find a | |
51 // bitmap at the requested scale factor and fell back to 1x. | |
52 const unsigned char kPngScaleChunk[12] = { 0x00, 0x00, 0x00, 0x00, | |
53 'c', 's', 'C', 'l', | |
54 0xc1, 0x30, 0x60, 0x4d }; | |
55 | |
56 // Mock for the ResourceBundle::Delegate class. | |
57 class MockResourceBundleDelegate : public ui::ResourceBundle::Delegate { | |
58 public: | |
59 MockResourceBundleDelegate() { | |
60 } | |
61 virtual ~MockResourceBundleDelegate() { | |
62 } | |
63 | |
64 MOCK_METHOD2(GetPathForResourcePack, base::FilePath( | |
65 const base::FilePath& pack_path, ui::ScaleFactor scale_factor)); | |
66 MOCK_METHOD2(GetPathForLocalePack, base::FilePath( | |
67 const base::FilePath& pack_path, const std::string& locale)); | |
68 MOCK_METHOD1(GetImageNamed, gfx::Image(int resource_id)); | |
69 MOCK_METHOD2(GetNativeImageNamed, | |
70 gfx::Image(int resource_id, | |
71 ui::ResourceBundle::ImageRTL rtl)); | |
72 MOCK_METHOD2(LoadDataResourceBytes, | |
73 base::RefCountedStaticMemory*(int resource_id, | |
74 ui::ScaleFactor scale_factor)); | |
75 MOCK_METHOD2(GetRawDataResourceMock, base::StringPiece( | |
76 int resource_id, | |
77 ui::ScaleFactor scale_factor)); | |
78 virtual bool GetRawDataResource(int resource_id, | |
79 ui::ScaleFactor scale_factor, | |
80 base::StringPiece* value) override { | |
81 *value = GetRawDataResourceMock(resource_id, scale_factor); | |
82 return true; | |
83 } | |
84 MOCK_METHOD1(GetLocalizedStringMock, base::string16(int message_id)); | |
85 virtual bool GetLocalizedString(int message_id, | |
86 base::string16* value) override { | |
87 *value = GetLocalizedStringMock(message_id); | |
88 return true; | |
89 } | |
90 MOCK_METHOD1(GetFontMock, | |
91 gfx::Font*(ui::ResourceBundle::FontStyle style)); | |
92 virtual scoped_ptr<gfx::Font> GetFont( | |
93 ui::ResourceBundle::FontStyle style) override { | |
94 return scoped_ptr<gfx::Font>(GetFontMock(style)); | |
95 } | |
96 }; | |
97 | |
98 // Returns |bitmap_data| with |custom_chunk| inserted after the IHDR chunk. | |
99 void AddCustomChunk(const base::StringPiece& custom_chunk, | |
100 std::vector<unsigned char>* bitmap_data) { | |
101 EXPECT_LT(arraysize(kPngMagic) + kPngChunkMetadataSize, bitmap_data->size()); | |
102 EXPECT_TRUE(std::equal( | |
103 bitmap_data->begin(), | |
104 bitmap_data->begin() + arraysize(kPngMagic), | |
105 kPngMagic)); | |
106 std::vector<unsigned char>::iterator ihdr_start = | |
107 bitmap_data->begin() + arraysize(kPngMagic); | |
108 char ihdr_length_data[sizeof(uint32)]; | |
109 for (size_t i = 0; i < sizeof(uint32); ++i) | |
110 ihdr_length_data[i] = *(ihdr_start + i); | |
111 uint32 ihdr_chunk_length = 0; | |
112 base::ReadBigEndian(reinterpret_cast<char*>(ihdr_length_data), | |
113 &ihdr_chunk_length); | |
114 EXPECT_TRUE(std::equal( | |
115 ihdr_start + sizeof(uint32), | |
116 ihdr_start + sizeof(uint32) + sizeof(kPngIHDRChunkType), | |
117 kPngIHDRChunkType)); | |
118 | |
119 bitmap_data->insert(ihdr_start + kPngChunkMetadataSize + ihdr_chunk_length, | |
120 custom_chunk.begin(), custom_chunk.end()); | |
121 } | |
122 | |
123 // Creates datapack at |path| with a single bitmap at resource ID 3 | |
124 // which is |edge_size|x|edge_size| pixels. | |
125 // If |custom_chunk| is non empty, adds it after the IHDR chunk | |
126 // in the encoded bitmap data. | |
127 void CreateDataPackWithSingleBitmap(const base::FilePath& path, | |
128 int edge_size, | |
129 const base::StringPiece& custom_chunk) { | |
130 SkBitmap bitmap; | |
131 bitmap.allocN32Pixels(edge_size, edge_size); | |
132 bitmap.eraseColor(SK_ColorWHITE); | |
133 std::vector<unsigned char> bitmap_data; | |
134 EXPECT_TRUE(gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bitmap_data)); | |
135 | |
136 if (custom_chunk.size() > 0) | |
137 AddCustomChunk(custom_chunk, &bitmap_data); | |
138 | |
139 std::map<uint16, base::StringPiece> resources; | |
140 resources[3u] = base::StringPiece( | |
141 reinterpret_cast<const char*>(&bitmap_data[0]), bitmap_data.size()); | |
142 DataPack::WritePack(path, resources, ui::DataPack::BINARY); | |
143 } | |
144 | |
145 } // namespace | |
146 | |
147 class ResourceBundleTest : public testing::Test { | |
148 public: | |
149 ResourceBundleTest() : resource_bundle_(NULL) { | |
150 } | |
151 | |
152 virtual ~ResourceBundleTest() { | |
153 } | |
154 | |
155 // Overridden from testing::Test: | |
156 virtual void TearDown() override { | |
157 delete resource_bundle_; | |
158 } | |
159 | |
160 // Returns new ResoureBundle with the specified |delegate|. The | |
161 // ResourceBundleTest class manages the lifetime of the returned | |
162 // ResourceBundle. | |
163 ResourceBundle* CreateResourceBundle(ResourceBundle::Delegate* delegate) { | |
164 DCHECK(!resource_bundle_); | |
165 | |
166 resource_bundle_ = new ResourceBundle(delegate); | |
167 return resource_bundle_; | |
168 } | |
169 | |
170 protected: | |
171 ResourceBundle* resource_bundle_; | |
172 | |
173 private: | |
174 DISALLOW_COPY_AND_ASSIGN(ResourceBundleTest); | |
175 }; | |
176 | |
177 TEST_F(ResourceBundleTest, DelegateGetPathForResourcePack) { | |
178 MockResourceBundleDelegate delegate; | |
179 ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); | |
180 | |
181 base::FilePath pack_path(FILE_PATH_LITERAL("/path/to/test_path.pak")); | |
182 ui::ScaleFactor pack_scale_factor = ui::SCALE_FACTOR_200P; | |
183 | |
184 EXPECT_CALL(delegate, | |
185 GetPathForResourcePack( | |
186 Property(&base::FilePath::value, pack_path.value()), | |
187 pack_scale_factor)) | |
188 .Times(1) | |
189 .WillOnce(Return(pack_path)); | |
190 | |
191 resource_bundle->AddDataPackFromPath(pack_path, pack_scale_factor); | |
192 } | |
193 | |
194 #if defined(OS_LINUX) | |
195 // Fails consistently on Linux: crbug.com/161902 | |
196 #define MAYBE_DelegateGetPathForLocalePack DISABLED_DelegateGetPathForLocalePack | |
197 #else | |
198 #define MAYBE_DelegateGetPathForLocalePack DelegateGetPathForLocalePack | |
199 #endif | |
200 TEST_F(ResourceBundleTest, MAYBE_DelegateGetPathForLocalePack) { | |
201 MockResourceBundleDelegate delegate; | |
202 ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); | |
203 | |
204 std::string locale = "en-US"; | |
205 | |
206 // Cancel the load. | |
207 EXPECT_CALL(delegate, GetPathForLocalePack(_, locale)) | |
208 .Times(2) | |
209 .WillRepeatedly(Return(base::FilePath())) | |
210 .RetiresOnSaturation(); | |
211 | |
212 EXPECT_FALSE(resource_bundle->LocaleDataPakExists(locale)); | |
213 EXPECT_EQ("", resource_bundle->LoadLocaleResources(locale)); | |
214 | |
215 // Allow the load to proceed. | |
216 EXPECT_CALL(delegate, GetPathForLocalePack(_, locale)) | |
217 .Times(2) | |
218 .WillRepeatedly(ReturnArg<0>()); | |
219 | |
220 EXPECT_TRUE(resource_bundle->LocaleDataPakExists(locale)); | |
221 EXPECT_EQ(locale, resource_bundle->LoadLocaleResources(locale)); | |
222 } | |
223 | |
224 TEST_F(ResourceBundleTest, DelegateGetImageNamed) { | |
225 MockResourceBundleDelegate delegate; | |
226 ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); | |
227 | |
228 gfx::Image empty_image = resource_bundle->GetEmptyImage(); | |
229 int resource_id = 5; | |
230 | |
231 EXPECT_CALL(delegate, GetImageNamed(resource_id)) | |
232 .Times(1) | |
233 .WillOnce(Return(empty_image)); | |
234 | |
235 gfx::Image result = resource_bundle->GetImageNamed(resource_id); | |
236 EXPECT_EQ(empty_image.ToSkBitmap(), result.ToSkBitmap()); | |
237 } | |
238 | |
239 TEST_F(ResourceBundleTest, DelegateGetNativeImageNamed) { | |
240 MockResourceBundleDelegate delegate; | |
241 ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); | |
242 | |
243 gfx::Image empty_image = resource_bundle->GetEmptyImage(); | |
244 int resource_id = 5; | |
245 | |
246 // Some platforms delegate GetNativeImageNamed calls to GetImageNamed. | |
247 EXPECT_CALL(delegate, GetImageNamed(resource_id)) | |
248 .Times(Between(0, 1)) | |
249 .WillOnce(Return(empty_image)); | |
250 EXPECT_CALL(delegate, | |
251 GetNativeImageNamed(resource_id, ui::ResourceBundle::RTL_DISABLED)) | |
252 .Times(Between(0, 1)) | |
253 .WillOnce(Return(empty_image)); | |
254 | |
255 gfx::Image result = resource_bundle->GetNativeImageNamed(resource_id); | |
256 EXPECT_EQ(empty_image.ToSkBitmap(), result.ToSkBitmap()); | |
257 } | |
258 | |
259 TEST_F(ResourceBundleTest, DelegateLoadDataResourceBytes) { | |
260 MockResourceBundleDelegate delegate; | |
261 ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); | |
262 | |
263 // Create the data resource for testing purposes. | |
264 unsigned char data[] = "My test data"; | |
265 scoped_refptr<base::RefCountedStaticMemory> static_memory( | |
266 new base::RefCountedStaticMemory(data, sizeof(data))); | |
267 | |
268 int resource_id = 5; | |
269 ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_NONE; | |
270 | |
271 EXPECT_CALL(delegate, LoadDataResourceBytes(resource_id, scale_factor)) | |
272 .Times(1).WillOnce(Return(static_memory.get())); | |
273 | |
274 scoped_refptr<base::RefCountedStaticMemory> result = | |
275 resource_bundle->LoadDataResourceBytesForScale(resource_id, scale_factor); | |
276 EXPECT_EQ(static_memory, result); | |
277 } | |
278 | |
279 TEST_F(ResourceBundleTest, DelegateGetRawDataResource) { | |
280 MockResourceBundleDelegate delegate; | |
281 ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); | |
282 | |
283 // Create the string piece for testing purposes. | |
284 char data[] = "My test data"; | |
285 base::StringPiece string_piece(data); | |
286 | |
287 int resource_id = 5; | |
288 | |
289 EXPECT_CALL(delegate, GetRawDataResourceMock( | |
290 resource_id, ui::SCALE_FACTOR_NONE)) | |
291 .Times(1) | |
292 .WillOnce(Return(string_piece)); | |
293 | |
294 base::StringPiece result = resource_bundle->GetRawDataResource( | |
295 resource_id); | |
296 EXPECT_EQ(string_piece.data(), result.data()); | |
297 } | |
298 | |
299 TEST_F(ResourceBundleTest, DelegateGetLocalizedString) { | |
300 MockResourceBundleDelegate delegate; | |
301 ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); | |
302 | |
303 base::string16 data = base::ASCIIToUTF16("My test data"); | |
304 int resource_id = 5; | |
305 | |
306 EXPECT_CALL(delegate, GetLocalizedStringMock(resource_id)) | |
307 .Times(1) | |
308 .WillOnce(Return(data)); | |
309 | |
310 base::string16 result = resource_bundle->GetLocalizedString(resource_id); | |
311 EXPECT_EQ(data, result); | |
312 } | |
313 | |
314 TEST_F(ResourceBundleTest, OverrideStringResource) { | |
315 ResourceBundle* resource_bundle = CreateResourceBundle(NULL); | |
316 | |
317 base::string16 data = base::ASCIIToUTF16("My test data"); | |
318 int resource_id = 5; | |
319 | |
320 base::string16 result = resource_bundle->GetLocalizedString(resource_id); | |
321 EXPECT_EQ(base::string16(), result); | |
322 | |
323 resource_bundle->OverrideLocaleStringResource(resource_id, data); | |
324 | |
325 result = resource_bundle->GetLocalizedString(resource_id); | |
326 EXPECT_EQ(data, result); | |
327 } | |
328 | |
329 TEST_F(ResourceBundleTest, DelegateGetLocalizedStringWithOverride) { | |
330 MockResourceBundleDelegate delegate; | |
331 ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); | |
332 | |
333 base::string16 delegate_data = base::ASCIIToUTF16("My delegate data"); | |
334 int resource_id = 5; | |
335 | |
336 EXPECT_CALL(delegate, GetLocalizedStringMock(resource_id)).Times(1).WillOnce( | |
337 Return(delegate_data)); | |
338 | |
339 base::string16 override_data = base::ASCIIToUTF16("My override data"); | |
340 | |
341 base::string16 result = resource_bundle->GetLocalizedString(resource_id); | |
342 EXPECT_EQ(delegate_data, result); | |
343 } | |
344 | |
345 #if (defined(USE_OZONE) && !defined(USE_PANGO)) || defined(OS_ANDROID) | |
346 #define MAYBE_DelegateGetFontList DISABLED_DelegateGetFontList | |
347 #else | |
348 #define MAYBE_DelegateGetFontList DelegateGetFontList | |
349 #endif | |
350 | |
351 TEST_F(ResourceBundleTest, MAYBE_DelegateGetFontList) { | |
352 MockResourceBundleDelegate delegate; | |
353 ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); | |
354 | |
355 // Should be called once for each font type. When we return NULL the default | |
356 // font will be created. | |
357 gfx::Font* test_font = NULL; | |
358 EXPECT_CALL(delegate, GetFontMock(_)) | |
359 .Times(8) | |
360 .WillRepeatedly(Return(test_font)); | |
361 | |
362 const gfx::FontList* font_list = | |
363 &resource_bundle->GetFontList(ui::ResourceBundle::BaseFont); | |
364 EXPECT_TRUE(font_list); | |
365 | |
366 const gfx::Font* font = | |
367 &resource_bundle->GetFont(ui::ResourceBundle::BaseFont); | |
368 EXPECT_TRUE(font); | |
369 } | |
370 | |
371 TEST_F(ResourceBundleTest, LocaleDataPakExists) { | |
372 ResourceBundle* resource_bundle = CreateResourceBundle(NULL); | |
373 | |
374 // Check that ResourceBundle::LocaleDataPakExists returns the correct results. | |
375 EXPECT_TRUE(resource_bundle->LocaleDataPakExists("en-US")); | |
376 EXPECT_FALSE(resource_bundle->LocaleDataPakExists("not_a_real_locale")); | |
377 } | |
378 | |
379 class ResourceBundleImageTest : public ResourceBundleTest { | |
380 public: | |
381 ResourceBundleImageTest() {} | |
382 | |
383 virtual ~ResourceBundleImageTest() { | |
384 } | |
385 | |
386 virtual void SetUp() override { | |
387 // Create a temporary directory to write test resource bundles to. | |
388 ASSERT_TRUE(dir_.CreateUniqueTempDir()); | |
389 } | |
390 | |
391 // Returns resource bundle which uses an empty data pak for locale data. | |
392 ui::ResourceBundle* CreateResourceBundleWithEmptyLocalePak() { | |
393 // Write an empty data pak for locale data. | |
394 const base::FilePath& locale_path = dir_path().Append( | |
395 FILE_PATH_LITERAL("locale.pak")); | |
396 EXPECT_EQ(base::WriteFile(locale_path, kEmptyPakContents, kEmptyPakSize), | |
397 static_cast<int>(kEmptyPakSize)); | |
398 | |
399 ui::ResourceBundle* resource_bundle = CreateResourceBundle(NULL); | |
400 | |
401 // Load the empty locale data pak. | |
402 resource_bundle->LoadTestResources(base::FilePath(), locale_path); | |
403 return resource_bundle; | |
404 } | |
405 | |
406 // Returns the path of temporary directory to write test data packs into. | |
407 const base::FilePath& dir_path() { return dir_.path(); } | |
408 | |
409 private: | |
410 scoped_ptr<DataPack> locale_pack_; | |
411 base::ScopedTempDir dir_; | |
412 | |
413 DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageTest); | |
414 }; | |
415 | |
416 // Verify that we don't crash when trying to load a resource that is not found. | |
417 // In some cases, we fail to mmap resources.pak, but try to keep going anyway. | |
418 TEST_F(ResourceBundleImageTest, LoadDataResourceBytes) { | |
419 base::FilePath data_path = dir_path().Append(FILE_PATH_LITERAL("sample.pak")); | |
420 | |
421 // Dump contents into the pak files. | |
422 ASSERT_EQ(base::WriteFile(data_path, kEmptyPakContents, | |
423 kEmptyPakSize), static_cast<int>(kEmptyPakSize)); | |
424 | |
425 // Create a resource bundle from the file. | |
426 ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak(); | |
427 resource_bundle->AddDataPackFromPath(data_path, SCALE_FACTOR_100P); | |
428 | |
429 const int kUnfoundResourceId = 10000; | |
430 EXPECT_EQ(NULL, resource_bundle->LoadDataResourceBytes( | |
431 kUnfoundResourceId)); | |
432 | |
433 // Give a .pak file that doesn't exist so we will fail to load it. | |
434 resource_bundle->AddDataPackFromPath( | |
435 base::FilePath(FILE_PATH_LITERAL("non-existant-file.pak")), | |
436 ui::SCALE_FACTOR_NONE); | |
437 EXPECT_EQ(NULL, resource_bundle->LoadDataResourceBytes( | |
438 kUnfoundResourceId)); | |
439 } | |
440 | |
441 TEST_F(ResourceBundleImageTest, GetRawDataResource) { | |
442 base::FilePath data_path = dir_path().Append(FILE_PATH_LITERAL("sample.pak")); | |
443 base::FilePath data_2x_path = | |
444 dir_path().Append(FILE_PATH_LITERAL("sample_2x.pak")); | |
445 | |
446 // Dump contents into the pak files. | |
447 ASSERT_EQ(base::WriteFile(data_path, kSamplePakContents, | |
448 kSamplePakSize), static_cast<int>(kSamplePakSize)); | |
449 ASSERT_EQ(base::WriteFile(data_2x_path, kSamplePakContents2x, | |
450 kSamplePakSize2x), static_cast<int>(kSamplePakSize2x)); | |
451 | |
452 // Load the regular and 2x pak files. | |
453 ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak(); | |
454 resource_bundle->AddDataPackFromPath(data_path, SCALE_FACTOR_100P); | |
455 resource_bundle->AddDataPackFromPath(data_2x_path, SCALE_FACTOR_200P); | |
456 | |
457 // Resource ID 4 exists in both 1x and 2x paks, so we expect a different | |
458 // result when requesting the 2x scale. | |
459 EXPECT_EQ("this is id 4", resource_bundle->GetRawDataResourceForScale(4, | |
460 SCALE_FACTOR_100P)); | |
461 EXPECT_EQ("this is id 4 2x", resource_bundle->GetRawDataResourceForScale(4, | |
462 SCALE_FACTOR_200P)); | |
463 | |
464 // Resource ID 6 only exists in the 1x pak so we expect the same resource | |
465 // for both scale factor requests. | |
466 EXPECT_EQ("this is id 6", resource_bundle->GetRawDataResourceForScale(6, | |
467 SCALE_FACTOR_100P)); | |
468 EXPECT_EQ("this is id 6", resource_bundle->GetRawDataResourceForScale(6, | |
469 SCALE_FACTOR_200P)); | |
470 } | |
471 | |
472 // Test requesting image reps at various scale factors from the image returned | |
473 // via ResourceBundle::GetImageNamed(). | |
474 TEST_F(ResourceBundleImageTest, GetImageNamed) { | |
475 #if defined(OS_WIN) | |
476 gfx::ForceHighDPISupportForTesting(2.0); | |
477 #endif | |
478 std::vector<ScaleFactor> supported_factors; | |
479 supported_factors.push_back(SCALE_FACTOR_100P); | |
480 supported_factors.push_back(SCALE_FACTOR_200P); | |
481 test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors); | |
482 base::FilePath data_1x_path = dir_path().AppendASCII("sample_1x.pak"); | |
483 base::FilePath data_2x_path = dir_path().AppendASCII("sample_2x.pak"); | |
484 | |
485 // Create the pak files. | |
486 CreateDataPackWithSingleBitmap(data_1x_path, 10, base::StringPiece()); | |
487 CreateDataPackWithSingleBitmap(data_2x_path, 20, base::StringPiece()); | |
488 | |
489 // Load the regular and 2x pak files. | |
490 ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak(); | |
491 resource_bundle->AddDataPackFromPath(data_1x_path, SCALE_FACTOR_100P); | |
492 resource_bundle->AddDataPackFromPath(data_2x_path, SCALE_FACTOR_200P); | |
493 | |
494 EXPECT_EQ(SCALE_FACTOR_200P, resource_bundle->GetMaxScaleFactor()); | |
495 | |
496 gfx::ImageSkia* image_skia = resource_bundle->GetImageSkiaNamed(3); | |
497 | |
498 #if defined(OS_CHROMEOS) || defined(OS_WIN) | |
499 // ChromeOS/Windows load highest scale factor first. | |
500 EXPECT_EQ(ui::SCALE_FACTOR_200P, | |
501 GetSupportedScaleFactor(image_skia->image_reps()[0].scale())); | |
502 #else | |
503 EXPECT_EQ(ui::SCALE_FACTOR_100P, | |
504 GetSupportedScaleFactor(image_skia->image_reps()[0].scale())); | |
505 #endif | |
506 | |
507 // Resource ID 3 exists in both 1x and 2x paks. Image reps should be | |
508 // available for both scale factors in |image_skia|. | |
509 gfx::ImageSkiaRep image_rep = | |
510 image_skia->GetRepresentation( | |
511 GetScaleForScaleFactor(ui::SCALE_FACTOR_100P)); | |
512 EXPECT_EQ(ui::SCALE_FACTOR_100P, GetSupportedScaleFactor(image_rep.scale())); | |
513 image_rep = | |
514 image_skia->GetRepresentation( | |
515 GetScaleForScaleFactor(ui::SCALE_FACTOR_200P)); | |
516 EXPECT_EQ(ui::SCALE_FACTOR_200P, GetSupportedScaleFactor(image_rep.scale())); | |
517 | |
518 // The 1.4x pack was not loaded. Requesting the 1.4x resource should return | |
519 // either the 1x or the 2x resource. | |
520 image_rep = image_skia->GetRepresentation( | |
521 ui::GetScaleForScaleFactor(ui::SCALE_FACTOR_140P)); | |
522 ui::ScaleFactor scale_factor = GetSupportedScaleFactor(image_rep.scale()); | |
523 EXPECT_TRUE(scale_factor == ui::SCALE_FACTOR_100P || | |
524 scale_factor == ui::SCALE_FACTOR_200P); | |
525 | |
526 // ImageSkia scales image if the one for the requested scale factor is not | |
527 // available. | |
528 EXPECT_EQ(1.4f, image_skia->GetRepresentation(1.4f).scale()); | |
529 } | |
530 | |
531 // Test that GetImageNamed() behaves properly for images which GRIT has | |
532 // annotated as having fallen back to 1x. | |
533 TEST_F(ResourceBundleImageTest, GetImageNamedFallback1x) { | |
534 std::vector<ScaleFactor> supported_factors; | |
535 supported_factors.push_back(SCALE_FACTOR_100P); | |
536 supported_factors.push_back(SCALE_FACTOR_200P); | |
537 test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors); | |
538 base::FilePath data_path = dir_path().AppendASCII("sample.pak"); | |
539 base::FilePath data_2x_path = dir_path().AppendASCII("sample_2x.pak"); | |
540 | |
541 // Create the pak files. | |
542 CreateDataPackWithSingleBitmap(data_path, 10, base::StringPiece()); | |
543 // 2x data pack bitmap has custom chunk to indicate that the 2x bitmap is not | |
544 // available and that GRIT fell back to 1x. | |
545 CreateDataPackWithSingleBitmap(data_2x_path, 10, base::StringPiece( | |
546 reinterpret_cast<const char*>(kPngScaleChunk), | |
547 arraysize(kPngScaleChunk))); | |
548 | |
549 // Load the regular and 2x pak files. | |
550 ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak(); | |
551 resource_bundle->AddDataPackFromPath(data_path, SCALE_FACTOR_100P); | |
552 resource_bundle->AddDataPackFromPath(data_2x_path, SCALE_FACTOR_200P); | |
553 | |
554 gfx::ImageSkia* image_skia = resource_bundle->GetImageSkiaNamed(3); | |
555 | |
556 // The image rep for 2x should be available. It should be resized to the | |
557 // proper 2x size. | |
558 gfx::ImageSkiaRep image_rep = | |
559 image_skia->GetRepresentation(GetScaleForScaleFactor( | |
560 ui::SCALE_FACTOR_200P)); | |
561 EXPECT_EQ(ui::SCALE_FACTOR_200P, GetSupportedScaleFactor(image_rep.scale())); | |
562 EXPECT_EQ(20, image_rep.pixel_width()); | |
563 EXPECT_EQ(20, image_rep.pixel_height()); | |
564 } | |
565 | |
566 #if defined(OS_WIN) | |
567 // Tests GetImageNamed() behaves properly when the size of a scaled image | |
568 // requires rounding as a result of using a non-integer scale factor. | |
569 // Scale factors of 140 and 1805 are Windows specific. | |
570 TEST_F(ResourceBundleImageTest, GetImageNamedFallback1xRounding) { | |
571 std::vector<ScaleFactor> supported_factors; | |
572 supported_factors.push_back(SCALE_FACTOR_100P); | |
573 supported_factors.push_back(SCALE_FACTOR_140P); | |
574 supported_factors.push_back(SCALE_FACTOR_180P); | |
575 test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors); | |
576 | |
577 base::FilePath data_path = dir_path().AppendASCII("sample.pak"); | |
578 base::FilePath data_140P_path = dir_path().AppendASCII("sample_140P.pak"); | |
579 base::FilePath data_180P_path = dir_path().AppendASCII("sample_180P.pak"); | |
580 | |
581 CreateDataPackWithSingleBitmap(data_path, 8, base::StringPiece()); | |
582 // Mark 140% and 180% images as requiring 1x fallback. | |
583 CreateDataPackWithSingleBitmap(data_140P_path, 8, base::StringPiece( | |
584 reinterpret_cast<const char*>(kPngScaleChunk), | |
585 arraysize(kPngScaleChunk))); | |
586 CreateDataPackWithSingleBitmap(data_180P_path, 8, base::StringPiece( | |
587 reinterpret_cast<const char*>(kPngScaleChunk), | |
588 arraysize(kPngScaleChunk))); | |
589 | |
590 ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak(); | |
591 resource_bundle->AddDataPackFromPath(data_path, SCALE_FACTOR_100P); | |
592 resource_bundle->AddDataPackFromPath(data_140P_path, SCALE_FACTOR_140P); | |
593 resource_bundle->AddDataPackFromPath(data_180P_path, SCALE_FACTOR_180P); | |
594 | |
595 // Non-integer dimensions should be rounded up. | |
596 gfx::ImageSkia* image_skia = resource_bundle->GetImageSkiaNamed(3); | |
597 gfx::ImageSkiaRep image_rep = | |
598 image_skia->GetRepresentation( | |
599 GetScaleForScaleFactor(ui::SCALE_FACTOR_140P)); | |
600 EXPECT_EQ(12, image_rep.pixel_width()); | |
601 image_rep = image_skia->GetRepresentation( | |
602 GetScaleForScaleFactor(ui::SCALE_FACTOR_180P)); | |
603 EXPECT_EQ(15, image_rep.pixel_width()); | |
604 } | |
605 #endif | |
606 | |
607 #if defined(OS_IOS) | |
608 // Fails on devices that have non-100P scaling. See crbug.com/298406 | |
609 #define MAYBE_FallbackToNone DISABLED_FallbackToNone | |
610 #else | |
611 #define MAYBE_FallbackToNone FallbackToNone | |
612 #endif | |
613 TEST_F(ResourceBundleImageTest, MAYBE_FallbackToNone) { | |
614 base::FilePath data_default_path = dir_path().AppendASCII("sample.pak"); | |
615 | |
616 // Create the pak files. | |
617 CreateDataPackWithSingleBitmap(data_default_path, 10, base::StringPiece()); | |
618 | |
619 // Load the regular pak files only. | |
620 ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak(); | |
621 resource_bundle->AddDataPackFromPath(data_default_path, SCALE_FACTOR_NONE); | |
622 | |
623 gfx::ImageSkia* image_skia = resource_bundle->GetImageSkiaNamed(3); | |
624 EXPECT_EQ(1u, image_skia->image_reps().size()); | |
625 EXPECT_TRUE(image_skia->image_reps()[0].unscaled()); | |
626 EXPECT_EQ(ui::SCALE_FACTOR_100P, | |
627 GetSupportedScaleFactor(image_skia->image_reps()[0].scale())); | |
628 } | |
629 | |
630 } // namespace ui | |
OLD | NEW |