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 17 matching lines...) Expand all Loading... |
28 #include "ui/base/ui_base_switches.h" | 28 #include "ui/base/ui_base_switches.h" |
29 #include "ui/gfx/codec/jpeg_codec.h" | 29 #include "ui/gfx/codec/jpeg_codec.h" |
30 #include "ui/gfx/codec/png_codec.h" | 30 #include "ui/gfx/codec/png_codec.h" |
31 #include "ui/gfx/image/image_skia.h" | 31 #include "ui/gfx/image/image_skia.h" |
32 #include "ui/gfx/image/image_skia_source.h" | 32 #include "ui/gfx/image/image_skia_source.h" |
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_WIN) |
| 39 #include "ui/gfx/win/dpi.h" |
| 40 #endif |
| 41 |
| 42 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 43 #include "base/mac/mac_util.h" |
| 44 #endif |
| 45 |
38 namespace ui { | 46 namespace ui { |
39 | 47 |
40 namespace { | 48 namespace { |
41 | 49 |
42 // Font sizes relative to base font. | 50 // Font sizes relative to base font. |
43 const int kSmallFontSizeDelta = -1; | 51 const int kSmallFontSizeDelta = -1; |
44 const int kMediumFontSizeDelta = 3; | 52 const int kMediumFontSizeDelta = 3; |
45 const int kLargeFontSizeDelta = 8; | 53 const int kLargeFontSizeDelta = 8; |
46 | 54 |
47 // PNG-related constants. | 55 // PNG-related constants. |
(...skipping 13 matching lines...) Expand all Loading... |
61 // scaled image is not exactly |scale_factor| * the size of the 1x resource. | 69 // scaled image is not exactly |scale_factor| * the size of the 1x resource. |
62 // When --highlight-missing-scaled-resources flag is specified, scaled 1x images | 70 // When --highlight-missing-scaled-resources flag is specified, scaled 1x images |
63 // are higlighted by blending them with red. | 71 // are higlighted by blending them with red. |
64 class ResourceBundle::ResourceBundleImageSource : public gfx::ImageSkiaSource { | 72 class ResourceBundle::ResourceBundleImageSource : public gfx::ImageSkiaSource { |
65 public: | 73 public: |
66 ResourceBundleImageSource(ResourceBundle* rb, int resource_id) | 74 ResourceBundleImageSource(ResourceBundle* rb, int resource_id) |
67 : rb_(rb), resource_id_(resource_id) {} | 75 : rb_(rb), resource_id_(resource_id) {} |
68 virtual ~ResourceBundleImageSource() {} | 76 virtual ~ResourceBundleImageSource() {} |
69 | 77 |
70 // gfx::ImageSkiaSource overrides: | 78 // gfx::ImageSkiaSource overrides: |
71 virtual gfx::ImageSkiaRep GetImageForScale( | 79 virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE { |
72 ui::ScaleFactor scale_factor) OVERRIDE { | |
73 SkBitmap image; | 80 SkBitmap image; |
74 bool fell_back_to_1x = false; | 81 bool fell_back_to_1x = false; |
| 82 ScaleFactor scale_factor = GetSupportedScaleFactor(scale); |
75 bool found = rb_->LoadBitmap(resource_id_, &scale_factor, | 83 bool found = rb_->LoadBitmap(resource_id_, &scale_factor, |
76 &image, &fell_back_to_1x); | 84 &image, &fell_back_to_1x); |
| 85 // Force to a supported scale. |
| 86 scale = ui::GetImageScale(scale_factor); |
77 if (!found) | 87 if (!found) |
78 return gfx::ImageSkiaRep(); | 88 return gfx::ImageSkiaRep(); |
79 | 89 |
80 if (fell_back_to_1x) { | 90 if (fell_back_to_1x) { |
81 // GRIT fell back to the 100% image, so rescale it to the correct size. | 91 // GRIT fell back to the 100% image, so rescale it to the correct size. |
82 float scale = GetScaleFactorScale(scale_factor); | |
83 image = skia::ImageOperations::Resize( | 92 image = skia::ImageOperations::Resize( |
84 image, | 93 image, |
85 skia::ImageOperations::RESIZE_LANCZOS3, | 94 skia::ImageOperations::RESIZE_LANCZOS3, |
86 gfx::ToCeiledInt(image.width() * scale), | 95 gfx::ToCeiledInt(image.width() * scale), |
87 gfx::ToCeiledInt(image.height() * scale)); | 96 gfx::ToCeiledInt(image.height() * scale)); |
88 // If --highlight-missing-scaled-resources is specified, log the resource | 97 // If --highlight-missing-scaled-resources is specified, log the resource |
89 // id and blend the created resource with red. | 98 // id and blend the created resource with red. |
90 if (ShouldHighlightMissingScaledResources()) { | 99 if (ShouldHighlightMissingScaledResources()) { |
91 LOG(ERROR) << "Missing " << scale << "x scaled resource. id=" | 100 LOG(ERROR) << "Missing " << scale << "x scaled resource. id=" |
92 << resource_id_; | 101 << resource_id_; |
93 | 102 |
94 SkBitmap mask; | 103 SkBitmap mask; |
95 mask.setConfig(SkBitmap::kARGB_8888_Config, | 104 mask.setConfig(SkBitmap::kARGB_8888_Config, |
96 image.width(), image.height()); | 105 image.width(), image.height()); |
97 mask.allocPixels(); | 106 mask.allocPixels(); |
98 mask.eraseColor(SK_ColorRED); | 107 mask.eraseColor(SK_ColorRED); |
99 image = SkBitmapOperations::CreateBlendedBitmap(image, mask, 0.2); | 108 image = SkBitmapOperations::CreateBlendedBitmap(image, mask, 0.2); |
100 } | 109 } |
101 } | 110 } |
102 | 111 |
103 return gfx::ImageSkiaRep(image, scale_factor); | 112 return gfx::ImageSkiaRep(image, scale); |
104 } | 113 } |
105 | 114 |
106 private: | 115 private: |
107 ResourceBundle* rb_; | 116 ResourceBundle* rb_; |
108 const int resource_id_; | 117 const int resource_id_; |
109 | 118 |
110 DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageSource); | 119 DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageSource); |
111 }; | 120 }; |
112 | 121 |
113 // static | 122 // static |
114 std::string ResourceBundle::InitSharedInstanceWithLocale( | 123 std::string ResourceBundle::InitSharedInstanceWithLocale( |
115 const std::string& pref_locale, Delegate* delegate) { | 124 const std::string& pref_locale, Delegate* delegate) { |
116 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; | 125 InitSharedInstance(delegate); |
117 g_shared_instance_ = new ResourceBundle(delegate); | |
118 | |
119 g_shared_instance_->LoadCommonResources(); | 126 g_shared_instance_->LoadCommonResources(); |
120 std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); | 127 std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); |
121 return result; | 128 return result; |
122 } | 129 } |
123 | 130 |
124 // static | 131 // static |
125 std::string ResourceBundle::InitSharedInstanceLocaleOnly( | 132 std::string ResourceBundle::InitSharedInstanceLocaleOnly( |
126 const std::string& pref_locale, Delegate* delegate) { | 133 const std::string& pref_locale, Delegate* delegate) { |
127 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; | 134 InitSharedInstance(delegate); |
128 g_shared_instance_ = new ResourceBundle(delegate); | |
129 | |
130 std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); | 135 std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); |
131 return result; | 136 return result; |
132 } | 137 } |
133 | 138 |
134 // static | 139 // static |
135 void ResourceBundle::InitSharedInstanceWithPakFile( | 140 void ResourceBundle::InitSharedInstanceWithPakFile( |
136 base::PlatformFile pak_file, bool should_load_common_resources) { | 141 base::PlatformFile pak_file, bool should_load_common_resources) { |
137 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; | 142 InitSharedInstance(NULL); |
138 g_shared_instance_ = new ResourceBundle(NULL); | |
139 | |
140 if (should_load_common_resources) | 143 if (should_load_common_resources) |
141 g_shared_instance_->LoadCommonResources(); | 144 g_shared_instance_->LoadCommonResources(); |
142 | 145 |
143 scoped_ptr<DataPack> data_pack( | 146 scoped_ptr<DataPack> data_pack( |
144 new DataPack(SCALE_FACTOR_100P)); | 147 new DataPack(SCALE_FACTOR_100P)); |
145 if (!data_pack->LoadFromFile(pak_file)) { | 148 if (!data_pack->LoadFromFile(pak_file)) { |
146 NOTREACHED() << "failed to load pak file"; | 149 NOTREACHED() << "failed to load pak file"; |
147 return; | 150 return; |
148 } | 151 } |
149 g_shared_instance_->locale_resources_data_.reset(data_pack.release()); | 152 g_shared_instance_->locale_resources_data_.reset(data_pack.release()); |
150 } | 153 } |
151 | 154 |
152 // static | 155 // static |
153 void ResourceBundle::InitSharedInstanceWithPakPath(const base::FilePath& path) { | 156 void ResourceBundle::InitSharedInstanceWithPakPath(const base::FilePath& path) { |
154 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; | 157 InitSharedInstance(NULL); |
155 g_shared_instance_ = new ResourceBundle(NULL); | |
156 | |
157 g_shared_instance_->LoadTestResources(path, path); | 158 g_shared_instance_->LoadTestResources(path, path); |
158 } | 159 } |
159 | 160 |
160 // static | 161 // static |
161 void ResourceBundle::CleanupSharedInstance() { | 162 void ResourceBundle::CleanupSharedInstance() { |
162 if (g_shared_instance_) { | 163 if (g_shared_instance_) { |
163 delete g_shared_instance_; | 164 delete g_shared_instance_; |
164 g_shared_instance_ = NULL; | 165 g_shared_instance_ = NULL; |
165 } | 166 } |
166 } | 167 } |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 if (image.IsEmpty()) { | 324 if (image.IsEmpty()) { |
324 DCHECK(!data_packs_.empty()) << | 325 DCHECK(!data_packs_.empty()) << |
325 "Missing call to SetResourcesDataDLL?"; | 326 "Missing call to SetResourcesDataDLL?"; |
326 | 327 |
327 // TODO(oshima): Consider reading the image size from png IHDR chunk and | 328 // TODO(oshima): Consider reading the image size from png IHDR chunk and |
328 // skip decoding here and remove #ifdef below. | 329 // skip decoding here and remove #ifdef below. |
329 // ResourceBundle::GetSharedInstance() is destroyed after the | 330 // ResourceBundle::GetSharedInstance() is destroyed after the |
330 // BrowserMainLoop has finished running. |image_skia| is guaranteed to be | 331 // BrowserMainLoop has finished running. |image_skia| is guaranteed to be |
331 // destroyed before the resource bundle is destroyed. | 332 // destroyed before the resource bundle is destroyed. |
332 #if defined(OS_CHROMEOS) | 333 #if defined(OS_CHROMEOS) |
333 ui::ScaleFactor scale_factor_to_load = ui::GetMaxScaleFactor(); | 334 float scale_to_load = gfx::ImageSkia::GetMaxSupportedScale(); |
334 #else | 335 #else |
335 ui::ScaleFactor scale_factor_to_load = ui::SCALE_FACTOR_100P; | 336 float scale_to_load = 1.0f; |
336 #endif | 337 #endif |
337 gfx::ImageSkia image_skia(new ResourceBundleImageSource(this, resource_id), | 338 gfx::ImageSkia image_skia(new ResourceBundleImageSource(this, resource_id), |
338 scale_factor_to_load); | 339 scale_to_load); |
339 if (image_skia.isNull()) { | 340 if (image_skia.isNull()) { |
340 LOG(WARNING) << "Unable to load image with id " << resource_id; | 341 LOG(WARNING) << "Unable to load image with id " << resource_id; |
341 NOTREACHED(); // Want to assert in debug mode. | 342 NOTREACHED(); // Want to assert in debug mode. |
342 // The load failed to retrieve the image; show a debugging red square. | 343 // The load failed to retrieve the image; show a debugging red square. |
343 return GetEmptyImage(); | 344 return GetEmptyImage(); |
344 } | 345 } |
345 image_skia.SetReadOnly(); | 346 image_skia.SetReadOnly(); |
346 image = gfx::Image(image_skia); | 347 image = gfx::Image(image_skia); |
347 } | 348 } |
348 | 349 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 images_and_fonts_lock_(new base::Lock), | 499 images_and_fonts_lock_(new base::Lock), |
499 locale_resources_data_lock_(new base::Lock), | 500 locale_resources_data_lock_(new base::Lock), |
500 max_scale_factor_(SCALE_FACTOR_100P) { | 501 max_scale_factor_(SCALE_FACTOR_100P) { |
501 } | 502 } |
502 | 503 |
503 ResourceBundle::~ResourceBundle() { | 504 ResourceBundle::~ResourceBundle() { |
504 FreeImages(); | 505 FreeImages(); |
505 UnloadLocaleResources(); | 506 UnloadLocaleResources(); |
506 } | 507 } |
507 | 508 |
| 509 // static |
| 510 void ResourceBundle::InitSharedInstance(Delegate* delegate) { |
| 511 DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; |
| 512 g_shared_instance_ = new ResourceBundle(delegate); |
| 513 static std::vector<ScaleFactor> supported_scale_factors; |
| 514 #if !defined(OS_IOS) |
| 515 // On platforms other than iOS, 100P is always a supported scale factor. |
| 516 supported_scale_factors.push_back(SCALE_FACTOR_100P); |
| 517 #endif |
| 518 |
| 519 #if defined(OS_ANDROID) |
| 520 const gfx::Display display = |
| 521 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); |
| 522 const float display_density = display.device_scale_factor(); |
| 523 const ScaleFactor closest = FindClosestScaleFactorUnsafe(display_density); |
| 524 if (closest != SCALE_FACTOR_100P) |
| 525 supported_scale_factors.push_back(closest); |
| 526 #elif defined(OS_IOS) |
| 527 gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); |
| 528 if (display.device_scale_factor() > 1.0) { |
| 529 DCHECK_EQ(2.0, display.device_scale_factor()); |
| 530 supported_scale_factors.push_back(SCALE_FACTOR_200P); |
| 531 } else { |
| 532 supported_scale_factors.push_back(SCALE_FACTOR_100P); |
| 533 } |
| 534 #elif defined(OS_MACOSX) |
| 535 if (base::mac::IsOSLionOrLater()) |
| 536 supported_scale_factors.push_back(SCALE_FACTOR_200P); |
| 537 #elif defined(OS_WIN) |
| 538 // Have high-DPI resources for 140% and 180% scaling on Windows based on |
| 539 // default scaling for Metro mode. Round to nearest supported scale in |
| 540 // all cases. |
| 541 if (gfx::IsInHighDPIMode()) { |
| 542 supported_scale_factors.push_back(SCALE_FACTOR_140P); |
| 543 supported_scale_factors.push_back(SCALE_FACTOR_180P); |
| 544 } |
| 545 #elif defined(OS_CHROMEOS) |
| 546 // TODO(oshima): Include 200P only if the device support 200P |
| 547 supported_scale_factors.push_back(SCALE_FACTOR_200P); |
| 548 #endif |
| 549 ui::SetSupportedScaleFactors(supported_scale_factors); |
| 550 } |
| 551 |
508 void ResourceBundle::FreeImages() { | 552 void ResourceBundle::FreeImages() { |
509 images_.clear(); | 553 images_.clear(); |
510 } | 554 } |
511 | 555 |
512 void ResourceBundle::AddDataPackFromPathInternal(const base::FilePath& path, | 556 void ResourceBundle::AddDataPackFromPathInternal(const base::FilePath& path, |
513 ScaleFactor scale_factor, | 557 ScaleFactor scale_factor, |
514 bool optional) { | 558 bool optional) { |
515 // Do not pass an empty |path| value to this method. If the absolute path is | 559 // Do not pass an empty |path| value to this method. If the absolute path is |
516 // unknown pass just the pack file name. | 560 // unknown pass just the pack file name. |
517 DCHECK(!path.empty()); | 561 DCHECK(!path.empty()); |
(...skipping 12 matching lines...) Expand all Loading... |
530 AddDataPack(data_pack.release()); | 574 AddDataPack(data_pack.release()); |
531 } else if (!optional) { | 575 } else if (!optional) { |
532 LOG(ERROR) << "Failed to load " << pack_path.value() | 576 LOG(ERROR) << "Failed to load " << pack_path.value() |
533 << "\nSome features may not be available."; | 577 << "\nSome features may not be available."; |
534 } | 578 } |
535 } | 579 } |
536 | 580 |
537 void ResourceBundle::AddDataPack(DataPack* data_pack) { | 581 void ResourceBundle::AddDataPack(DataPack* data_pack) { |
538 data_packs_.push_back(data_pack); | 582 data_packs_.push_back(data_pack); |
539 | 583 |
540 if (GetScaleFactorScale(data_pack->GetScaleFactor()) > | 584 if (GetImageScale(data_pack->GetScaleFactor()) > |
541 GetScaleFactorScale(max_scale_factor_)) | 585 GetImageScale(max_scale_factor_)) |
542 max_scale_factor_ = data_pack->GetScaleFactor(); | 586 max_scale_factor_ = data_pack->GetScaleFactor(); |
543 } | 587 } |
544 | 588 |
545 void ResourceBundle::LoadFontsIfNecessary() { | 589 void ResourceBundle::LoadFontsIfNecessary() { |
546 images_and_fonts_lock_->AssertAcquired(); | 590 images_and_fonts_lock_->AssertAcquired(); |
547 if (!base_font_list_.get()) { | 591 if (!base_font_list_.get()) { |
548 if (delegate_) { | 592 if (delegate_) { |
549 base_font_list_ = GetFontListFromDelegate(BaseFont); | 593 base_font_list_ = GetFontListFromDelegate(BaseFont); |
550 bold_font_list_ = GetFontListFromDelegate(BoldFont); | 594 bold_font_list_ = GetFontListFromDelegate(BoldFont); |
551 small_font_list_ = GetFontListFromDelegate(SmallFont); | 595 small_font_list_ = GetFontListFromDelegate(SmallFont); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 // static | 771 // static |
728 bool ResourceBundle::DecodePNG(const unsigned char* buf, | 772 bool ResourceBundle::DecodePNG(const unsigned char* buf, |
729 size_t size, | 773 size_t size, |
730 SkBitmap* bitmap, | 774 SkBitmap* bitmap, |
731 bool* fell_back_to_1x) { | 775 bool* fell_back_to_1x) { |
732 *fell_back_to_1x = PNGContainsFallbackMarker(buf, size); | 776 *fell_back_to_1x = PNGContainsFallbackMarker(buf, size); |
733 return gfx::PNGCodec::Decode(buf, size, bitmap); | 777 return gfx::PNGCodec::Decode(buf, size, bitmap); |
734 } | 778 } |
735 | 779 |
736 } // namespace ui | 780 } // namespace ui |
OLD | NEW |