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 "jni/UIResources_jni.h"
17 #include "skia/ext/image_operations.h"
18 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "third_party/skia/include/core/SkCanvas.h"
20 #include "third_party/skia/include/core/SkPaint.h"
21 #include "ui/gfx/android/java_bitmap.h"
22 #include "ui/gfx/screen.h"
27 SkBitmap
CreateOverscrollGlowLBitmap(const gfx::Size
& screen_size
) {
28 const float kSin
= 0.5f
; // sin(PI / 6)
29 const float kCos
= 0.866f
; // cos(PI / 6);
32 paint
.setAntiAlias(true);
34 paint
.setStyle(SkPaint::kFill_Style
);
36 const float arc_width
=
37 std::min(screen_size
.width(), screen_size
.height()) * 0.5f
/ kSin
;
38 const float y
= kCos
* arc_width
;
39 const float height
= arc_width
- y
;
40 gfx::Size
bounds(arc_width
, height
);
41 SkRect arc_rect
= SkRect::MakeXYWH(
42 -arc_width
/ 2.f
, -arc_width
- y
, arc_width
* 2.f
, arc_width
* 2.f
);
44 glow_bitmap
.allocPixels(SkImageInfo::MakeA8(bounds
.width(), bounds
.height()));
45 glow_bitmap
.eraseColor(SK_ColorTRANSPARENT
);
47 SkCanvas
canvas(glow_bitmap
);
48 canvas
.clipRect(SkRect::MakeXYWH(0, 0, bounds
.width(), bounds
.height()));
49 canvas
.drawArc(arc_rect
, 45, 90, true, paint
);
53 SkBitmap
LoadJavaBitmap(ui::SystemUIResourceType type
, const gfx::Size
& size
) {
54 ScopedJavaLocalRef
<jobject
> jobj
=
55 Java_UIResources_getBitmap(base::android::AttachCurrentThread(),
56 base::android::GetApplicationContext(), type
,
57 size
.width(), size
.height());
61 SkBitmap bitmap
= CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jobj
.obj()));
68 return skia::ImageOperations::Resize(
69 bitmap
, skia::ImageOperations::RESIZE_BOX
, size
.width(), size
.height());
72 void LoadBitmap(ui::SystemUIResourceType type
,
73 SkBitmap
* bitmap_holder
,
74 const gfx::Size
& screen_size
) {
76 "browser", "SystemUIResourceManagerImpl::LoadBitmap", "type", type
);
79 case ui::OVERSCROLL_EDGE
:
80 bitmap
= LoadJavaBitmap(type
, gfx::Size(128, 12));
82 case ui::OVERSCROLL_GLOW
:
83 bitmap
= LoadJavaBitmap(type
, gfx::Size(128, 64));
85 case ui::OVERSCROLL_GLOW_L
:
86 bitmap
= CreateOverscrollGlowLBitmap(screen_size
);
88 case ui::OVERSCROLL_REFRESH_IDLE
:
89 case ui::OVERSCROLL_REFRESH_ACTIVE
:
90 bitmap
= LoadJavaBitmap(type
, gfx::Size());
93 bitmap
.setImmutable();
94 *bitmap_holder
= bitmap
;
99 class SystemUIResourceManagerImpl::Entry
100 : public content::UIResourceClientAndroid
{
102 explicit Entry(UIResourceProvider
* provider
) : id_(0), provider_(provider
) {
108 provider_
->DeleteUIResource(id_
);
112 void SetBitmap(const SkBitmap
& bitmap
) {
113 DCHECK(!bitmap
.empty());
114 DCHECK(bitmap_
.empty());
119 cc::UIResourceId
GetUIResourceId() {
123 id_
= provider_
->CreateUIResource(this);
127 // content::UIResourceClient implementation.
128 cc::UIResourceBitmap
GetBitmap(cc::UIResourceId uid
,
129 bool resource_lost
) override
{
130 DCHECK(!bitmap_
.empty());
131 return cc::UIResourceBitmap(bitmap_
);
134 // content::UIResourceClientAndroid implementation.
135 void UIResourceIsInvalid() override
{ id_
= 0; }
137 const SkBitmap
& bitmap() const { return bitmap_
; }
141 cc::UIResourceId id_
;
142 UIResourceProvider
* provider_
;
144 DISALLOW_COPY_AND_ASSIGN(Entry
);
147 SystemUIResourceManagerImpl::SystemUIResourceManagerImpl(
148 UIResourceProvider
* ui_resource_provider
)
149 : ui_resource_provider_(ui_resource_provider
), weak_factory_(this) {
152 SystemUIResourceManagerImpl::~SystemUIResourceManagerImpl() {
155 void SystemUIResourceManagerImpl::PreloadResource(
156 ui::SystemUIResourceType type
) {
160 cc::UIResourceId
SystemUIResourceManagerImpl::GetUIResourceId(
161 ui::SystemUIResourceType type
) {
162 return GetEntry(type
)->GetUIResourceId();
165 SystemUIResourceManagerImpl::Entry
* SystemUIResourceManagerImpl::GetEntry(
166 ui::SystemUIResourceType type
) {
167 DCHECK_GE(type
, ui::SYSTEM_UI_RESOURCE_TYPE_FIRST
);
168 DCHECK_LE(type
, ui::SYSTEM_UI_RESOURCE_TYPE_LAST
);
169 if (!resource_map_
[type
]) {
170 resource_map_
[type
].reset(new Entry(ui_resource_provider_
));
171 // Lazily build the resource.
174 return resource_map_
[type
].get();
177 void SystemUIResourceManagerImpl::BuildResource(ui::SystemUIResourceType type
) {
178 DCHECK(GetEntry(type
)->bitmap().empty());
180 // Instead of blocking the main thread, we post a task to load the bitmap.
181 SkBitmap
* bitmap
= new SkBitmap();
182 gfx::Size screen_size
=
183 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().GetSizeInPixel();
184 base::Closure load_bitmap
=
185 base::Bind(&LoadBitmap
, type
, bitmap
, screen_size
);
186 base::Closure finished_load
=
187 base::Bind(&SystemUIResourceManagerImpl::OnFinishedLoadBitmap
,
188 weak_factory_
.GetWeakPtr(),
190 base::Owned(bitmap
));
191 base::WorkerPool::PostTaskAndReply(
192 FROM_HERE
, load_bitmap
, finished_load
, true);
195 void SystemUIResourceManagerImpl::OnFinishedLoadBitmap(
196 ui::SystemUIResourceType type
,
197 SkBitmap
* bitmap_holder
) {
198 DCHECK(bitmap_holder
);
199 GetEntry(type
)->SetBitmap(*bitmap_holder
);
203 bool SystemUIResourceManagerImpl::RegisterUIResources(JNIEnv
* env
) {
204 return RegisterNativesImpl(env
);
207 } // namespace content