| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/base/resource/resource_bundle.h" | 5 #include "ui/base/resource/resource_bundle.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 #include "ui/gfx/safe_integer_conversions.h" | 33 #include "ui/gfx/safe_integer_conversions.h" |
| 34 #include "ui/gfx/screen.h" | 34 #include "ui/gfx/screen.h" |
| 35 #include "ui/gfx/size_conversions.h" | 35 #include "ui/gfx/size_conversions.h" |
| 36 #include "ui/gfx/skbitmap_operations.h" | 36 #include "ui/gfx/skbitmap_operations.h" |
| 37 | 37 |
| 38 #if defined(OS_CHROMEOS) | 38 #if defined(OS_CHROMEOS) |
| 39 #include "ui/base/l10n/l10n_util.h" | 39 #include "ui/base/l10n/l10n_util.h" |
| 40 #include "ui/gfx/platform_font_pango.h" | 40 #include "ui/gfx/platform_font_pango.h" |
| 41 #endif | 41 #endif |
| 42 | 42 |
| 43 #if defined(OS_WIN) |
| 44 #include "ui/gfx/win/dpi.h" |
| 45 #endif |
| 46 |
| 47 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 48 #include "base/mac/mac_util.h" |
| 49 #endif |
| 50 |
| 43 namespace ui { | 51 namespace ui { |
| 44 | 52 |
| 45 namespace { | 53 namespace { |
| 46 | 54 |
| 47 // Font sizes relative to base font. | 55 // Font sizes relative to base font. |
| 48 const int kSmallFontSizeDelta = -1; | 56 const int kSmallFontSizeDelta = -1; |
| 49 const int kMediumFontSizeDelta = 3; | 57 const int kMediumFontSizeDelta = 3; |
| 50 const int kLargeFontSizeDelta = 8; | 58 const int kLargeFontSizeDelta = 8; |
| 51 | 59 |
| 52 // PNG-related constants. | 60 // PNG-related constants. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 73 // scaled image is not exactly |scale_factor| * the size of the 1x resource. | 81 // scaled image is not exactly |scale_factor| * the size of the 1x resource. |
| 74 // When --highlight-missing-scaled-resources flag is specified, scaled 1x images | 82 // When --highlight-missing-scaled-resources flag is specified, scaled 1x images |
| 75 // are higlighted by blending them with red. | 83 // are higlighted by blending them with red. |
| 76 class ResourceBundle::ResourceBundleImageSource : public gfx::ImageSkiaSource { | 84 class ResourceBundle::ResourceBundleImageSource : public gfx::ImageSkiaSource { |
| 77 public: | 85 public: |
| 78 ResourceBundleImageSource(ResourceBundle* rb, int resource_id) | 86 ResourceBundleImageSource(ResourceBundle* rb, int resource_id) |
| 79 : rb_(rb), resource_id_(resource_id) {} | 87 : rb_(rb), resource_id_(resource_id) {} |
| 80 virtual ~ResourceBundleImageSource() {} | 88 virtual ~ResourceBundleImageSource() {} |
| 81 | 89 |
| 82 // gfx::ImageSkiaSource overrides: | 90 // gfx::ImageSkiaSource overrides: |
| 83 virtual gfx::ImageSkiaRep GetImageForScale( | 91 virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE { |
| 84 ui::ScaleFactor scale_factor) OVERRIDE { | |
| 85 SkBitmap image; | 92 SkBitmap image; |
| 86 bool fell_back_to_1x = false; | 93 bool fell_back_to_1x = false; |
| 94 ScaleFactor scale_factor = GetSupportedScaleFactor(scale); |
| 87 bool found = rb_->LoadBitmap(resource_id_, &scale_factor, | 95 bool found = rb_->LoadBitmap(resource_id_, &scale_factor, |
| 88 &image, &fell_back_to_1x); | 96 &image, &fell_back_to_1x); |
| 97 // Force to a supported scale. |
| 98 scale = ui::GetImageScale(scale_factor); |
| 89 if (!found) | 99 if (!found) |
| 90 return gfx::ImageSkiaRep(); | 100 return gfx::ImageSkiaRep(); |
| 91 | 101 |
| 92 if (fell_back_to_1x) { | 102 if (fell_back_to_1x) { |
| 93 // GRIT fell back to the 100% image, so rescale it to the correct size. | 103 // GRIT fell back to the 100% image, so rescale it to the correct size. |
| 94 float scale = GetScaleFactorScale(scale_factor); | |
| 95 image = skia::ImageOperations::Resize( | 104 image = skia::ImageOperations::Resize( |
| 96 image, | 105 image, |
| 97 skia::ImageOperations::RESIZE_LANCZOS3, | 106 skia::ImageOperations::RESIZE_LANCZOS3, |
| 98 gfx::ToCeiledInt(image.width() * scale), | 107 gfx::ToCeiledInt(image.width() * scale), |
| 99 gfx::ToCeiledInt(image.height() * scale)); | 108 gfx::ToCeiledInt(image.height() * scale)); |
| 100 // If --highlight-missing-scaled-resources is specified, log the resource | 109 // If --highlight-missing-scaled-resources is specified, log the resource |
| 101 // id and blend the created resource with red. | 110 // id and blend the created resource with red. |
| 102 if (ShouldHighlightMissingScaledResources()) { | 111 if (ShouldHighlightMissingScaledResources()) { |
| 103 LOG(ERROR) << "Missing " << scale << "x scaled resource. id=" | 112 LOG(ERROR) << "Missing " << scale << "x scaled resource. id=" |
| 104 << resource_id_; | 113 << resource_id_; |
| 105 | 114 |
| 106 SkBitmap mask; | 115 SkBitmap mask; |
| 107 mask.setConfig(SkBitmap::kARGB_8888_Config, | 116 mask.setConfig(SkBitmap::kARGB_8888_Config, |
| 108 image.width(), image.height()); | 117 image.width(), image.height()); |
| 109 mask.allocPixels(); | 118 mask.allocPixels(); |
| 110 mask.eraseColor(SK_ColorRED); | 119 mask.eraseColor(SK_ColorRED); |
| 111 image = SkBitmapOperations::CreateBlendedBitmap(image, mask, 0.2); | 120 image = SkBitmapOperations::CreateBlendedBitmap(image, mask, 0.2); |
| 112 } | 121 } |
| 113 } | 122 } |
| 114 | 123 |
| 115 return gfx::ImageSkiaRep(image, scale_factor); | 124 return gfx::ImageSkiaRep(image, scale); |
| 116 } | 125 } |
| 117 | 126 |
| 118 private: | 127 private: |
| 119 ResourceBundle* rb_; | 128 ResourceBundle* rb_; |
| 120 const int resource_id_; | 129 const int resource_id_; |
| 121 | 130 |
| 122 DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageSource); | 131 DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageSource); |
| 123 }; | 132 }; |
| 124 | 133 |
| 125 // static | 134 // static |
| 126 std::string ResourceBundle::InitSharedInstanceWithLocale( | 135 std::string ResourceBundle::InitSharedInstanceWithLocale( |
| 127 const std::string& pref_locale, Delegate* delegate) { | 136 const std::string& pref_locale, Delegate* delegate) { |
| 128 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; | 137 InitSharedInstance(delegate); |
| 129 g_shared_instance_ = new ResourceBundle(delegate); | |
| 130 | |
| 131 g_shared_instance_->LoadCommonResources(); | 138 g_shared_instance_->LoadCommonResources(); |
| 132 std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); | 139 std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); |
| 133 InitDefaultFont(); | 140 InitDefaultFont(); |
| 134 return result; | 141 return result; |
| 135 } | 142 } |
| 136 | 143 |
| 137 // static | 144 // static |
| 138 std::string ResourceBundle::InitSharedInstanceLocaleOnly( | 145 std::string ResourceBundle::InitSharedInstanceLocaleOnly( |
| 139 const std::string& pref_locale, Delegate* delegate) { | 146 const std::string& pref_locale, Delegate* delegate) { |
| 140 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; | 147 InitSharedInstance(delegate); |
| 141 g_shared_instance_ = new ResourceBundle(delegate); | |
| 142 | |
| 143 std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); | 148 std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); |
| 144 InitDefaultFont(); | 149 InitDefaultFont(); |
| 145 return result; | 150 return result; |
| 146 } | 151 } |
| 147 | 152 |
| 148 // static | 153 // static |
| 149 void ResourceBundle::InitSharedInstanceWithPakFile( | 154 void ResourceBundle::InitSharedInstanceWithPakFile( |
| 150 base::PlatformFile pak_file, bool should_load_common_resources) { | 155 base::PlatformFile pak_file, bool should_load_common_resources) { |
| 151 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; | 156 InitSharedInstance(NULL); |
| 152 g_shared_instance_ = new ResourceBundle(NULL); | |
| 153 | |
| 154 if (should_load_common_resources) | 157 if (should_load_common_resources) |
| 155 g_shared_instance_->LoadCommonResources(); | 158 g_shared_instance_->LoadCommonResources(); |
| 156 | 159 |
| 157 scoped_ptr<DataPack> data_pack( | 160 scoped_ptr<DataPack> data_pack( |
| 158 new DataPack(SCALE_FACTOR_100P)); | 161 new DataPack(SCALE_FACTOR_100P)); |
| 159 if (!data_pack->LoadFromFile(pak_file)) { | 162 if (!data_pack->LoadFromFile(pak_file)) { |
| 160 NOTREACHED() << "failed to load pak file"; | 163 NOTREACHED() << "failed to load pak file"; |
| 161 return; | 164 return; |
| 162 } | 165 } |
| 163 g_shared_instance_->locale_resources_data_.reset(data_pack.release()); | 166 g_shared_instance_->locale_resources_data_.reset(data_pack.release()); |
| 164 InitDefaultFont(); | 167 InitDefaultFont(); |
| 165 } | 168 } |
| 166 | 169 |
| 167 // static | 170 // static |
| 168 void ResourceBundle::InitSharedInstanceWithPakPath(const base::FilePath& path) { | 171 void ResourceBundle::InitSharedInstanceWithPakPath(const base::FilePath& path) { |
| 169 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; | 172 InitSharedInstance(NULL); |
| 170 g_shared_instance_ = new ResourceBundle(NULL); | |
| 171 | |
| 172 g_shared_instance_->LoadTestResources(path, path); | 173 g_shared_instance_->LoadTestResources(path, path); |
| 173 | 174 |
| 174 InitDefaultFont(); | 175 InitDefaultFont(); |
| 175 } | 176 } |
| 176 | 177 |
| 177 // static | 178 // static |
| 178 void ResourceBundle::CleanupSharedInstance() { | 179 void ResourceBundle::CleanupSharedInstance() { |
| 179 if (g_shared_instance_) { | 180 if (g_shared_instance_) { |
| 180 delete g_shared_instance_; | 181 delete g_shared_instance_; |
| 181 g_shared_instance_ = NULL; | 182 g_shared_instance_ = NULL; |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 } | 335 } |
| 335 | 336 |
| 336 gfx::Image image; | 337 gfx::Image image; |
| 337 if (delegate_) | 338 if (delegate_) |
| 338 image = delegate_->GetImageNamed(resource_id); | 339 image = delegate_->GetImageNamed(resource_id); |
| 339 | 340 |
| 340 if (image.IsEmpty()) { | 341 if (image.IsEmpty()) { |
| 341 DCHECK(!data_packs_.empty()) << | 342 DCHECK(!data_packs_.empty()) << |
| 342 "Missing call to SetResourcesDataDLL?"; | 343 "Missing call to SetResourcesDataDLL?"; |
| 343 | 344 |
| 345 #if defined(OS_CHROMEOS) |
| 346 ui::ScaleFactor scale_factor_to_load = GetMaxScaleFactor(); |
| 347 #else |
| 348 ui::ScaleFactor scale_factor_to_load = ui::SCALE_FACTOR_100P; |
| 349 #endif |
| 350 |
| 351 float scale = GetImageScale(scale_factor_to_load); |
| 344 // TODO(oshima): Consider reading the image size from png IHDR chunk and | 352 // TODO(oshima): Consider reading the image size from png IHDR chunk and |
| 345 // skip decoding here and remove #ifdef below. | 353 // skip decoding here and remove #ifdef below. |
| 346 // ResourceBundle::GetSharedInstance() is destroyed after the | 354 // ResourceBundle::GetSharedInstance() is destroyed after the |
| 347 // BrowserMainLoop has finished running. |image_skia| is guaranteed to be | 355 // BrowserMainLoop has finished running. |image_skia| is guaranteed to be |
| 348 // destroyed before the resource bundle is destroyed. | 356 // destroyed before the resource bundle is destroyed. |
| 349 #if defined(OS_CHROMEOS) | |
| 350 ui::ScaleFactor scale_factor_to_load = ui::GetMaxScaleFactor(); | |
| 351 #else | |
| 352 ui::ScaleFactor scale_factor_to_load = ui::SCALE_FACTOR_100P; | |
| 353 #endif | |
| 354 gfx::ImageSkia image_skia(new ResourceBundleImageSource(this, resource_id), | 357 gfx::ImageSkia image_skia(new ResourceBundleImageSource(this, resource_id), |
| 355 scale_factor_to_load); | 358 scale); |
| 356 if (image_skia.isNull()) { | 359 if (image_skia.isNull()) { |
| 357 LOG(WARNING) << "Unable to load image with id " << resource_id; | 360 LOG(WARNING) << "Unable to load image with id " << resource_id; |
| 358 NOTREACHED(); // Want to assert in debug mode. | 361 NOTREACHED(); // Want to assert in debug mode. |
| 359 // The load failed to retrieve the image; show a debugging red square. | 362 // The load failed to retrieve the image; show a debugging red square. |
| 360 return GetEmptyImage(); | 363 return GetEmptyImage(); |
| 361 } | 364 } |
| 362 image_skia.SetReadOnly(); | 365 image_skia.SetReadOnly(); |
| 363 image = gfx::Image(image_skia); | 366 image = gfx::Image(image_skia); |
| 364 } | 367 } |
| 365 | 368 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 const gfx::Font& ResourceBundle::GetFont(FontStyle style) { | 506 const gfx::Font& ResourceBundle::GetFont(FontStyle style) { |
| 504 return GetFontList(style).GetPrimaryFont(); | 507 return GetFontList(style).GetPrimaryFont(); |
| 505 } | 508 } |
| 506 | 509 |
| 507 void ResourceBundle::ReloadFonts() { | 510 void ResourceBundle::ReloadFonts() { |
| 508 base::AutoLock lock_scope(*images_and_fonts_lock_); | 511 base::AutoLock lock_scope(*images_and_fonts_lock_); |
| 509 base_font_list_.reset(); | 512 base_font_list_.reset(); |
| 510 LoadFontsIfNecessary(); | 513 LoadFontsIfNecessary(); |
| 511 } | 514 } |
| 512 | 515 |
| 516 ScaleFactor ResourceBundle::GetMaxScaleFactor() const { |
| 517 #if defined(OS_CHROMEOS) |
| 518 return max_scale_factor_; |
| 519 #else |
| 520 return GetSupportedScaleFactors().back(); |
| 521 #endif |
| 522 } |
| 523 |
| 513 ResourceBundle::ResourceBundle(Delegate* delegate) | 524 ResourceBundle::ResourceBundle(Delegate* delegate) |
| 514 : delegate_(delegate), | 525 : delegate_(delegate), |
| 515 images_and_fonts_lock_(new base::Lock), | 526 images_and_fonts_lock_(new base::Lock), |
| 516 locale_resources_data_lock_(new base::Lock), | 527 locale_resources_data_lock_(new base::Lock), |
| 517 max_scale_factor_(SCALE_FACTOR_100P) { | 528 max_scale_factor_(SCALE_FACTOR_100P) { |
| 518 } | 529 } |
| 519 | 530 |
| 520 ResourceBundle::~ResourceBundle() { | 531 ResourceBundle::~ResourceBundle() { |
| 521 FreeImages(); | 532 FreeImages(); |
| 522 UnloadLocaleResources(); | 533 UnloadLocaleResources(); |
| 523 } | 534 } |
| 524 | 535 |
| 536 // static |
| 537 void ResourceBundle::InitSharedInstance(Delegate* delegate) { |
| 538 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; |
| 539 g_shared_instance_ = new ResourceBundle(delegate); |
| 540 static std::vector<ScaleFactor> supported_scale_factors; |
| 541 #if !defined(OS_IOS) |
| 542 // On platforms other than iOS, 100P is always a supported scale factor. |
| 543 supported_scale_factors.push_back(SCALE_FACTOR_100P); |
| 544 #endif |
| 545 |
| 546 #if defined(OS_ANDROID) |
| 547 const gfx::Display display = |
| 548 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); |
| 549 const float display_density = display.device_scale_factor(); |
| 550 const ScaleFactor closest = FindClosestScaleFactorUnsafe(display_density); |
| 551 if (closest != SCALE_FACTOR_100P) |
| 552 supported_scale_factors.push_back(closest); |
| 553 #elif defined(OS_IOS) |
| 554 gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); |
| 555 if (display.device_scale_factor() > 1.0) { |
| 556 DCHECK_EQ(2.0, display.device_scale_factor()); |
| 557 supported_scale_factors.push_back(SCALE_FACTOR_200P); |
| 558 } else { |
| 559 supported_scale_factors.push_back(SCALE_FACTOR_100P); |
| 560 } |
| 561 #elif defined(OS_MACOSX) |
| 562 if (base::mac::IsOSLionOrLater()) |
| 563 supported_scale_factors.push_back(SCALE_FACTOR_200P); |
| 564 #elif defined(OS_WIN) |
| 565 // Have high-DPI resources for 140% and 180% scaling on Windows based on |
| 566 // default scaling for Metro mode. Round to nearest supported scale in |
| 567 // all cases. |
| 568 if (gfx::IsInHighDPIMode()) { |
| 569 supported_scale_factors.push_back(SCALE_FACTOR_140P); |
| 570 supported_scale_factors.push_back(SCALE_FACTOR_180P); |
| 571 } |
| 572 #elif defined(OS_CHROMEOS) |
| 573 // TODO(oshima): Include 200P only if the device support 200P |
| 574 supported_scale_factors.push_back(SCALE_FACTOR_200P); |
| 575 #endif |
| 576 ui::SetSupportedScaleFactors(supported_scale_factors); |
| 577 } |
| 578 |
| 525 void ResourceBundle::FreeImages() { | 579 void ResourceBundle::FreeImages() { |
| 526 images_.clear(); | 580 images_.clear(); |
| 527 } | 581 } |
| 528 | 582 |
| 529 void ResourceBundle::AddDataPackFromPathInternal(const base::FilePath& path, | 583 void ResourceBundle::AddDataPackFromPathInternal(const base::FilePath& path, |
| 530 ScaleFactor scale_factor, | 584 ScaleFactor scale_factor, |
| 531 bool optional) { | 585 bool optional) { |
| 532 // Do not pass an empty |path| value to this method. If the absolute path is | 586 // Do not pass an empty |path| value to this method. If the absolute path is |
| 533 // unknown pass just the pack file name. | 587 // unknown pass just the pack file name. |
| 534 DCHECK(!path.empty()); | 588 DCHECK(!path.empty()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 547 AddDataPack(data_pack.release()); | 601 AddDataPack(data_pack.release()); |
| 548 } else if (!optional) { | 602 } else if (!optional) { |
| 549 LOG(ERROR) << "Failed to load " << pack_path.value() | 603 LOG(ERROR) << "Failed to load " << pack_path.value() |
| 550 << "\nSome features may not be available."; | 604 << "\nSome features may not be available."; |
| 551 } | 605 } |
| 552 } | 606 } |
| 553 | 607 |
| 554 void ResourceBundle::AddDataPack(DataPack* data_pack) { | 608 void ResourceBundle::AddDataPack(DataPack* data_pack) { |
| 555 data_packs_.push_back(data_pack); | 609 data_packs_.push_back(data_pack); |
| 556 | 610 |
| 557 if (GetScaleFactorScale(data_pack->GetScaleFactor()) > | 611 if (GetImageScale(data_pack->GetScaleFactor()) > |
| 558 GetScaleFactorScale(max_scale_factor_)) | 612 GetImageScale(max_scale_factor_)) |
| 559 max_scale_factor_ = data_pack->GetScaleFactor(); | 613 max_scale_factor_ = data_pack->GetScaleFactor(); |
| 560 } | 614 } |
| 561 | 615 |
| 562 void ResourceBundle::LoadFontsIfNecessary() { | 616 void ResourceBundle::LoadFontsIfNecessary() { |
| 563 images_and_fonts_lock_->AssertAcquired(); | 617 images_and_fonts_lock_->AssertAcquired(); |
| 564 if (!base_font_list_.get()) { | 618 if (!base_font_list_.get()) { |
| 565 if (delegate_) { | 619 if (delegate_) { |
| 566 base_font_list_ = GetFontListFromDelegate(BaseFont); | 620 base_font_list_ = GetFontListFromDelegate(BaseFont); |
| 567 bold_font_list_ = GetFontListFromDelegate(BoldFont); | 621 bold_font_list_ = GetFontListFromDelegate(BoldFont); |
| 568 small_font_list_ = GetFontListFromDelegate(SmallFont); | 622 small_font_list_ = GetFontListFromDelegate(SmallFont); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 // static | 798 // static |
| 745 bool ResourceBundle::DecodePNG(const unsigned char* buf, | 799 bool ResourceBundle::DecodePNG(const unsigned char* buf, |
| 746 size_t size, | 800 size_t size, |
| 747 SkBitmap* bitmap, | 801 SkBitmap* bitmap, |
| 748 bool* fell_back_to_1x) { | 802 bool* fell_back_to_1x) { |
| 749 *fell_back_to_1x = PNGContainsFallbackMarker(buf, size); | 803 *fell_back_to_1x = PNGContainsFallbackMarker(buf, size); |
| 750 return gfx::PNGCodec::Decode(buf, size, bitmap); | 804 return gfx::PNGCodec::Decode(buf, size, bitmap); |
| 751 } | 805 } |
| 752 | 806 |
| 753 } // namespace ui | 807 } // namespace ui |
| OLD | NEW |