16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
26e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
36e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// found in the LICENSE file.
46e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "content/browser/android/system_ui_resource_manager_impl.h"
66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/bind.h"
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/bind_helpers.h"
903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/debug/trace_event.h"
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/location.h"
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/observer_list.h"
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/threading/worker_pool.h"
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "cc/resources/ui_resource_bitmap.h"
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "content/public/browser/android/ui_resource_client_android.h"
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "content/public/browser/android/ui_resource_provider.h"
166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h"
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "third_party/skia/include/core/SkPaint.h"
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "third_party/skia/include/effects/SkPorterDuff.h"
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/gfx/android/java_bitmap.h"
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/gfx/screen.h"
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace content {
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace {
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)SkBitmap CreateOverscrollGlowLBitmap(const gfx::Size& screen_size) {
2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const float kSin = 0.5f;    // sin(PI / 6)
2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const float kCos = 0.866f;  // cos(PI / 6);
2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SkPaint paint;
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  paint.setAntiAlias(true);
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  paint.setAlpha(0xBB);
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  paint.setStyle(SkPaint::kFill_Style);
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const float arc_width =
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      std::min(screen_size.width(), screen_size.height()) * 0.5f / kSin;
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const float y = kCos * arc_width;
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const float height = arc_width - y;
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  gfx::Size bounds(arc_width, height);
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SkRect arc_rect = SkRect::MakeXYWH(
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      -arc_width / 2.f, -arc_width - y, arc_width * 2.f, arc_width * 2.f);
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SkBitmap glow_bitmap;
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  glow_bitmap.allocPixels(SkImageInfo::MakeA8(bounds.width(), bounds.height()));
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  glow_bitmap.eraseColor(SK_ColorTRANSPARENT);
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SkCanvas canvas(glow_bitmap);
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  canvas.clipRect(SkRect::MakeXYWH(0, 0, bounds.width(), bounds.height()));
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  canvas.drawArc(arc_rect, 45, 90, true, paint);
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return glow_bitmap;
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void LoadBitmap(ui::SystemUIResourceManager::ResourceType type,
5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                SkBitmap* bitmap_holder,
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                const gfx::Size& screen_size) {
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  TRACE_EVENT1(
5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "browser", "SystemUIResourceManagerImpl::LoadBitmap", "type", type);
5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SkBitmap bitmap;
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  switch (type) {
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case ui::SystemUIResourceManager::OVERSCROLL_EDGE:
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      bitmap = gfx::CreateSkBitmapFromAndroidResource(
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          "android:drawable/overscroll_edge", gfx::Size(128, 12));
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      break;
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case ui::SystemUIResourceManager::OVERSCROLL_GLOW:
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      bitmap = gfx::CreateSkBitmapFromAndroidResource(
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          "android:drawable/overscroll_glow", gfx::Size(128, 64));
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      break;
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case ui::SystemUIResourceManager::OVERSCROLL_GLOW_L:
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      bitmap = CreateOverscrollGlowLBitmap(screen_size);
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      break;
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bitmap.setImmutable();
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  *bitmap_holder = bitmap;
7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class SystemUIResourceManagerImpl::Entry
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : public content::UIResourceClientAndroid {
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public:
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  explicit Entry(UIResourceProvider* provider) : id_(0), provider_(provider) {
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DCHECK(provider);
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual ~Entry() {
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (id_)
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      provider_->DeleteUIResource(id_);
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    id_ = 0;
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void SetBitmap(const SkBitmap& bitmap) {
9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    DCHECK(!bitmap.empty());
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DCHECK(bitmap_.empty());
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DCHECK(!id_);
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    bitmap_ = bitmap;
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  cc::UIResourceId GetUIResourceId() {
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (bitmap_.empty())
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return 0;
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!id_)
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      id_ = provider_->CreateUIResource(this);
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return id_;
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // content::UIResourceClient implementation.
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual cc::UIResourceBitmap GetBitmap(cc::UIResourceId uid,
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                         bool resource_lost) OVERRIDE {
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DCHECK(!bitmap_.empty());
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return cc::UIResourceBitmap(bitmap_);
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // content::UIResourceClientAndroid implementation.
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void UIResourceIsInvalid() OVERRIDE { id_ = 0; }
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const SkBitmap& bitmap() const { return bitmap_; }
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private:
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SkBitmap bitmap_;
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  cc::UIResourceId id_;
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  UIResourceProvider* provider_;
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Entry);
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)SystemUIResourceManagerImpl::SystemUIResourceManagerImpl(
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    UIResourceProvider* ui_resource_provider)
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : ui_resource_provider_(ui_resource_provider), weak_factory_(this) {
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)SystemUIResourceManagerImpl::~SystemUIResourceManagerImpl() {
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SystemUIResourceManagerImpl::PreloadResource(ResourceType type) {
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  GetEntry(type);
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)cc::UIResourceId SystemUIResourceManagerImpl::GetUIResourceId(
1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ResourceType type) {
1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return GetEntry(type)->GetUIResourceId();
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)SystemUIResourceManagerImpl::Entry* SystemUIResourceManagerImpl::GetEntry(
1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ResourceType type) {
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK_GE(type, RESOURCE_TYPE_FIRST);
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK_LE(type, RESOURCE_TYPE_LAST);
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!resource_map_[type]) {
1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    resource_map_[type].reset(new Entry(ui_resource_provider_));
1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Lazily build the resource.
1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    BuildResource(type);
1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return resource_map_[type].get();
1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SystemUIResourceManagerImpl::BuildResource(ResourceType type) {
1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(GetEntry(type)->bitmap().empty());
1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Instead of blocking the main thread, we post a task to load the bitmap.
1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SkBitmap* bitmap = new SkBitmap();
15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  gfx::Size screen_size =
16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().GetSizeInPixel();
1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::Closure load_bitmap =
16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(&LoadBitmap, type, bitmap, screen_size);
1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::Closure finished_load =
1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::Bind(&SystemUIResourceManagerImpl::OnFinishedLoadBitmap,
1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 weak_factory_.GetWeakPtr(),
1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 type,
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 base::Owned(bitmap));
1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::WorkerPool::PostTaskAndReply(
1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      FROM_HERE, load_bitmap, finished_load, true);
1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SystemUIResourceManagerImpl::OnFinishedLoadBitmap(
1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ResourceType type,
1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    SkBitmap* bitmap_holder) {
1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(bitmap_holder);
1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  GetEntry(type)->SetBitmap(*bitmap_holder);
1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace content
180