blob: e3174d83cf7e21f75c9e31115891554ff2fbb2d0 [file] [log] [blame]
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "app/resource_bundle.h"
#include "app/gfx/codec/png_codec.h"
#include "app/gfx/font.h"
#include "base/logging.h"
#include "base/string_piece.h"
#include "net/base/file_stream.h"
#include "net/base/net_errors.h"
#include "third_party/skia/include/core/SkBitmap.h"
ResourceBundle* ResourceBundle::g_shared_instance_ = NULL;
/* static */
// TODO(glen): Finish moving these into theme provider (dialogs still
// depend on these colors).
const SkColor ResourceBundle::frame_color =
SkColorSetRGB(77, 139, 217);
const SkColor ResourceBundle::frame_color_inactive =
SkColorSetRGB(184, 209, 240);
const SkColor ResourceBundle::frame_color_incognito =
SkColorSetRGB(83, 106, 139);
const SkColor ResourceBundle::frame_color_incognito_inactive =
SkColorSetRGB(126, 139, 156);
const SkColor ResourceBundle::toolbar_color =
SkColorSetRGB(210, 225, 246);
const SkColor ResourceBundle::toolbar_separator_color =
SkColorSetRGB(182, 186, 192);
/* static */
void ResourceBundle::InitSharedInstance(const std::wstring& pref_locale) {
DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice";
g_shared_instance_ = new ResourceBundle();
g_shared_instance_->LoadResources(pref_locale);
}
/* static */
void ResourceBundle::CleanupSharedInstance() {
if (g_shared_instance_) {
delete g_shared_instance_;
g_shared_instance_ = NULL;
}
}
/* static */
ResourceBundle& ResourceBundle::GetSharedInstance() {
// Must call InitSharedInstance before this function.
CHECK(g_shared_instance_ != NULL);
return *g_shared_instance_;
}
ResourceBundle::ResourceBundle()
: resources_data_(NULL),
locale_resources_data_(NULL) {
}
void ResourceBundle::FreeImages() {
for (SkImageMap::iterator i = skia_images_.begin();
i != skia_images_.end(); i++) {
delete i->second;
}
skia_images_.clear();
}
/* static */
SkBitmap* ResourceBundle::LoadBitmap(DataHandle data_handle, int resource_id) {
scoped_refptr<RefCountedMemory> memory(
LoadResourceBytes(data_handle, resource_id));
if (!memory)
return NULL;
SkBitmap bitmap;
if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) {
NOTREACHED() << "Unable to decode theme image resource " << resource_id;
return NULL;
}
return new SkBitmap(bitmap);
}
std::string ResourceBundle::GetDataResource(int resource_id) {
return GetRawDataResource(resource_id).as_string();
}
RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytes(
int resource_id) const {
return LoadResourceBytes(resources_data_, resource_id);
}
SkBitmap* ResourceBundle::GetBitmapNamed(int resource_id) {
// Check to see if we already have the Skia image in the cache.
{
AutoLock lock_scope(lock_);
SkImageMap::const_iterator found = skia_images_.find(resource_id);
if (found != skia_images_.end())
return found->second;
}
scoped_ptr<SkBitmap> bitmap;
bitmap.reset(LoadBitmap(resources_data_, resource_id));
if (bitmap.get()) {
// We loaded successfully. Cache the Skia version of the bitmap.
AutoLock lock_scope(lock_);
// Another thread raced us, and has already cached the skia image.
if (skia_images_.count(resource_id))
return skia_images_[resource_id];
skia_images_[resource_id] = bitmap.get();
return bitmap.release();
}
// We failed to retrieve the bitmap, show a debugging red square.
{
LOG(WARNING) << "Unable to load bitmap with id " << resource_id;
NOTREACHED(); // Want to assert in debug mode.
AutoLock lock_scope(lock_); // Guard empty_bitmap initialization.
static SkBitmap* empty_bitmap = NULL;
if (!empty_bitmap) {
// The placeholder bitmap is bright red so people notice the problem.
// This bitmap will be leaked, but this code should never be hit.
empty_bitmap = new SkBitmap();
empty_bitmap->setConfig(SkBitmap::kARGB_8888_Config, 32, 32);
empty_bitmap->allocPixels();
empty_bitmap->eraseARGB(255, 255, 0, 0);
}
return empty_bitmap;
}
}
void ResourceBundle::LoadFontsIfNecessary() {
AutoLock lock_scope(lock_);
if (!base_font_.get()) {
base_font_.reset(new gfx::Font());
small_font_.reset(new gfx::Font());
*small_font_ = base_font_->DeriveFont(-2);
medium_font_.reset(new gfx::Font());
*medium_font_ = base_font_->DeriveFont(3);
medium_bold_font_.reset(new gfx::Font());
*medium_bold_font_ =
base_font_->DeriveFont(3, base_font_->style() | gfx::Font::BOLD);
large_font_.reset(new gfx::Font());
*large_font_ = base_font_->DeriveFont(8);
}
}
const gfx::Font& ResourceBundle::GetFont(FontStyle style) {
LoadFontsIfNecessary();
switch (style) {
case SmallFont:
return *small_font_;
case MediumFont:
return *medium_font_;
case MediumBoldFont:
return *medium_bold_font_;
case LargeFont:
return *large_font_;
default:
return *base_font_;
}
}