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 23namespace content { 24namespace { 25 26SkBitmap 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(0xBB); 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 glow_bitmap.allocPixels(SkImageInfo::MakeA8(bounds.width(), bounds.height())); 44 glow_bitmap.eraseColor(SK_ColorTRANSPARENT); 45 46 SkCanvas canvas(glow_bitmap); 47 canvas.clipRect(SkRect::MakeXYWH(0, 0, bounds.width(), bounds.height())); 48 canvas.drawArc(arc_rect, 45, 90, true, paint); 49 return glow_bitmap; 50} 51 52void LoadBitmap(ui::SystemUIResourceManager::ResourceType type, 53 SkBitmap* bitmap_holder, 54 const gfx::Size& screen_size) { 55 TRACE_EVENT1( 56 "browser", "SystemUIResourceManagerImpl::LoadBitmap", "type", type); 57 SkBitmap bitmap; 58 switch (type) { 59 case ui::SystemUIResourceManager::OVERSCROLL_EDGE: 60 bitmap = gfx::CreateSkBitmapFromAndroidResource( 61 "android:drawable/overscroll_edge", gfx::Size(128, 12)); 62 break; 63 case ui::SystemUIResourceManager::OVERSCROLL_GLOW: 64 bitmap = gfx::CreateSkBitmapFromAndroidResource( 65 "android:drawable/overscroll_glow", gfx::Size(128, 64)); 66 break; 67 case ui::SystemUIResourceManager::OVERSCROLL_GLOW_L: 68 bitmap = CreateOverscrollGlowLBitmap(screen_size); 69 break; 70 } 71 bitmap.setImmutable(); 72 *bitmap_holder = bitmap; 73} 74 75} // namespace 76 77class SystemUIResourceManagerImpl::Entry 78 : public content::UIResourceClientAndroid { 79 public: 80 explicit Entry(UIResourceProvider* provider) : id_(0), provider_(provider) { 81 DCHECK(provider); 82 } 83 84 virtual ~Entry() { 85 if (id_) 86 provider_->DeleteUIResource(id_); 87 id_ = 0; 88 } 89 90 void SetBitmap(const SkBitmap& bitmap) { 91 DCHECK(!bitmap.empty()); 92 DCHECK(bitmap_.empty()); 93 DCHECK(!id_); 94 bitmap_ = bitmap; 95 } 96 97 cc::UIResourceId GetUIResourceId() { 98 if (bitmap_.empty()) 99 return 0; 100 if (!id_) 101 id_ = provider_->CreateUIResource(this); 102 return id_; 103 } 104 105 // content::UIResourceClient implementation. 106 virtual cc::UIResourceBitmap GetBitmap(cc::UIResourceId uid, 107 bool resource_lost) OVERRIDE { 108 DCHECK(!bitmap_.empty()); 109 return cc::UIResourceBitmap(bitmap_); 110 } 111 112 // content::UIResourceClientAndroid implementation. 113 virtual void UIResourceIsInvalid() OVERRIDE { id_ = 0; } 114 115 const SkBitmap& bitmap() const { return bitmap_; } 116 117 private: 118 SkBitmap bitmap_; 119 cc::UIResourceId id_; 120 UIResourceProvider* provider_; 121 122 DISALLOW_COPY_AND_ASSIGN(Entry); 123}; 124 125SystemUIResourceManagerImpl::SystemUIResourceManagerImpl( 126 UIResourceProvider* ui_resource_provider) 127 : ui_resource_provider_(ui_resource_provider), weak_factory_(this) { 128} 129 130SystemUIResourceManagerImpl::~SystemUIResourceManagerImpl() { 131} 132 133void SystemUIResourceManagerImpl::PreloadResource(ResourceType type) { 134 GetEntry(type); 135} 136 137cc::UIResourceId SystemUIResourceManagerImpl::GetUIResourceId( 138 ResourceType type) { 139 return GetEntry(type)->GetUIResourceId(); 140} 141 142SystemUIResourceManagerImpl::Entry* SystemUIResourceManagerImpl::GetEntry( 143 ResourceType type) { 144 DCHECK_GE(type, RESOURCE_TYPE_FIRST); 145 DCHECK_LE(type, RESOURCE_TYPE_LAST); 146 if (!resource_map_[type]) { 147 resource_map_[type].reset(new Entry(ui_resource_provider_)); 148 // Lazily build the resource. 149 BuildResource(type); 150 } 151 return resource_map_[type].get(); 152} 153 154void SystemUIResourceManagerImpl::BuildResource(ResourceType type) { 155 DCHECK(GetEntry(type)->bitmap().empty()); 156 157 // Instead of blocking the main thread, we post a task to load the bitmap. 158 SkBitmap* bitmap = new SkBitmap(); 159 gfx::Size screen_size = 160 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().GetSizeInPixel(); 161 base::Closure load_bitmap = 162 base::Bind(&LoadBitmap, type, bitmap, screen_size); 163 base::Closure finished_load = 164 base::Bind(&SystemUIResourceManagerImpl::OnFinishedLoadBitmap, 165 weak_factory_.GetWeakPtr(), 166 type, 167 base::Owned(bitmap)); 168 base::WorkerPool::PostTaskAndReply( 169 FROM_HERE, load_bitmap, finished_load, true); 170} 171 172void SystemUIResourceManagerImpl::OnFinishedLoadBitmap( 173 ResourceType type, 174 SkBitmap* bitmap_holder) { 175 DCHECK(bitmap_holder); 176 GetEntry(type)->SetBitmap(*bitmap_holder); 177} 178 179} // namespace content 180