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"
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);
55 void LoadBitmap(ui::SystemUIResourceManager::ResourceType type,
56 SkBitmap* bitmap_holder,
57 const gfx::Size& screen_size) {
59 "browser", "SystemUIResourceManagerImpl::LoadBitmap", "type", type);
62 case ui::SystemUIResourceManager::OVERSCROLL_EDGE:
63 bitmap = gfx::CreateSkBitmapFromAndroidResource(
64 "android:drawable/overscroll_edge", gfx::Size(128, 12));
66 case ui::SystemUIResourceManager::OVERSCROLL_GLOW:
67 bitmap = gfx::CreateSkBitmapFromAndroidResource(
68 "android:drawable/overscroll_glow", gfx::Size(128, 64));
70 case ui::SystemUIResourceManager::OVERSCROLL_GLOW_L:
71 bitmap = CreateOverscrollGlowLBitmap(screen_size);
74 bitmap.setImmutable();
75 *bitmap_holder = bitmap;
80 class SystemUIResourceManagerImpl::Entry
81 : public content::UIResourceClientAndroid {
83 explicit Entry(UIResourceProvider* provider) : id_(0), provider_(provider) {
89 provider_->DeleteUIResource(id_);
93 void SetBitmap(const SkBitmap& bitmap) {
94 DCHECK(!bitmap.empty());
95 DCHECK(bitmap_.empty());
100 cc::UIResourceId GetUIResourceId() {
104 id_ = provider_->CreateUIResource(this);
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_);
115 // content::UIResourceClientAndroid implementation.
116 virtual void UIResourceIsInvalid() OVERRIDE { id_ = 0; }
118 const SkBitmap& bitmap() const { return bitmap_; }
122 cc::UIResourceId id_;
123 UIResourceProvider* provider_;
125 DISALLOW_COPY_AND_ASSIGN(Entry);
128 SystemUIResourceManagerImpl::SystemUIResourceManagerImpl(
129 UIResourceProvider* ui_resource_provider)
130 : ui_resource_provider_(ui_resource_provider), weak_factory_(this) {
133 SystemUIResourceManagerImpl::~SystemUIResourceManagerImpl() {
136 void SystemUIResourceManagerImpl::PreloadResource(ResourceType type) {
140 cc::UIResourceId SystemUIResourceManagerImpl::GetUIResourceId(
142 return GetEntry(type)->GetUIResourceId();
145 SystemUIResourceManagerImpl::Entry* SystemUIResourceManagerImpl::GetEntry(
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.
154 return resource_map_[type].get();
157 void SystemUIResourceManagerImpl::BuildResource(ResourceType type) {
158 DCHECK(GetEntry(type)->bitmap().empty());
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(),
170 base::Owned(bitmap));
171 base::WorkerPool::PostTaskAndReply(
172 FROM_HERE, load_bitmap, finished_load, true);
175 void SystemUIResourceManagerImpl::OnFinishedLoadBitmap(
177 SkBitmap* bitmap_holder) {
178 DCHECK(bitmap_holder);
179 GetEntry(type)->SetBitmap(*bitmap_holder);
182 } // namespace content