| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/stl_util-inl.h" | 8 #include "base/stl_util-inl.h" |
| 9 #include "base/string_piece.h" | 9 #include "base/string_piece.h" |
| 10 #include "base/synchronization/lock.h" | 10 #include "base/synchronization/lock.h" |
| 11 #include "build/build_config.h" | 11 #include "build/build_config.h" |
| 12 #include "third_party/skia/include/core/SkBitmap.h" | 12 #include "third_party/skia/include/core/SkBitmap.h" |
| 13 #include "ui/base/resource/data_pack.h" | 13 #include "ui/base/resource/data_pack.h" |
| 14 #include "ui/gfx/codec/png_codec.h" | 14 #include "ui/gfx/codec/png_codec.h" |
| 15 #include "ui/gfx/font.h" | 15 #include "ui/gfx/font.h" |
| 16 #include "ui/gfx/image.h" |
| 16 | 17 |
| 17 namespace ui { | 18 namespace ui { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 // Font sizes relative to base font. | 22 // Font sizes relative to base font. |
| 22 #if defined(OS_CHROMEOS) && defined(CROS_FONTS_USING_BCI) | 23 #if defined(OS_CHROMEOS) && defined(CROS_FONTS_USING_BCI) |
| 23 const int kSmallFontSizeDelta = -3; | 24 const int kSmallFontSizeDelta = -3; |
| 24 const int kMediumFontSizeDelta = 2; | 25 const int kMediumFontSizeDelta = 2; |
| 25 const int kLargeFontSizeDelta = 7; | 26 const int kLargeFontSizeDelta = 7; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 } | 88 } |
| 88 | 89 |
| 89 /* static */ | 90 /* static */ |
| 90 ResourceBundle& ResourceBundle::GetSharedInstance() { | 91 ResourceBundle& ResourceBundle::GetSharedInstance() { |
| 91 // Must call InitSharedInstance before this function. | 92 // Must call InitSharedInstance before this function. |
| 92 CHECK(g_shared_instance_ != NULL); | 93 CHECK(g_shared_instance_ != NULL); |
| 93 return *g_shared_instance_; | 94 return *g_shared_instance_; |
| 94 } | 95 } |
| 95 | 96 |
| 96 SkBitmap* ResourceBundle::GetBitmapNamed(int resource_id) { | 97 SkBitmap* ResourceBundle::GetBitmapNamed(int resource_id) { |
| 97 // Check to see if we already have the Skia image in the cache. | 98 const SkBitmap* bitmap = |
| 99 static_cast<const SkBitmap*>(GetImageNamed(resource_id)); |
| 100 return const_cast<SkBitmap*>(bitmap); |
| 101 } |
| 102 |
| 103 gfx::Image& ResourceBundle::GetImageNamed(int resource_id) { |
| 104 // Check to see if the image is already in the cache. |
| 98 { | 105 { |
| 99 base::AutoLock lock_scope(*lock_); | 106 base::AutoLock lock_scope(*lock_); |
| 100 SkImageMap::const_iterator found = skia_images_.find(resource_id); | 107 ImageMap::const_iterator found = images_.find(resource_id); |
| 101 if (found != skia_images_.end()) | 108 if (found != images_.end()) |
| 102 return found->second; | 109 return *found->second; |
| 103 } | 110 } |
| 104 | 111 |
| 105 scoped_ptr<SkBitmap> bitmap; | 112 scoped_ptr<SkBitmap> bitmap(LoadBitmap(resources_data_, resource_id)); |
| 106 | |
| 107 bitmap.reset(LoadBitmap(resources_data_, resource_id)); | |
| 108 | |
| 109 if (bitmap.get()) { | 113 if (bitmap.get()) { |
| 110 // We loaded successfully. Cache the Skia version of the bitmap. | 114 // The load was successful, so cache the image. |
| 111 base::AutoLock lock_scope(*lock_); | 115 base::AutoLock lock_scope(*lock_); |
| 112 | 116 |
| 113 // Another thread raced us, and has already cached the skia image. | 117 // Another thread raced the load and has already cached the image. |
| 114 if (skia_images_.count(resource_id)) | 118 if (images_.count(resource_id)) |
| 115 return skia_images_[resource_id]; | 119 return *images_[resource_id]; |
| 116 | 120 |
| 117 skia_images_[resource_id] = bitmap.get(); | 121 gfx::Image* image = new gfx::Image(bitmap.release()); |
| 118 return bitmap.release(); | 122 images_[resource_id] = image; |
| 123 return *image; |
| 119 } | 124 } |
| 120 | 125 |
| 121 // We failed to retrieve the bitmap, show a debugging red square. | 126 // The load failed to retrieve the image; show a debugging red square. |
| 122 { | 127 LOG(WARNING) << "Unable to load image with id " << resource_id; |
| 123 LOG(WARNING) << "Unable to load bitmap with id " << resource_id; | 128 NOTREACHED(); // Want to assert in debug mode. |
| 124 NOTREACHED(); // Want to assert in debug mode. | 129 return *GetEmptyImage(); |
| 130 } |
| 125 | 131 |
| 126 base::AutoLock lock_scope(*lock_); // Guard empty_bitmap initialization. | 132 #if !defined(OS_MACOSX) && !defined(OS_LINUX) |
| 127 | 133 // Only Mac and Linux have non-Skia native image types. All other platforms use |
| 128 static SkBitmap* empty_bitmap = NULL; | 134 // Skia natively, so just use GetImageNamed(). |
| 129 if (!empty_bitmap) { | 135 gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) { |
| 130 // The placeholder bitmap is bright red so people notice the problem. | 136 return GetImageNamed(resource_id); |
| 131 // This bitmap will be leaked, but this code should never be hit. | |
| 132 empty_bitmap = new SkBitmap(); | |
| 133 empty_bitmap->setConfig(SkBitmap::kARGB_8888_Config, 32, 32); | |
| 134 empty_bitmap->allocPixels(); | |
| 135 empty_bitmap->eraseARGB(255, 255, 0, 0); | |
| 136 } | |
| 137 return empty_bitmap; | |
| 138 } | |
| 139 } | 137 } |
| 138 #endif |
| 140 | 139 |
| 141 RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytes( | 140 RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytes( |
| 142 int resource_id) const { | 141 int resource_id) const { |
| 143 RefCountedStaticMemory* bytes = | 142 RefCountedStaticMemory* bytes = |
| 144 LoadResourceBytes(resources_data_, resource_id); | 143 LoadResourceBytes(resources_data_, resource_id); |
| 145 | 144 |
| 146 // Check all our additional data packs for the resources if it wasn't loaded | 145 // Check all our additional data packs for the resources if it wasn't loaded |
| 147 // from our main source. | 146 // from our main source. |
| 148 for (std::vector<LoadedDataPack*>::const_iterator it = data_packs_.begin(); | 147 for (std::vector<LoadedDataPack*>::const_iterator it = data_packs_.begin(); |
| 149 !bytes && it != data_packs_.end(); ++it) { | 148 !bytes && it != data_packs_.end(); ++it) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 164 return *medium_font_; | 163 return *medium_font_; |
| 165 case MediumBoldFont: | 164 case MediumBoldFont: |
| 166 return *medium_bold_font_; | 165 return *medium_bold_font_; |
| 167 case LargeFont: | 166 case LargeFont: |
| 168 return *large_font_; | 167 return *large_font_; |
| 169 default: | 168 default: |
| 170 return *base_font_; | 169 return *base_font_; |
| 171 } | 170 } |
| 172 } | 171 } |
| 173 | 172 |
| 174 gfx::NativeImage ResourceBundle::GetNativeImageNamed(int resource_id) { | |
| 175 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 176 #if defined(OS_MACOSX) | |
| 177 return rb.GetNSImageNamed(resource_id); | |
| 178 #elif defined(USE_X11) && !defined(TOOLKIT_VIEWS) | |
| 179 return rb.GetPixbufNamed(resource_id); | |
| 180 #else | |
| 181 return rb.GetBitmapNamed(resource_id); | |
| 182 #endif | |
| 183 } | |
| 184 | |
| 185 ResourceBundle::ResourceBundle() | 173 ResourceBundle::ResourceBundle() |
| 186 : lock_(new base::Lock), | 174 : lock_(new base::Lock), |
| 187 resources_data_(NULL), | 175 resources_data_(NULL), |
| 188 locale_resources_data_(NULL) { | 176 locale_resources_data_(NULL) { |
| 189 } | 177 } |
| 190 | 178 |
| 191 void ResourceBundle::FreeImages() { | 179 void ResourceBundle::FreeImages() { |
| 192 STLDeleteContainerPairSecondPointers(skia_images_.begin(), | 180 STLDeleteContainerPairSecondPointers(images_.begin(), |
| 193 skia_images_.end()); | 181 images_.end()); |
| 194 skia_images_.clear(); | 182 images_.clear(); |
| 195 } | 183 } |
| 196 | 184 |
| 197 void ResourceBundle::LoadFontsIfNecessary() { | 185 void ResourceBundle::LoadFontsIfNecessary() { |
| 198 base::AutoLock lock_scope(*lock_); | 186 base::AutoLock lock_scope(*lock_); |
| 199 if (!base_font_.get()) { | 187 if (!base_font_.get()) { |
| 200 base_font_.reset(new gfx::Font()); | 188 base_font_.reset(new gfx::Font()); |
| 201 | 189 |
| 202 bold_font_.reset(new gfx::Font()); | 190 bold_font_.reset(new gfx::Font()); |
| 203 *bold_font_ = | 191 *bold_font_ = |
| 204 base_font_->DeriveFont(0, base_font_->GetStyle() | gfx::Font::BOLD); | 192 base_font_->DeriveFont(0, base_font_->GetStyle() | gfx::Font::BOLD); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 228 | 216 |
| 229 SkBitmap bitmap; | 217 SkBitmap bitmap; |
| 230 if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) { | 218 if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) { |
| 231 NOTREACHED() << "Unable to decode theme image resource " << resource_id; | 219 NOTREACHED() << "Unable to decode theme image resource " << resource_id; |
| 232 return NULL; | 220 return NULL; |
| 233 } | 221 } |
| 234 | 222 |
| 235 return new SkBitmap(bitmap); | 223 return new SkBitmap(bitmap); |
| 236 } | 224 } |
| 237 | 225 |
| 226 gfx::Image* ResourceBundle::GetEmptyImage() { |
| 227 base::AutoLock lock(*lock_); |
| 228 |
| 229 static gfx::Image* empty_image = NULL; |
| 230 if (!empty_image) { |
| 231 // The placeholder bitmap is bright red so people notice the problem. |
| 232 // This bitmap will be leaked, but this code should never be hit. |
| 233 SkBitmap* bitmap = new SkBitmap(); |
| 234 bitmap->setConfig(SkBitmap::kARGB_8888_Config, 32, 32); |
| 235 bitmap->allocPixels(); |
| 236 bitmap->eraseARGB(255, 255, 0, 0); |
| 237 empty_image = new gfx::Image(bitmap); |
| 238 } |
| 239 return empty_image; |
| 240 } |
| 238 | 241 |
| 239 // LoadedDataPack ------------------------------------------------------------- | 242 // LoadedDataPack ------------------------------------------------------------- |
| 240 | 243 |
| 241 ResourceBundle::LoadedDataPack::LoadedDataPack(const FilePath& path) | 244 ResourceBundle::LoadedDataPack::LoadedDataPack(const FilePath& path) |
| 242 : path_(path) { | 245 : path_(path) { |
| 243 // Always preload the data packs so we can maintain constness. | 246 // Always preload the data packs so we can maintain constness. |
| 244 Load(); | 247 Load(); |
| 245 } | 248 } |
| 246 | 249 |
| 247 ResourceBundle::LoadedDataPack::~LoadedDataPack() { | 250 ResourceBundle::LoadedDataPack::~LoadedDataPack() { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 260 int resource_id, base::StringPiece* data) const { | 263 int resource_id, base::StringPiece* data) const { |
| 261 return data_pack_->GetStringPiece(static_cast<uint32>(resource_id), data); | 264 return data_pack_->GetStringPiece(static_cast<uint32>(resource_id), data); |
| 262 } | 265 } |
| 263 | 266 |
| 264 RefCountedStaticMemory* ResourceBundle::LoadedDataPack::GetStaticMemory( | 267 RefCountedStaticMemory* ResourceBundle::LoadedDataPack::GetStaticMemory( |
| 265 int resource_id) const { | 268 int resource_id) const { |
| 266 return data_pack_->GetStaticMemory(resource_id); | 269 return data_pack_->GetStaticMemory(resource_id); |
| 267 } | 270 } |
| 268 | 271 |
| 269 } // namespace ui | 272 } // namespace ui |
| OLD | NEW |