diff options
Diffstat (limited to 'ui/base/resource/resource_bundle_linux.cc')
-rw-r--r-- | ui/base/resource/resource_bundle_linux.cc | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/ui/base/resource/resource_bundle_linux.cc b/ui/base/resource/resource_bundle_linux.cc new file mode 100644 index 0000000..92a39df --- /dev/null +++ b/ui/base/resource/resource_bundle_linux.cc @@ -0,0 +1,148 @@ +// Copyright (c) 2011 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 "ui/base/resource/resource_bundle.h" + +#include <gtk/gtk.h> + +#include "base/base_paths.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/i18n/rtl.h" +#include "base/lock.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/string_piece.h" +#include "base/string_util.h" +#include "gfx/font.h" +#include "gfx/gtk_util.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/ui_base_paths.h" + +namespace ui { + +namespace { + +// Convert the raw image data into a GdkPixbuf. The GdkPixbuf that is returned +// has a ref count of 1 so the caller must call g_object_unref to free the +// memory. +GdkPixbuf* LoadPixbuf(RefCountedStaticMemory* data, bool rtl_enabled) { + ScopedGObject<GdkPixbufLoader>::Type loader(gdk_pixbuf_loader_new()); + bool ok = data && gdk_pixbuf_loader_write(loader.get(), + reinterpret_cast<const guint8*>(data->front()), data->size(), NULL); + if (!ok) + return NULL; + // Calling gdk_pixbuf_loader_close forces the data to be parsed by the + // loader. We must do this before calling gdk_pixbuf_loader_get_pixbuf. + ok = gdk_pixbuf_loader_close(loader.get(), NULL); + if (!ok) + return NULL; + GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf(loader.get()); + if (!pixbuf) + return NULL; + + if (base::i18n::IsRTL() && rtl_enabled) { + // |pixbuf| will get unreffed and destroyed (see below). The returned value + // has ref count 1. + return gdk_pixbuf_flip(pixbuf, TRUE); + } else { + // The pixbuf is owned by the loader, so add a ref so when we delete the + // loader (when the ScopedGObject goes out of scope), the pixbuf still + // exists. + g_object_ref(pixbuf); + return pixbuf; + } +} + +} // namespace + +void ResourceBundle::FreeGdkPixBufs() { + for (GdkPixbufMap::iterator i = gdk_pixbufs_.begin(); + i != gdk_pixbufs_.end(); i++) { + g_object_unref(i->second); + } + gdk_pixbufs_.clear(); +} + +// static +FilePath ResourceBundle::GetResourcesFilePath() { + FilePath resources_file_path; + PathService::Get(ui::FILE_RESOURCES_PAK, &resources_file_path); + return resources_file_path; +} + +// static +FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale) { + FilePath locale_file_path; + PathService::Get(ui::DIR_LOCALES, &locale_file_path); + if (locale_file_path.empty()) + return locale_file_path; + if (app_locale.empty()) + return FilePath(); + locale_file_path = locale_file_path.AppendASCII(app_locale + ".pak"); + if (!file_util::PathExists(locale_file_path)) + return FilePath(); + return locale_file_path; +} + +GdkPixbuf* ResourceBundle::GetPixbufImpl(int resource_id, bool rtl_enabled) { + // Use the negative |resource_id| for the key for BIDI-aware images. + int key = rtl_enabled ? -resource_id : resource_id; + + // Check to see if we already have the pixbuf in the cache. + { + AutoLock lock_scope(*lock_); + GdkPixbufMap::const_iterator found = gdk_pixbufs_.find(key); + if (found != gdk_pixbufs_.end()) + return found->second; + } + + scoped_refptr<RefCountedStaticMemory> data( + LoadDataResourceBytes(resource_id)); + GdkPixbuf* pixbuf = LoadPixbuf(data.get(), rtl_enabled); + + // We loaded successfully. Cache the pixbuf. + if (pixbuf) { + AutoLock lock_scope(*lock_); + + // Another thread raced us, and has already cached the pixbuf. + if (gdk_pixbufs_.count(key)) { + g_object_unref(pixbuf); + return gdk_pixbufs_[key]; + } + + gdk_pixbufs_[key] = pixbuf; + return pixbuf; + } + + // We failed to retrieve the bitmap, show a debugging red square. + { + LOG(WARNING) << "Unable to load GdkPixbuf with id " << resource_id; + NOTREACHED(); // Want to assert in debug mode. + + AutoLock lock_scope(*lock_); // Guard empty_bitmap initialization. + + static GdkPixbuf* 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. + scoped_ptr<SkBitmap> skia_bitmap(new SkBitmap()); + skia_bitmap->setConfig(SkBitmap::kARGB_8888_Config, 32, 32); + skia_bitmap->allocPixels(); + skia_bitmap->eraseARGB(255, 255, 0, 0); + empty_bitmap = gfx::GdkPixbufFromSkBitmap(skia_bitmap.get()); + } + return empty_bitmap; + } +} + +GdkPixbuf* ResourceBundle::GetPixbufNamed(int resource_id) { + return GetPixbufImpl(resource_id, false); +} + +GdkPixbuf* ResourceBundle::GetRTLEnabledPixbufNamed(int resource_id) { + return GetPixbufImpl(resource_id, true); +} + +} // namespace ui |