This source file includes following definitions.
- InitDefaultFontList
- resource_id_
- ResourceBundleImageSource
- GetImageForScale
- InitSharedInstanceWithLocale
- InitSharedInstanceLocaleOnly
- InitSharedInstanceWithPakFile
- InitSharedInstanceWithPakPath
- CleanupSharedInstance
- HasSharedInstance
- GetSharedInstance
- LocaleDataPakExists
- AddDataPackFromPath
- AddOptionalDataPackFromPath
- AddDataPackFromFile
- GetLocaleFilePath
- LoadLocaleResources
- LoadTestResources
- UnloadLocaleResources
- OverrideLocalePakForTest
- GetOverriddenPakPath
- ReloadLocaleResources
- GetImageSkiaNamed
- GetImageNamed
- GetNativeImageNamed
- LoadDataResourceBytes
- LoadDataResourceBytesForScale
- GetRawDataResource
- GetRawDataResourceForScale
- GetLocalizedString
- GetFontList
- GetFont
- ReloadFonts
- GetMaxScaleFactor
- max_scale_factor_
- InitSharedInstance
- FreeImages
- AddDataPackFromPathInternal
- AddDataPack
- LoadFontsIfNecessary
- GetFontListFromDelegate
- LoadBitmap
- LoadBitmap
- GetEmptyImage
- ShouldHighlightMissingScaledResources
- PNGContainsFallbackMarker
- DecodePNG
- PlatformScaleImage
#include "ui/base/resource/resource_bundle.h"
#include <vector>
#include "base/big_endian.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "build/build_config.h"
#include "grit/app_locale_settings.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/layout.h"
#include "ui/base/resource/data_pack.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_source.h"
#include "ui/gfx/safe_integer_conversions.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/skbitmap_operations.h"
#if defined(OS_CHROMEOS)
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/platform_font_pango.h"
#endif
#if defined(OS_WIN)
#include "ui/base/win/dpi_setup.h"
#include "ui/gfx/win/dpi.h"
#endif
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include "base/mac/mac_util.h"
#endif
namespace ui {
namespace {
const int kSmallFontSizeDelta = -1;
const int kMediumFontSizeDelta = 3;
const int kLargeFontSizeDelta = 8;
const unsigned char kPngMagic[8] = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
const size_t kPngChunkMetadataSize = 12;
const unsigned char kPngScaleChunkType[4] = { 'c', 's', 'C', 'l' };
const unsigned char kPngDataChunkType[4] = { 'I', 'D', 'A', 'T' };
ResourceBundle* g_shared_instance_ = NULL;
void InitDefaultFontList() {
#if defined(OS_CHROMEOS)
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
std::string font_family = base::UTF16ToUTF8(
rb.GetLocalizedString(IDS_UI_FONT_FAMILY_CROS));
gfx::FontList::SetDefaultFontDescription(font_family);
gfx::PlatformFontPango::SetDefaultFontDescription(font_family);
#else
gfx::FontList::SetDefaultFontDescription(std::string());
#endif
}
}
class ResourceBundle::ResourceBundleImageSource : public gfx::ImageSkiaSource {
public:
ResourceBundleImageSource(ResourceBundle* rb, int resource_id)
: rb_(rb), resource_id_(resource_id) {}
virtual ~ResourceBundleImageSource() {}
virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
SkBitmap image;
bool fell_back_to_1x = false;
ScaleFactor scale_factor = GetSupportedScaleFactor(scale);
bool found = rb_->LoadBitmap(resource_id_, &scale_factor,
&image, &fell_back_to_1x);
if (!found)
return gfx::ImageSkiaRep();
if (fell_back_to_1x) {
image = skia::ImageOperations::Resize(
image,
skia::ImageOperations::RESIZE_LANCZOS3,
gfx::ToCeiledInt(image.width() * scale),
gfx::ToCeiledInt(image.height() * scale));
if (ShouldHighlightMissingScaledResources()) {
LOG(ERROR) << "Missing " << scale << "x scaled resource. id="
<< resource_id_;
SkBitmap mask;
mask.setConfig(SkBitmap::kARGB_8888_Config,
image.width(), image.height());
mask.allocPixels();
mask.eraseColor(SK_ColorRED);
image = SkBitmapOperations::CreateBlendedBitmap(image, mask, 0.2);
}
} else {
image = PlatformScaleImage(image,
ui::GetScaleForScaleFactor(scale_factor),
scale);
}
return gfx::ImageSkiaRep(image, scale);
}
private:
ResourceBundle* rb_;
const int resource_id_;
DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageSource);
};
std::string ResourceBundle::InitSharedInstanceWithLocale(
const std::string& pref_locale, Delegate* delegate) {
InitSharedInstance(delegate);
g_shared_instance_->LoadCommonResources();
std::string result = g_shared_instance_->LoadLocaleResources(pref_locale);
InitDefaultFontList();
return result;
}
std::string ResourceBundle::InitSharedInstanceLocaleOnly(
const std::string& pref_locale, Delegate* delegate) {
InitSharedInstance(delegate);
std::string result = g_shared_instance_->LoadLocaleResources(pref_locale);
InitDefaultFontList();
return result;
}
void ResourceBundle::InitSharedInstanceWithPakFile(
base::File pak_file, bool should_load_common_resources) {
InitSharedInstance(NULL);
if (should_load_common_resources)
g_shared_instance_->LoadCommonResources();
scoped_ptr<DataPack> data_pack(
new DataPack(SCALE_FACTOR_100P));
if (!data_pack->LoadFromFile(pak_file.Pass())) {
NOTREACHED() << "failed to load pak file";
return;
}
g_shared_instance_->locale_resources_data_.reset(data_pack.release());
InitDefaultFontList();
}
void ResourceBundle::InitSharedInstanceWithPakPath(const base::FilePath& path) {
InitSharedInstance(NULL);
g_shared_instance_->LoadTestResources(path, path);
InitDefaultFontList();
}
void ResourceBundle::CleanupSharedInstance() {
if (g_shared_instance_) {
delete g_shared_instance_;
g_shared_instance_ = NULL;
}
}
bool ResourceBundle::HasSharedInstance() {
return g_shared_instance_ != NULL;
}
ResourceBundle& ResourceBundle::GetSharedInstance() {
CHECK(g_shared_instance_ != NULL);
return *g_shared_instance_;
}
bool ResourceBundle::LocaleDataPakExists(const std::string& locale) {
return !GetLocaleFilePath(locale, true).empty();
}
void ResourceBundle::AddDataPackFromPath(const base::FilePath& path,
ScaleFactor scale_factor) {
AddDataPackFromPathInternal(path, scale_factor, false);
}
void ResourceBundle::AddOptionalDataPackFromPath(const base::FilePath& path,
ScaleFactor scale_factor) {
AddDataPackFromPathInternal(path, scale_factor, true);
}
void ResourceBundle::AddDataPackFromFile(base::File file,
ScaleFactor scale_factor) {
scoped_ptr<DataPack> data_pack(
new DataPack(scale_factor));
if (data_pack->LoadFromFile(file.Pass())) {
AddDataPack(data_pack.release());
} else {
LOG(ERROR) << "Failed to load data pack from file."
<< "\nSome features may not be available.";
}
}
#if !defined(OS_MACOSX)
base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
bool test_file_exists) {
if (app_locale.empty())
return base::FilePath();
base::FilePath locale_file_path;
PathService::Get(ui::DIR_LOCALES, &locale_file_path);
if (!locale_file_path.empty())
locale_file_path = locale_file_path.AppendASCII(app_locale + ".pak");
if (delegate_) {
locale_file_path =
delegate_->GetPathForLocalePack(locale_file_path, app_locale);
}
if (locale_file_path.empty() || !locale_file_path.IsAbsolute())
return base::FilePath();
if (test_file_exists && !base::PathExists(locale_file_path))
return base::FilePath();
return locale_file_path;
}
#endif
std::string ResourceBundle::LoadLocaleResources(
const std::string& pref_locale) {
DCHECK(!locale_resources_data_.get()) << "locale.pak already loaded";
std::string app_locale = l10n_util::GetApplicationLocale(pref_locale);
base::FilePath locale_file_path = GetOverriddenPakPath();
if (locale_file_path.empty()) {
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kLocalePak)) {
locale_file_path =
command_line->GetSwitchValuePath(switches::kLocalePak);
} else {
locale_file_path = GetLocaleFilePath(app_locale, true);
}
}
if (locale_file_path.empty()) {
LOG(WARNING) << "locale_file_path.empty()";
return std::string();
}
scoped_ptr<DataPack> data_pack(
new DataPack(SCALE_FACTOR_100P));
if (!data_pack->LoadFromPath(locale_file_path)) {
UMA_HISTOGRAM_ENUMERATION("ResourceBundle.LoadLocaleResourcesError",
logging::GetLastSystemErrorCode(), 16000);
LOG(ERROR) << "failed to load locale.pak";
NOTREACHED();
return std::string();
}
locale_resources_data_.reset(data_pack.release());
return app_locale;
}
void ResourceBundle::LoadTestResources(const base::FilePath& path,
const base::FilePath& locale_path) {
scoped_ptr<DataPack> data_pack(new DataPack(SCALE_FACTOR_100P));
if (!path.empty() && data_pack->LoadFromPath(path))
AddDataPack(data_pack.release());
data_pack.reset(new DataPack(ui::SCALE_FACTOR_NONE));
if (!locale_path.empty() && data_pack->LoadFromPath(locale_path)) {
locale_resources_data_.reset(data_pack.release());
} else {
locale_resources_data_.reset(new DataPack(ui::SCALE_FACTOR_NONE));
}
}
void ResourceBundle::UnloadLocaleResources() {
locale_resources_data_.reset();
}
void ResourceBundle::OverrideLocalePakForTest(const base::FilePath& pak_path) {
overridden_pak_path_ = pak_path;
}
const base::FilePath& ResourceBundle::GetOverriddenPakPath() {
return overridden_pak_path_;
}
std::string ResourceBundle::ReloadLocaleResources(
const std::string& pref_locale) {
base::AutoLock lock_scope(*locale_resources_data_lock_);
UnloadLocaleResources();
return LoadLocaleResources(pref_locale);
}
gfx::ImageSkia* ResourceBundle::GetImageSkiaNamed(int resource_id) {
const gfx::ImageSkia* image = GetImageNamed(resource_id).ToImageSkia();
return const_cast<gfx::ImageSkia*>(image);
}
gfx::Image& ResourceBundle::GetImageNamed(int resource_id) {
{
base::AutoLock lock_scope(*images_and_fonts_lock_);
if (images_.count(resource_id))
return images_[resource_id];
}
gfx::Image image;
if (delegate_)
image = delegate_->GetImageNamed(resource_id);
if (image.IsEmpty()) {
DCHECK(!data_packs_.empty()) <<
"Missing call to SetResourcesDataDLL?";
#if defined(OS_CHROMEOS) || defined(OS_WIN)
ui::ScaleFactor scale_factor_to_load = GetMaxScaleFactor();
#else
ui::ScaleFactor scale_factor_to_load = ui::SCALE_FACTOR_100P;
#endif
float scale = GetImageScale(scale_factor_to_load);
gfx::ImageSkia image_skia(new ResourceBundleImageSource(this, resource_id),
scale);
if (image_skia.isNull()) {
LOG(WARNING) << "Unable to load image with id " << resource_id;
NOTREACHED();
return GetEmptyImage();
}
image_skia.SetReadOnly();
image = gfx::Image(image_skia);
}
base::AutoLock lock_scope(*images_and_fonts_lock_);
if (images_.count(resource_id))
return images_[resource_id];
images_[resource_id] = image;
return images_[resource_id];
}
gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) {
return GetNativeImageNamed(resource_id, RTL_DISABLED);
}
base::RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytes(
int resource_id) const {
return LoadDataResourceBytesForScale(resource_id, ui::SCALE_FACTOR_NONE);
}
base::RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytesForScale(
int resource_id,
ScaleFactor scale_factor) const {
base::RefCountedStaticMemory* bytes = NULL;
if (delegate_)
bytes = delegate_->LoadDataResourceBytes(resource_id, scale_factor);
if (!bytes) {
base::StringPiece data =
GetRawDataResourceForScale(resource_id, scale_factor);
if (!data.empty()) {
bytes = new base::RefCountedStaticMemory(data.data(), data.length());
}
}
return bytes;
}
base::StringPiece ResourceBundle::GetRawDataResource(int resource_id) const {
return GetRawDataResourceForScale(resource_id, ui::SCALE_FACTOR_NONE);
}
base::StringPiece ResourceBundle::GetRawDataResourceForScale(
int resource_id,
ScaleFactor scale_factor) const {
base::StringPiece data;
if (delegate_ &&
delegate_->GetRawDataResource(resource_id, scale_factor, &data))
return data;
if (scale_factor != ui::SCALE_FACTOR_100P) {
for (size_t i = 0; i < data_packs_.size(); i++) {
if (data_packs_[i]->GetScaleFactor() == scale_factor &&
data_packs_[i]->GetStringPiece(resource_id, &data))
return data;
}
}
for (size_t i = 0; i < data_packs_.size(); i++) {
if ((data_packs_[i]->GetScaleFactor() == ui::SCALE_FACTOR_100P ||
data_packs_[i]->GetScaleFactor() == ui::SCALE_FACTOR_200P ||
data_packs_[i]->GetScaleFactor() == ui::SCALE_FACTOR_NONE) &&
data_packs_[i]->GetStringPiece(resource_id, &data))
return data;
}
return base::StringPiece();
}
base::string16 ResourceBundle::GetLocalizedString(int message_id) {
base::string16 string;
if (delegate_ && delegate_->GetLocalizedString(message_id, &string))
return string;
base::AutoLock lock_scope(*locale_resources_data_lock_);
if (!locale_resources_data_.get()) {
LOG(WARNING) << "locale resources are not loaded";
return base::string16();
}
base::StringPiece data;
if (!locale_resources_data_->GetStringPiece(message_id, &data)) {
data = GetRawDataResource(message_id);
if (data.empty()) {
NOTREACHED() << "unable to find resource: " << message_id;
return base::string16();
}
}
ResourceHandle::TextEncodingType encoding =
locale_resources_data_->GetTextEncodingType();
DCHECK(encoding == ResourceHandle::UTF16 || encoding == ResourceHandle::UTF8)
<< "requested localized string from binary pack file";
base::string16 msg;
if (encoding == ResourceHandle::UTF16) {
msg = base::string16(reinterpret_cast<const base::char16*>(data.data()),
data.length() / 2);
} else if (encoding == ResourceHandle::UTF8) {
msg = base::UTF8ToUTF16(data);
}
return msg;
}
const gfx::FontList& ResourceBundle::GetFontList(FontStyle style) {
{
base::AutoLock lock_scope(*images_and_fonts_lock_);
LoadFontsIfNecessary();
}
switch (style) {
case BoldFont:
return *bold_font_list_;
case SmallFont:
return *small_font_list_;
case MediumFont:
return *medium_font_list_;
case SmallBoldFont:
return *small_bold_font_list_;
case MediumBoldFont:
return *medium_bold_font_list_;
case LargeFont:
return *large_font_list_;
case LargeBoldFont:
return *large_bold_font_list_;
default:
return *base_font_list_;
}
}
const gfx::Font& ResourceBundle::GetFont(FontStyle style) {
return GetFontList(style).GetPrimaryFont();
}
void ResourceBundle::ReloadFonts() {
base::AutoLock lock_scope(*images_and_fonts_lock_);
base_font_list_.reset();
LoadFontsIfNecessary();
}
ScaleFactor ResourceBundle::GetMaxScaleFactor() const {
#if defined(OS_CHROMEOS) || defined(OS_WIN)
return max_scale_factor_;
#else
return GetSupportedScaleFactors().back();
#endif
}
ResourceBundle::ResourceBundle(Delegate* delegate)
: delegate_(delegate),
images_and_fonts_lock_(new base::Lock),
locale_resources_data_lock_(new base::Lock),
max_scale_factor_(SCALE_FACTOR_100P) {
}
ResourceBundle::~ResourceBundle() {
FreeImages();
UnloadLocaleResources();
}
void ResourceBundle::InitSharedInstance(Delegate* delegate) {
DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice";
g_shared_instance_ = new ResourceBundle(delegate);
static std::vector<ScaleFactor> supported_scale_factors;
#if !defined(OS_IOS) && !defined(OS_WIN)
supported_scale_factors.push_back(SCALE_FACTOR_100P);
#endif
#if defined(OS_ANDROID)
const gfx::Display display =
gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
const float display_density = display.device_scale_factor();
const ScaleFactor closest = FindClosestScaleFactorUnsafe(display_density);
if (closest != SCALE_FACTOR_100P)
supported_scale_factors.push_back(closest);
#elif defined(OS_IOS)
gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
if (display.device_scale_factor() > 1.0) {
DCHECK_EQ(2.0, display.device_scale_factor());
supported_scale_factors.push_back(SCALE_FACTOR_200P);
} else {
supported_scale_factors.push_back(SCALE_FACTOR_100P);
}
#elif defined(OS_MACOSX)
if (base::mac::IsOSLionOrLater())
supported_scale_factors.push_back(SCALE_FACTOR_200P);
#elif defined(OS_CHROMEOS)
supported_scale_factors.push_back(SCALE_FACTOR_200P);
#elif defined(OS_LINUX) && defined(ENABLE_HIDPI)
supported_scale_factors.push_back(SCALE_FACTOR_200P);
#elif defined(OS_WIN)
bool default_to_100P = true;
if (gfx::IsHighDPIEnabled()) {
if (gfx::GetDPIScale() > 1.25) {
supported_scale_factors.push_back(SCALE_FACTOR_200P);
default_to_100P = false;
}
}
if (default_to_100P)
supported_scale_factors.push_back(SCALE_FACTOR_100P);
#endif
ui::SetSupportedScaleFactors(supported_scale_factors);
#if defined(OS_WIN)
ui::win::InitDeviceScaleFactor();
#endif
}
void ResourceBundle::FreeImages() {
images_.clear();
}
void ResourceBundle::AddDataPackFromPathInternal(const base::FilePath& path,
ScaleFactor scale_factor,
bool optional) {
DCHECK(!path.empty());
base::FilePath pack_path = path;
if (delegate_)
pack_path = delegate_->GetPathForResourcePack(pack_path, scale_factor);
if (pack_path.empty() || !pack_path.IsAbsolute())
return;
scoped_ptr<DataPack> data_pack(
new DataPack(scale_factor));
if (data_pack->LoadFromPath(pack_path)) {
AddDataPack(data_pack.release());
} else if (!optional) {
LOG(ERROR) << "Failed to load " << pack_path.value()
<< "\nSome features may not be available.";
}
}
void ResourceBundle::AddDataPack(DataPack* data_pack) {
data_packs_.push_back(data_pack);
if (GetImageScale(data_pack->GetScaleFactor()) >
GetImageScale(max_scale_factor_))
max_scale_factor_ = data_pack->GetScaleFactor();
}
void ResourceBundle::LoadFontsIfNecessary() {
images_and_fonts_lock_->AssertAcquired();
if (!base_font_list_.get()) {
if (delegate_) {
base_font_list_ = GetFontListFromDelegate(BaseFont);
bold_font_list_ = GetFontListFromDelegate(BoldFont);
small_font_list_ = GetFontListFromDelegate(SmallFont);
small_bold_font_list_ = GetFontListFromDelegate(SmallBoldFont);
medium_font_list_ = GetFontListFromDelegate(MediumFont);
medium_bold_font_list_ = GetFontListFromDelegate(MediumBoldFont);
large_font_list_ = GetFontListFromDelegate(LargeFont);
large_bold_font_list_ = GetFontListFromDelegate(LargeBoldFont);
}
if (!base_font_list_.get())
base_font_list_.reset(new gfx::FontList());
if (!bold_font_list_.get()) {
bold_font_list_.reset(new gfx::FontList());
*bold_font_list_ = base_font_list_->DeriveWithStyle(
base_font_list_->GetFontStyle() | gfx::Font::BOLD);
}
if (!small_font_list_.get()) {
small_font_list_.reset(new gfx::FontList());
*small_font_list_ =
base_font_list_->DeriveWithSizeDelta(kSmallFontSizeDelta);
}
if (!small_bold_font_list_.get()) {
small_bold_font_list_.reset(new gfx::FontList());
*small_bold_font_list_ = small_font_list_->DeriveWithStyle(
small_font_list_->GetFontStyle() | gfx::Font::BOLD);
}
if (!medium_font_list_.get()) {
medium_font_list_.reset(new gfx::FontList());
*medium_font_list_ =
base_font_list_->DeriveWithSizeDelta(kMediumFontSizeDelta);
}
if (!medium_bold_font_list_.get()) {
medium_bold_font_list_.reset(new gfx::FontList());
*medium_bold_font_list_ = medium_font_list_->DeriveWithStyle(
medium_font_list_->GetFontStyle() | gfx::Font::BOLD);
}
if (!large_font_list_.get()) {
large_font_list_.reset(new gfx::FontList());
*large_font_list_ =
base_font_list_->DeriveWithSizeDelta(kLargeFontSizeDelta);
}
if (!large_bold_font_list_.get()) {
large_bold_font_list_.reset(new gfx::FontList());
*large_bold_font_list_ = large_font_list_->DeriveWithStyle(
large_font_list_->GetFontStyle() | gfx::Font::BOLD);
}
}
}
scoped_ptr<gfx::FontList> ResourceBundle::GetFontListFromDelegate(
FontStyle style) {
DCHECK(delegate_);
scoped_ptr<gfx::Font> font = delegate_->GetFont(style);
if (font.get())
return scoped_ptr<gfx::FontList>(new gfx::FontList(*font));
return scoped_ptr<gfx::FontList>();
}
bool ResourceBundle::LoadBitmap(const ResourceHandle& data_handle,
int resource_id,
SkBitmap* bitmap,
bool* fell_back_to_1x) const {
DCHECK(fell_back_to_1x);
scoped_refptr<base::RefCountedMemory> memory(
data_handle.GetStaticMemory(resource_id));
if (!memory.get())
return false;
if (DecodePNG(memory->front(), memory->size(), bitmap, fell_back_to_1x))
return true;
#if !defined(OS_IOS)
scoped_ptr<SkBitmap> jpeg_bitmap(
gfx::JPEGCodec::Decode(memory->front(), memory->size()));
if (jpeg_bitmap.get()) {
bitmap->swap(*jpeg_bitmap.get());
*fell_back_to_1x = false;
return true;
}
#endif
NOTREACHED() << "Unable to decode theme image resource " << resource_id;
return false;
}
bool ResourceBundle::LoadBitmap(int resource_id,
ScaleFactor* scale_factor,
SkBitmap* bitmap,
bool* fell_back_to_1x) const {
DCHECK(fell_back_to_1x);
for (size_t i = 0; i < data_packs_.size(); ++i) {
if (data_packs_[i]->GetScaleFactor() == ui::SCALE_FACTOR_NONE &&
LoadBitmap(*data_packs_[i], resource_id, bitmap, fell_back_to_1x)) {
*scale_factor = ui::SCALE_FACTOR_100P;
DCHECK(!*fell_back_to_1x);
return true;
}
if (data_packs_[i]->GetScaleFactor() == *scale_factor &&
LoadBitmap(*data_packs_[i], resource_id, bitmap, fell_back_to_1x)) {
return true;
}
}
return false;
}
gfx::Image& ResourceBundle::GetEmptyImage() {
base::AutoLock lock(*images_and_fonts_lock_);
if (empty_image_.IsEmpty()) {
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32, 32);
bitmap.allocPixels();
bitmap.eraseARGB(255, 255, 0, 0);
empty_image_ = gfx::Image::CreateFrom1xBitmap(bitmap);
}
return empty_image_;
}
bool ResourceBundle::ShouldHighlightMissingScaledResources() {
return CommandLine::ForCurrentProcess()->HasSwitch(
switches::kHighlightMissingScaledResources);
}
bool ResourceBundle::PNGContainsFallbackMarker(const unsigned char* buf,
size_t size) {
if (size < arraysize(kPngMagic) ||
memcmp(buf, kPngMagic, arraysize(kPngMagic)) != 0) {
return false;
}
size_t pos = arraysize(kPngMagic);
for (;;) {
if (size - pos < kPngChunkMetadataSize)
break;
uint32 length = 0;
base::ReadBigEndian(reinterpret_cast<const char*>(buf + pos), &length);
if (size - pos - kPngChunkMetadataSize < length)
break;
if (length == 0 && memcmp(buf + pos + sizeof(uint32), kPngScaleChunkType,
arraysize(kPngScaleChunkType)) == 0) {
return true;
}
if (memcmp(buf + pos + sizeof(uint32), kPngDataChunkType,
arraysize(kPngDataChunkType)) == 0) {
break;
}
pos += length + kPngChunkMetadataSize;
}
return false;
}
bool ResourceBundle::DecodePNG(const unsigned char* buf,
size_t size,
SkBitmap* bitmap,
bool* fell_back_to_1x) {
*fell_back_to_1x = PNGContainsFallbackMarker(buf, size);
return gfx::PNGCodec::Decode(buf, size, bitmap);
}
#if !defined(OS_WIN)
SkBitmap ResourceBundle::PlatformScaleImage(const SkBitmap& image,
float loaded_image_scale,
float desired_scale) {
return image;
}
#endif
}