Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ui / base / resource / resource_bundle_gtk.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/base/resource/resource_bundle.h"
6
7 #include "base/i18n/rtl.h"
8 #include "base/logging.h"
9 #include "base/memory/ref_counted_memory.h"
10 #include "base/path_service.h"
11 #include "base/synchronization/lock.h"
12 #include "third_party/skia/include/core/SkBitmap.h"
13 #include "ui/base/layout.h"
14 #include "ui/base/resource/resource_handle.h"
15 #include "ui/base/ui_base_paths.h"
16 #include "ui/gfx/image/image.h"
17 #include "ui/gfx/scoped_gobject.h"
18
19 #include <gtk/gtk.h>
20
21 namespace ui {
22
23 namespace {
24
25 // Convert the raw image data into a GdkPixbuf.  The GdkPixbuf that is returned
26 // has a ref count of 1 so the caller must call g_object_unref to free the
27 // memory.
28 GdkPixbuf* LoadPixbuf(base::RefCountedStaticMemory* data, bool rtl_enabled) {
29   ScopedGObject<GdkPixbufLoader>::Type loader(gdk_pixbuf_loader_new());
30   bool ok = data && gdk_pixbuf_loader_write(loader.get(),
31       data->front_as<guint8>(), data->size(), NULL);
32   if (!ok)
33     return NULL;
34   // Calling gdk_pixbuf_loader_close forces the data to be parsed by the
35   // loader.  We must do this before calling gdk_pixbuf_loader_get_pixbuf.
36   ok = gdk_pixbuf_loader_close(loader.get(), NULL);
37   if (!ok)
38     return NULL;
39   GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf(loader.get());
40   if (!pixbuf)
41     return NULL;
42
43   if (base::i18n::IsRTL() && rtl_enabled) {
44     // |pixbuf| will get unreffed and destroyed (see below). The returned value
45     // has ref count 1.
46     return gdk_pixbuf_flip(pixbuf, TRUE);
47   } else {
48     // The pixbuf is owned by the loader, so add a ref so when we delete the
49     // loader (when the ScopedGObject goes out of scope), the pixbuf still
50     // exists.
51     g_object_ref(pixbuf);
52     return pixbuf;
53   }
54 }
55
56 base::FilePath GetResourcesPakFilePath(const std::string& pak_name) {
57   base::FilePath path;
58   if (PathService::Get(base::DIR_MODULE, &path))
59     return path.AppendASCII(pak_name.c_str());
60
61   // Return just the name of the pack file.
62   return base::FilePath(pak_name.c_str());
63 }
64
65 }  // namespace
66
67 void ResourceBundle::LoadCommonResources() {
68   AddDataPackFromPath(GetResourcesPakFilePath(
69                       "chrome_100_percent.pak"),
70                       SCALE_FACTOR_100P);
71 }
72
73 gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) {
74   // Use the negative |resource_id| for the key for BIDI-aware images.
75   int key = rtl == RTL_ENABLED ? -resource_id : resource_id;
76
77   // Check to see if the image is already in the cache.
78   {
79     base::AutoLock lock_scope(*images_and_fonts_lock_);
80     if (images_.count(key))
81       return images_[key];
82   }
83
84   gfx::Image image;
85   if (delegate_)
86     image = delegate_->GetNativeImageNamed(resource_id, rtl);
87
88   if (image.IsEmpty()) {
89     scoped_refptr<base::RefCountedStaticMemory> data(
90         LoadDataResourceBytesForScale(resource_id, SCALE_FACTOR_100P));
91     GdkPixbuf* pixbuf = LoadPixbuf(data.get(), rtl == RTL_ENABLED);
92
93     if (!pixbuf) {
94       LOG(WARNING) << "Unable to load pixbuf with id " << resource_id;
95       NOTREACHED();  // Want to assert in debug mode.
96       return GetEmptyImage();
97     }
98
99     image = gfx::Image(pixbuf);  // Takes ownership.
100   }
101
102   base::AutoLock lock_scope(*images_and_fonts_lock_);
103
104   // Another thread raced the load and has already cached the image.
105   if (images_.count(key))
106     return images_[key];
107
108   images_[key] = image;
109   return images_[key];
110 }
111
112 }  // namespace ui