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 |