OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "chrome/common/resource_bundle.h" | 5 #include "chrome/common/resource_bundle.h" |
6 | 6 |
7 #if defined(TOOLKIT_GTK) | 7 #if defined(TOOLKIT_GTK) |
8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
9 #endif | 9 #endif |
10 | 10 |
11 #include "base/base_paths.h" | 11 #include "base/base_paths.h" |
12 #include "base/data_pack.h" | 12 #include "base/data_pack.h" |
13 #include "base/file_path.h" | 13 #include "base/file_path.h" |
14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
15 #include "base/gfx/gtk_util.h" | |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "base/path_service.h" | 17 #include "base/path_service.h" |
17 #include "base/string_piece.h" | 18 #include "base/string_piece.h" |
18 #include "base/string_util.h" | 19 #include "base/string_util.h" |
19 #include "chrome/common/chrome_paths.h" | 20 #include "chrome/common/chrome_paths.h" |
20 #include "chrome/common/gfx/chrome_font.h" | 21 #include "chrome/common/gfx/chrome_font.h" |
21 #include "chrome/common/l10n_util.h" | 22 #include "chrome/common/l10n_util.h" |
23 #include "SkBitmap.h" | |
24 | |
25 namespace { | |
26 | |
27 #if defined(TOOLKIT_GTK) | |
28 // Convert the raw image data into a GdkPixbuf. The GdkPixbuf that is returned | |
29 // has a ref count of 1 so the caller must call g_object_unref to free the | |
30 // memory. | |
31 GdkPixbuf* LoadPixbuf(std::vector<unsigned char>& data) { | |
32 GdkPixbufLoader* loader = gdk_pixbuf_loader_new(); | |
33 bool ok = gdk_pixbuf_loader_write(loader, static_cast<guint8*>(data.data()), | |
34 data.size(), NULL); | |
35 if (!ok) | |
36 return NULL; | |
Dean McNamee
2009/04/15 19:58:17
we'll leak the loader, but I guess I'm ok w/ that.
| |
37 // Calling gdk_pixbuf_loader_close forces the data to be parsed by the | |
38 // loader. We must do this before calling gdk_pixbuf_loader_get_pixbuf. | |
39 ok = gdk_pixbuf_loader_close(loader, NULL); | |
40 if (!ok) | |
41 return NULL; | |
42 GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); | |
43 if (!pixbuf) | |
44 return NULL; | |
45 | |
46 // The pixbuf is owned by the loader, so add a ref so when we delete the | |
47 // loader, the pixbuf still exists. | |
48 g_object_ref(pixbuf); | |
49 g_object_unref(loader); | |
50 | |
51 return pixbuf; | |
52 } | |
53 #endif | |
54 | |
55 } // namespace | |
22 | 56 |
23 ResourceBundle::~ResourceBundle() { | 57 ResourceBundle::~ResourceBundle() { |
24 FreeImages(); | 58 FreeImages(); |
59 // Free GdkPixbufs. | |
60 for (GdkPixbufMap::iterator i = gdk_pixbufs_.begin(); | |
61 i != gdk_pixbufs_.end(); i++) { | |
62 g_object_unref(i->second); | |
63 } | |
64 gdk_pixbufs_.clear(); | |
25 | 65 |
26 delete locale_resources_data_; | 66 delete locale_resources_data_; |
27 locale_resources_data_ = NULL; | 67 locale_resources_data_ = NULL; |
28 delete theme_data_; | 68 delete theme_data_; |
29 theme_data_ = NULL; | 69 theme_data_ = NULL; |
30 delete resources_data_; | 70 delete resources_data_; |
31 resources_data_ = NULL; | 71 resources_data_ = NULL; |
32 } | 72 } |
33 | 73 |
34 void ResourceBundle::LoadResources(const std::wstring& pref_locale) { | 74 void ResourceBundle::LoadResources(const std::wstring& pref_locale) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 } | 156 } |
117 } | 157 } |
118 | 158 |
119 // Data pack encodes strings as UTF16. | 159 // Data pack encodes strings as UTF16. |
120 string16 msg(reinterpret_cast<const char16*>(data.data()), | 160 string16 msg(reinterpret_cast<const char16*>(data.data()), |
121 data.length() / 2); | 161 data.length() / 2); |
122 return msg; | 162 return msg; |
123 } | 163 } |
124 | 164 |
125 #if defined(TOOLKIT_GTK) | 165 #if defined(TOOLKIT_GTK) |
126 GdkPixbuf* ResourceBundle::LoadPixbuf(int resource_id) { | 166 GdkPixbuf* ResourceBundle::GetPixbufNamed(int resource_id) { |
127 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 167 // Check to see if we already have the pixbuf in the cache. |
168 { | |
169 AutoLock lock_scope(lock_); | |
170 GdkPixbufMap::const_iterator found = gdk_pixbufs_.find(resource_id); | |
171 if (found != gdk_pixbufs_.end()) | |
172 return found->second; | |
173 } | |
174 | |
175 | |
128 std::vector<unsigned char> data; | 176 std::vector<unsigned char> data; |
129 rb.LoadImageResourceBytes(resource_id, &data); | 177 LoadImageResourceBytes(resource_id, &data); |
178 GdkPixbuf* pixbuf = LoadPixbuf(data); | |
130 | 179 |
131 GdkPixbufLoader* loader = gdk_pixbuf_loader_new(); | 180 // We loaded successfully. Cache the pixbuf. |
132 bool ok = gdk_pixbuf_loader_write(loader, static_cast<guint8*>(data.data()), | 181 if (pixbuf) { |
133 data.size(), NULL); | 182 AutoLock lock_scope(lock_); |
134 DCHECK(ok) << "failed to write " << resource_id; | |
135 // Calling gdk_pixbuf_loader_close forces the data to be parsed by the | |
136 // loader. We must do this before calling gdk_pixbuf_loader_get_pixbuf. | |
137 ok = gdk_pixbuf_loader_close(loader, NULL); | |
138 DCHECK(ok) << "close failed " << resource_id; | |
139 GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); | |
140 DCHECK(pixbuf) << "failed to load " << resource_id << " " << data.size(); | |
141 | 183 |
142 // The pixbuf is owned by the loader, so add a ref so when we delete the | 184 // Another thread raced us, and has already cached the pixbuf. |
143 // loader, the pixbuf still exists. | 185 if (gdk_pixbufs_.count(resource_id)) { |
144 g_object_ref(pixbuf); | 186 g_object_unref(pixbuf); |
145 g_object_unref(loader); | 187 return gdk_pixbufs_[resource_id]; |
188 } | |
146 | 189 |
147 return pixbuf; | 190 gdk_pixbufs_[resource_id] = pixbuf; |
191 return pixbuf; | |
192 } | |
193 | |
194 // We failed to retrieve the bitmap, show a debugging red square. | |
195 { | |
196 LOG(WARNING) << "Unable to load GdkPixbuf with id " << resource_id; | |
197 NOTREACHED(); // Want to assert in debug mode. | |
198 | |
199 AutoLock lock_scope(lock_); // Guard empty_bitmap initialization. | |
200 | |
201 static GdkPixbuf* empty_bitmap = NULL; | |
202 if (!empty_bitmap) { | |
203 // The placeholder bitmap is bright red so people notice the problem. | |
204 // This bitmap will be leaked, but this code should never be hit. | |
205 scoped_ptr<SkBitmap> skia_bitmap(new SkBitmap()); | |
206 skia_bitmap->setConfig(SkBitmap::kARGB_8888_Config, 32, 32); | |
207 skia_bitmap->allocPixels(); | |
208 skia_bitmap->eraseARGB(255, 255, 0, 0); | |
209 empty_bitmap = gfx::GdkPixbufFromSkBitmap(skia_bitmap.get()); | |
210 } | |
211 return empty_bitmap; | |
212 } | |
148 } | 213 } |
149 #endif | 214 #endif |
OLD | NEW |