7ee66993创建于 2012年8月17日历史提交
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/renderer/webview_animating_overlay.h"

#include "base/logging.h"
#include "content/public/renderer/render_view.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "ui/gfx/size.h"
#include "ui/gfx/skia_util.h"

const int kAnimationDurationMiliseconds = 500;
const int kAnimationFrameRate = 60;
const int kTargetAlpha = 191;

WebViewAnimatingOverlay::WebViewAnimatingOverlay(
    content::RenderView* render_view)
    : render_view_(render_view),
      state_(HIDDEN),
      animation_(kAnimationDurationMiliseconds, kAnimationFrameRate, this) {
}

WebViewAnimatingOverlay::~WebViewAnimatingOverlay() {
  if (render_view_->GetWebView())
    render_view_->GetWebView()->removePageOverlay(this);
}

void WebViewAnimatingOverlay::Show() {
  if (state_ == ANIMATING_IN || state_ == VISIBLE)
    return;

  if (state_ == ANIMATING_OUT) {
    animation_.SetCurrentValue(1.0 - animation_.GetCurrentValue());
  } else {
    DCHECK_EQ(HIDDEN, state_);
    if (render_view_->GetWebView())
      render_view_->GetWebView()->addPageOverlay(this, 0);
  }

  state_ = ANIMATING_IN;
  animation_.Start();
}

void WebViewAnimatingOverlay::Hide() {
  if (state_ == ANIMATING_OUT || state_ == HIDDEN)
    return;

  if (state_ == ANIMATING_IN)
    animation_.SetCurrentValue(1.0 - animation_.GetCurrentValue());

  state_ = ANIMATING_OUT;
  animation_.Start();
}

void WebViewAnimatingOverlay::paintPageOverlay(WebKit::WebCanvas* canvas) {
  SkRect rect = gfx::RectToSkRect(gfx::Rect(render_view_->GetSize()));

  // The center of the radial gradient should be near the top middle.
  SkPoint center_point;
  center_point.iset(rect.width() * 0.5, rect.height() * 0.05);
  int radius = static_cast<int>(rect.width());

  // Animate in or out using the alpha.
  int alpha = GetCurrentAlpha();
  SkColor colors[] = {
    SkColorSetARGB(alpha, 255, 255, 255),
    SkColorSetARGB(alpha, 127, 127, 127)
  };

  SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(center_point,
      SkIntToScalar(radius), colors, NULL, arraysize(colors),
      SkShader::kClamp_TileMode));
  SkPaint paint;
  paint.setShader(shader);
  paint.setDither(true);

  canvas->drawRect(rect, paint);
}

void WebViewAnimatingOverlay::AnimationEnded(const ui::Animation* animation) {
  if (state_ == ANIMATING_IN) {
    state_ = VISIBLE;
  } else {
    DCHECK_EQ(ANIMATING_OUT, state_);
    state_ = HIDDEN;
    if (render_view_->GetWebView())
      render_view_->GetWebView()->removePageOverlay(this);
  }
}

void WebViewAnimatingOverlay::AnimationProgressed(
    const ui::Animation* animation) {
  render_view_->Repaint(render_view_->GetSize());
}

int WebViewAnimatingOverlay::GetCurrentAlpha() {
  switch (state_) {
    case ANIMATING_IN:
      return animation_.CurrentValueBetween(0, kTargetAlpha);
    case ANIMATING_OUT:
      return animation_.CurrentValueBetween(kTargetAlpha, 0);
    case VISIBLE:
    case HIDDEN:
      return kTargetAlpha;
  }
  NOTREACHED();
  return 1.0;
}