Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / android / system_ui_resource_manager_impl.cc
1 // Copyright 2014 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 "content/browser/android/system_ui_resource_manager_impl.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/debug/trace_event.h"
10 #include "base/location.h"
11 #include "base/observer_list.h"
12 #include "base/threading/worker_pool.h"
13 #include "cc/resources/ui_resource_bitmap.h"
14 #include "content/public/browser/android/ui_resource_client_android.h"
15 #include "content/public/browser/android/ui_resource_provider.h"
16 #include "third_party/skia/include/core/SkBitmap.h"
17 #include "third_party/skia/include/core/SkCanvas.h"
18 #include "third_party/skia/include/core/SkPaint.h"
19 #include "third_party/skia/include/effects/SkPorterDuff.h"
20 #include "ui/gfx/android/java_bitmap.h"
21 #include "ui/gfx/screen.h"
22
23 namespace content {
24 namespace {
25
26 SkBitmap CreateOverscrollGlowLBitmap(const gfx::Size& screen_size) {
27   const float kSin = 0.5f;    // sin(PI / 6)
28   const float kCos = 0.866f;  // cos(PI / 6);
29
30   SkPaint paint;
31   paint.setAntiAlias(true);
32   paint.setAlpha(0x33);
33   paint.setStyle(SkPaint::kFill_Style);
34
35   const float arc_width =
36       std::min(screen_size.width(), screen_size.height()) * 0.5f / kSin;
37   const float y = kCos * arc_width;
38   const float height = arc_width - y;
39   gfx::Size bounds(arc_width, height);
40   SkRect arc_rect = SkRect::MakeXYWH(
41       -arc_width / 2.f, -arc_width - y, arc_width * 2.f, arc_width * 2.f);
42   SkBitmap glow_bitmap;
43   if (!glow_bitmap.allocPixels(
44           SkImageInfo::MakeA8(bounds.width(), bounds.height()))) {
45     LOG(FATAL) << " Failed to allocate bitmap of size " << bounds.width() << "x"
46                << bounds.height();
47   }
48
49   SkCanvas canvas(glow_bitmap);
50   canvas.clipRect(SkRect::MakeXYWH(0, 0, bounds.width(), bounds.height()));
51   canvas.drawArc(arc_rect, 45, 90, true, paint);
52   return glow_bitmap;
53 }
54
55 void LoadBitmap(ui::SystemUIResourceManager::ResourceType type,
56                 SkBitmap* bitmap_holder,
57                 const gfx::Size& screen_size) {
58   TRACE_EVENT1(
59       "browser", "SystemUIResourceManagerImpl::LoadBitmap", "type", type);
60   SkBitmap bitmap;
61   switch (type) {
62     case ui::SystemUIResourceManager::OVERSCROLL_EDGE:
63       bitmap = gfx::CreateSkBitmapFromAndroidResource(
64           "android:drawable/overscroll_edge", gfx::Size(128, 12));
65       break;
66     case ui::SystemUIResourceManager::OVERSCROLL_GLOW:
67       bitmap = gfx::CreateSkBitmapFromAndroidResource(
68           "android:drawable/overscroll_glow", gfx::Size(128, 64));
69       break;
70     case ui::SystemUIResourceManager::OVERSCROLL_GLOW_L:
71       bitmap = CreateOverscrollGlowLBitmap(screen_size);
72       break;
73   }
74   bitmap.setImmutable();
75   *bitmap_holder = bitmap;
76 }
77
78 }  // namespace
79
80 class SystemUIResourceManagerImpl::Entry
81     : public content::UIResourceClientAndroid {
82  public:
83   explicit Entry(UIResourceProvider* provider) : id_(0), provider_(provider) {
84     DCHECK(provider);
85   }
86
87   virtual ~Entry() {
88     if (id_)
89       provider_->DeleteUIResource(id_);
90     id_ = 0;
91   }
92
93   void SetBitmap(const SkBitmap& bitmap) {
94     DCHECK(!bitmap.empty());
95     DCHECK(bitmap_.empty());
96     DCHECK(!id_);
97     bitmap_ = bitmap;
98   }
99
100   cc::UIResourceId GetUIResourceId() {
101     if (bitmap_.empty())
102       return 0;
103     if (!id_)
104       id_ = provider_->CreateUIResource(this);
105     return id_;
106   }
107
108   // content::UIResourceClient implementation.
109   virtual cc::UIResourceBitmap GetBitmap(cc::UIResourceId uid,
110                                          bool resource_lost) OVERRIDE {
111     DCHECK(!bitmap_.empty());
112     return cc::UIResourceBitmap(bitmap_);
113   }
114
115   // content::UIResourceClientAndroid implementation.
116   virtual void UIResourceIsInvalid() OVERRIDE { id_ = 0; }
117
118   const SkBitmap& bitmap() const { return bitmap_; }
119
120  private:
121   SkBitmap bitmap_;
122   cc::UIResourceId id_;
123   UIResourceProvider* provider_;
124
125   DISALLOW_COPY_AND_ASSIGN(Entry);
126 };
127
128 SystemUIResourceManagerImpl::SystemUIResourceManagerImpl(
129     UIResourceProvider* ui_resource_provider)
130     : ui_resource_provider_(ui_resource_provider), weak_factory_(this) {
131 }
132
133 SystemUIResourceManagerImpl::~SystemUIResourceManagerImpl() {
134 }
135
136 void SystemUIResourceManagerImpl::PreloadResource(ResourceType type) {
137   GetEntry(type);
138 }
139
140 cc::UIResourceId SystemUIResourceManagerImpl::GetUIResourceId(
141     ResourceType type) {
142   return GetEntry(type)->GetUIResourceId();
143 }
144
145 SystemUIResourceManagerImpl::Entry* SystemUIResourceManagerImpl::GetEntry(
146     ResourceType type) {
147   DCHECK_GE(type, RESOURCE_TYPE_FIRST);
148   DCHECK_LE(type, RESOURCE_TYPE_LAST);
149   if (!resource_map_[type]) {
150     resource_map_[type].reset(new Entry(ui_resource_provider_));
151     // Lazily build the resource.
152     BuildResource(type);
153   }
154   return resource_map_[type].get();
155 }
156
157 void SystemUIResourceManagerImpl::BuildResource(ResourceType type) {
158   DCHECK(GetEntry(type)->bitmap().empty());
159
160   // Instead of blocking the main thread, we post a task to load the bitmap.
161   SkBitmap* bitmap = new SkBitmap();
162   gfx::Size screen_size =
163       gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().GetSizeInPixel();
164   base::Closure load_bitmap =
165       base::Bind(&LoadBitmap, type, bitmap, screen_size);
166   base::Closure finished_load =
167       base::Bind(&SystemUIResourceManagerImpl::OnFinishedLoadBitmap,
168                  weak_factory_.GetWeakPtr(),
169                  type,
170                  base::Owned(bitmap));
171   base::WorkerPool::PostTaskAndReply(
172       FROM_HERE, load_bitmap, finished_load, true);
173 }
174
175 void SystemUIResourceManagerImpl::OnFinishedLoadBitmap(
176     ResourceType type,
177     SkBitmap* bitmap_holder) {
178   DCHECK(bitmap_holder);
179   GetEntry(type)->SetBitmap(*bitmap_holder);
180 }
181
182 }  // namespace content