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