| 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/codec/tiff_codec.h" |
| 15 #include "ui/gfx/font.h" | 16 #include "ui/gfx/font.h" |
| 16 #include "ui/gfx/image.h" | 17 #include "ui/gfx/image.h" |
| 17 | 18 |
| 18 namespace ui { | 19 namespace ui { |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 | 22 |
| 22 // Font sizes relative to base font. | 23 // Font sizes relative to base font. |
| 23 #if defined(OS_CHROMEOS) && defined(CROS_FONTS_USING_BCI) | 24 #if defined(OS_CHROMEOS) && defined(CROS_FONTS_USING_BCI) |
| 24 const int kSmallFontSizeDelta = -3; | 25 const int kSmallFontSizeDelta = -3; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 CHECK(g_shared_instance_ != NULL); | 102 CHECK(g_shared_instance_ != NULL); |
| 102 return *g_shared_instance_; | 103 return *g_shared_instance_; |
| 103 } | 104 } |
| 104 | 105 |
| 105 SkBitmap* ResourceBundle::GetBitmapNamed(int resource_id) { | 106 SkBitmap* ResourceBundle::GetBitmapNamed(int resource_id) { |
| 106 const SkBitmap* bitmap = | 107 const SkBitmap* bitmap = |
| 107 static_cast<const SkBitmap*>(GetImageNamed(resource_id)); | 108 static_cast<const SkBitmap*>(GetImageNamed(resource_id)); |
| 108 return const_cast<SkBitmap*>(bitmap); | 109 return const_cast<SkBitmap*>(bitmap); |
| 109 } | 110 } |
| 110 | 111 |
| 112 bool ResourceBundle::GetBitmapsNamed(int resource_id, |
| 113 std::vector<SkBitmap*>& bitmaps) { |
| 114 std::vector<gfx::Image*> images; |
| 115 if (!GetImagesNamed(resource_id, images)) |
| 116 return false; |
| 117 |
| 118 for (std::vector<gfx::Image*>::iterator it = images.begin(); |
| 119 it != images.end(); ++it) { |
| 120 const SkBitmap* bitmap = static_cast<const SkBitmap*>(**it); |
| 121 bitmaps.push_back(const_cast<SkBitmap*>(bitmap)); |
| 122 } |
| 123 return true; |
| 124 } |
| 125 |
| 111 gfx::Image& ResourceBundle::GetImageNamed(int resource_id) { | 126 gfx::Image& ResourceBundle::GetImageNamed(int resource_id) { |
| 112 // Check to see if the image is already in the cache. | 127 std::vector<gfx::Image*> images; |
| 113 { | 128 if (GetImagesNamed(resource_id, images)) { |
| 114 base::AutoLock lock_scope(*lock_); | 129 if (!images.empty()) |
| 115 ImageMap::const_iterator found = images_.find(resource_id); | 130 return **images.begin(); |
| 116 if (found != images_.end()) | |
| 117 return *found->second; | |
| 118 } | |
| 119 | |
| 120 scoped_ptr<SkBitmap> bitmap(LoadBitmap(resources_data_, resource_id)); | |
| 121 if (bitmap.get()) { | |
| 122 // The load was successful, so cache the image. | |
| 123 base::AutoLock lock_scope(*lock_); | |
| 124 | |
| 125 // Another thread raced the load and has already cached the image. | |
| 126 if (images_.count(resource_id)) | |
| 127 return *images_[resource_id]; | |
| 128 | |
| 129 gfx::Image* image = new gfx::Image(bitmap.release()); | |
| 130 images_[resource_id] = image; | |
| 131 return *image; | |
| 132 } | 131 } |
| 133 | 132 |
| 134 // The load failed to retrieve the image; show a debugging red square. | 133 // The load failed to retrieve the image; show a debugging red square. |
| 135 LOG(WARNING) << "Unable to load image with id " << resource_id; | 134 NOTREACHED(); |
| 136 NOTREACHED(); // Want to assert in debug mode. | |
| 137 return *GetEmptyImage(); | 135 return *GetEmptyImage(); |
| 138 } | 136 } |
| 139 | 137 |
| 138 bool ResourceBundle::GetImagesNamed(int resource_id, |
| 139 std::vector<gfx::Image*>& images) { |
| 140 // Check to see if the image is already in the cache. |
| 141 if (GetImagesFromCacheNamed(resource_id, images)) { |
| 142 return true; |
| 143 } |
| 144 |
| 145 std::vector<SkBitmap> bitmaps; |
| 146 if (LoadBitmaps(resources_data_, resource_id, bitmaps)) { |
| 147 // The load was successful, so cache the images. |
| 148 { |
| 149 base::AutoLock lock_scope(*lock_); |
| 150 |
| 151 // Has another thread raced the load and has already cached the image? |
| 152 if (!images_.count(resource_id)) { |
| 153 std::vector<gfx::Image*>* images_ptr = new std::vector<gfx::Image*>; |
| 154 for (std::vector<SkBitmap>::iterator it = bitmaps.begin(); |
| 155 it != bitmaps.end(); ++it) { |
| 156 SkBitmap* bitmap = new SkBitmap(*it); |
| 157 gfx::Image* image = new gfx::Image(bitmap); |
| 158 images_ptr->push_back(image); |
| 159 images_[resource_id] = images_ptr; |
| 160 } |
| 161 } |
| 162 } |
| 163 return GetImagesFromCacheNamed(resource_id, images); |
| 164 } |
| 165 |
| 166 // The load failed to retrieve the image. |
| 167 LOG(WARNING) << "Unable to load image with id " << resource_id; |
| 168 NOTREACHED(); // Want to assert in debug mode. |
| 169 return false; |
| 170 } |
| 171 |
| 172 bool ResourceBundle::GetImagesFromCacheNamed(int resource_id, |
| 173 std::vector<gfx::Image*>& images) { |
| 174 base::AutoLock lock_scope(*lock_); |
| 175 |
| 176 ImageMap::const_iterator found = images_.find(resource_id); |
| 177 if (found == images_.end()) |
| 178 return false; |
| 179 |
| 180 std::vector<gfx::Image*>* found_images = found->second; |
| 181 for (std::vector<gfx::Image*>::const_iterator it = found_images->begin(); |
| 182 it != found_images->end(); ++it) { |
| 183 images.push_back(*it); |
| 184 } |
| 185 return true; |
| 186 } |
| 187 |
| 140 #if !defined(OS_MACOSX) && !defined(OS_LINUX) | 188 #if !defined(OS_MACOSX) && !defined(OS_LINUX) |
| 141 // Only Mac and Linux have non-Skia native image types. All other platforms use | 189 // Only Mac and Linux have non-Skia native image types. All other platforms use |
| 142 // Skia natively, so just use GetImageNamed(). | 190 // Skia natively, so just use GetImageNamed(). |
| 143 gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) { | 191 gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) { |
| 144 return GetImageNamed(resource_id); | 192 return GetImageNamed(resource_id); |
| 145 } | 193 } |
| 146 #endif | 194 #endif |
| 147 | 195 |
| 148 RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytes( | 196 RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytes( |
| 149 int resource_id) const { | 197 int resource_id) const { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 LoadFontsIfNecessary(); | 235 LoadFontsIfNecessary(); |
| 188 } | 236 } |
| 189 | 237 |
| 190 ResourceBundle::ResourceBundle() | 238 ResourceBundle::ResourceBundle() |
| 191 : lock_(new base::Lock), | 239 : lock_(new base::Lock), |
| 192 resources_data_(NULL), | 240 resources_data_(NULL), |
| 193 locale_resources_data_(NULL) { | 241 locale_resources_data_(NULL) { |
| 194 } | 242 } |
| 195 | 243 |
| 196 void ResourceBundle::FreeImages() { | 244 void ResourceBundle::FreeImages() { |
| 197 STLDeleteContainerPairSecondPointers(images_.begin(), | 245 for (ImageMap::iterator i = images_.begin(); i != images_.end(); ++i) { |
| 198 images_.end()); | 246 STLDeleteContainerPointers(i->second->begin(), i->second->end()); |
| 199 images_.clear(); | 247 } |
| 248 STLDeleteValues(&images_); |
| 200 } | 249 } |
| 201 | 250 |
| 202 void ResourceBundle::LoadFontsIfNecessary() { | 251 void ResourceBundle::LoadFontsIfNecessary() { |
| 203 lock_->AssertAcquired(); | 252 lock_->AssertAcquired(); |
| 204 if (!base_font_.get()) { | 253 if (!base_font_.get()) { |
| 205 base_font_.reset(new gfx::Font()); | 254 base_font_.reset(new gfx::Font()); |
| 206 | 255 |
| 207 bold_font_.reset(new gfx::Font()); | 256 bold_font_.reset(new gfx::Font()); |
| 208 *bold_font_ = | 257 *bold_font_ = |
| 209 base_font_->DeriveFont(0, base_font_->GetStyle() | gfx::Font::BOLD); | 258 base_font_->DeriveFont(0, base_font_->GetStyle() | gfx::Font::BOLD); |
| 210 | 259 |
| 211 small_font_.reset(new gfx::Font()); | 260 small_font_.reset(new gfx::Font()); |
| 212 *small_font_ = base_font_->DeriveFont(kSmallFontSizeDelta); | 261 *small_font_ = base_font_->DeriveFont(kSmallFontSizeDelta); |
| 213 | 262 |
| 214 medium_font_.reset(new gfx::Font()); | 263 medium_font_.reset(new gfx::Font()); |
| 215 *medium_font_ = base_font_->DeriveFont(kMediumFontSizeDelta); | 264 *medium_font_ = base_font_->DeriveFont(kMediumFontSizeDelta); |
| 216 | 265 |
| 217 medium_bold_font_.reset(new gfx::Font()); | 266 medium_bold_font_.reset(new gfx::Font()); |
| 218 *medium_bold_font_ = | 267 *medium_bold_font_ = |
| 219 base_font_->DeriveFont(kMediumFontSizeDelta, | 268 base_font_->DeriveFont(kMediumFontSizeDelta, |
| 220 base_font_->GetStyle() | gfx::Font::BOLD); | 269 base_font_->GetStyle() | gfx::Font::BOLD); |
| 221 | 270 |
| 222 large_font_.reset(new gfx::Font()); | 271 large_font_.reset(new gfx::Font()); |
| 223 *large_font_ = base_font_->DeriveFont(kLargeFontSizeDelta); | 272 *large_font_ = base_font_->DeriveFont(kLargeFontSizeDelta); |
| 224 } | 273 } |
| 225 } | 274 } |
| 226 | 275 |
| 227 /* static */ | 276 /* static */ |
| 228 SkBitmap* ResourceBundle::LoadBitmap(DataHandle data_handle, int resource_id) { | 277 bool ResourceBundle::LoadBitmaps(DataHandle data_handle, int resource_id, |
| 278 std::vector<SkBitmap>& bitmaps) { |
| 229 scoped_refptr<RefCountedMemory> memory( | 279 scoped_refptr<RefCountedMemory> memory( |
| 230 LoadResourceBytes(data_handle, resource_id)); | 280 LoadResourceBytes(data_handle, resource_id)); |
| 231 if (!memory) | 281 if (!memory) |
| 232 return NULL; | 282 return false; |
| 233 | 283 |
| 234 SkBitmap bitmap; | 284 SkBitmap bitmap; |
| 235 if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) { | 285 if (gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) { |
| 236 NOTREACHED() << "Unable to decode theme image resource " << resource_id; | 286 bitmaps.push_back(bitmap); |
| 237 return NULL; | 287 return true; |
| 238 } | 288 } |
| 239 | 289 |
| 240 return new SkBitmap(bitmap); | 290 if (gfx::TIFFCodec::Decode(memory->front(), memory->size(), bitmaps)) { |
| 291 return true; |
| 292 } |
| 293 |
| 294 NOTREACHED() << "Unable to decode theme image resource " << resource_id; |
| 295 return false; |
| 241 } | 296 } |
| 242 | 297 |
| 243 gfx::Image* ResourceBundle::GetEmptyImage() { | 298 gfx::Image* ResourceBundle::GetEmptyImage() { |
| 244 base::AutoLock lock(*lock_); | 299 base::AutoLock lock(*lock_); |
| 245 | 300 |
| 246 static gfx::Image* empty_image = NULL; | 301 static gfx::Image* empty_image = NULL; |
| 247 if (!empty_image) { | 302 if (!empty_image) { |
| 248 // The placeholder bitmap is bright red so people notice the problem. | 303 // The placeholder bitmap is bright red so people notice the problem. |
| 249 // This bitmap will be leaked, but this code should never be hit. | 304 // This bitmap will be leaked, but this code should never be hit. |
| 250 SkBitmap* bitmap = new SkBitmap(); | 305 SkBitmap* bitmap = new SkBitmap(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 280 int resource_id, base::StringPiece* data) const { | 335 int resource_id, base::StringPiece* data) const { |
| 281 return data_pack_->GetStringPiece(static_cast<uint32>(resource_id), data); | 336 return data_pack_->GetStringPiece(static_cast<uint32>(resource_id), data); |
| 282 } | 337 } |
| 283 | 338 |
| 284 RefCountedStaticMemory* ResourceBundle::LoadedDataPack::GetStaticMemory( | 339 RefCountedStaticMemory* ResourceBundle::LoadedDataPack::GetStaticMemory( |
| 285 int resource_id) const { | 340 int resource_id) const { |
| 286 return data_pack_->GetStaticMemory(resource_id); | 341 return data_pack_->GetStaticMemory(resource_id); |
| 287 } | 342 } |
| 288 | 343 |
| 289 } // namespace ui | 344 } // namespace ui |
| OLD | NEW |