// 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_app_panel = SK_ColorWHITE; const SkColor ResourceBundle::frame_color_app_panel_inactive = SK_ColorWHITE; 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 */ std::string ResourceBundle::InitSharedInstance( const std::wstring& pref_locale) { DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; g_shared_instance_ = new ResourceBundle(); return 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 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 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()); bold_font_.reset(new gfx::Font()); *bold_font_ = base_font_->DeriveFont(0, base_font_->style() | gfx::Font::BOLD); 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 BoldFont: return *bold_font_; 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_; } }