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.
5 #include "content/browser/android/system_ui_resource_manager_impl.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"
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);
31 paint
.setAntiAlias(true);
33 paint
.setStyle(SkPaint::kFill_Style
);
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
);
43 if (!glow_bitmap
.allocPixels(
44 SkImageInfo::MakeA8(bounds
.width(), bounds
.height()))) {
45 LOG(FATAL
) << " Failed to allocate bitmap of size " << bounds
.width() << "x"
48 glow_bitmap
.eraseColor(SK_ColorTRANSPARENT
);
50 SkCanvas
canvas(glow_bitmap
);
51 canvas
.clipRect(SkRect::MakeXYWH(0, 0, bounds
.width(), bounds
.height()));
52 canvas
.drawArc(arc_rect
, 45, 90, true, paint
);
56 void LoadBitmap(ui::SystemUIResourceManager::ResourceType type
,
57 SkBitmap
* bitmap_holder
,
58 const gfx::Size
& screen_size
) {
60 "browser", "SystemUIResourceManagerImpl::LoadBitmap", "type", type
);
63 case ui::SystemUIResourceManager::OVERSCROLL_EDGE
:
64 bitmap
= gfx::CreateSkBitmapFromAndroidResource(
65 "android:drawable/overscroll_edge", gfx::Size(128, 12));
67 case ui::SystemUIResourceManager::OVERSCROLL_GLOW
:
68 bitmap
= gfx::CreateSkBitmapFromAndroidResource(
69 "android:drawable/overscroll_glow", gfx::Size(128, 64));
71 case ui::SystemUIResourceManager::OVERSCROLL_GLOW_L
:
72 bitmap
= CreateOverscrollGlowLBitmap(screen_size
);
75 bitmap
.setImmutable();
76 *bitmap_holder
= bitmap
;
81 class SystemUIResourceManagerImpl::Entry
82 : public content::UIResourceClientAndroid
{
84 explicit Entry(UIResourceProvider
* provider
) : id_(0), provider_(provider
) {
90 provider_
->DeleteUIResource(id_
);
94 void SetBitmap(const SkBitmap
& bitmap
) {
95 DCHECK(!bitmap
.empty());
96 DCHECK(bitmap_
.empty());
101 cc::UIResourceId
GetUIResourceId() {
105 id_
= provider_
->CreateUIResource(this);
109 // content::UIResourceClient implementation.
110 virtual cc::UIResourceBitmap
GetBitmap(cc::UIResourceId uid
,
111 bool resource_lost
) OVERRIDE
{
112 DCHECK(!bitmap_
.empty());
113 return cc::UIResourceBitmap(bitmap_
);
116 // content::UIResourceClientAndroid implementation.
117 virtual void UIResourceIsInvalid() OVERRIDE
{ id_
= 0; }
119 const SkBitmap
& bitmap() const { return bitmap_
; }
123 cc::UIResourceId id_
;
124 UIResourceProvider
* provider_
;
126 DISALLOW_COPY_AND_ASSIGN(Entry
);
129 SystemUIResourceManagerImpl::SystemUIResourceManagerImpl(
130 UIResourceProvider
* ui_resource_provider
)
131 : ui_resource_provider_(ui_resource_provider
), weak_factory_(this) {
134 SystemUIResourceManagerImpl::~SystemUIResourceManagerImpl() {
137 void SystemUIResourceManagerImpl::PreloadResource(ResourceType type
) {
141 cc::UIResourceId
SystemUIResourceManagerImpl::GetUIResourceId(
143 return GetEntry(type
)->GetUIResourceId();
146 SystemUIResourceManagerImpl::Entry
* SystemUIResourceManagerImpl::GetEntry(
148 DCHECK_GE(type
, RESOURCE_TYPE_FIRST
);
149 DCHECK_LE(type
, RESOURCE_TYPE_LAST
);
150 if (!resource_map_
[type
]) {
151 resource_map_
[type
].reset(new Entry(ui_resource_provider_
));
152 // Lazily build the resource.
155 return resource_map_
[type
].get();
158 void SystemUIResourceManagerImpl::BuildResource(ResourceType type
) {
159 DCHECK(GetEntry(type
)->bitmap().empty());
161 // Instead of blocking the main thread, we post a task to load the bitmap.
162 SkBitmap
* bitmap
= new SkBitmap();
163 gfx::Size screen_size
=
164 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().GetSizeInPixel();
165 base::Closure load_bitmap
=
166 base::Bind(&LoadBitmap
, type
, bitmap
, screen_size
);
167 base::Closure finished_load
=
168 base::Bind(&SystemUIResourceManagerImpl::OnFinishedLoadBitmap
,
169 weak_factory_
.GetWeakPtr(),
171 base::Owned(bitmap
));
172 base::WorkerPool::PostTaskAndReply(
173 FROM_HERE
, load_bitmap
, finished_load
, true);
176 void SystemUIResourceManagerImpl::OnFinishedLoadBitmap(
178 SkBitmap
* bitmap_holder
) {
179 DCHECK(bitmap_holder
);
180 GetEntry(type
)->SetBitmap(*bitmap_holder
);
183 } // namespace content