1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/tabs/tab.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <limits>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/defaults.h"
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/themes/theme_service.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_resources.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/effects/SkGradientShader.h"
163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/multi_animation.h"
173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/slide_animation.h"
183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/throb_animation.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas_skia.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/favicon_size.h"
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/font.h"
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/path.h"
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/skbitmap_operations.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/button/image_button.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/tooltip_manager.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/non_client_view.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kLeftPadding = 16;
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kTopPadding = 6;
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kRightPadding = 15;
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kBottomPadding = 5;
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kDropShadowHeight = 2;
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kToolbarOverlap = 1;
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const int kFaviconTitleSpacing = 4;
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kTitleCloseButtonSpacing = 5;
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kStandardTitleWidth = 175;
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kCloseButtonVertFuzz = 0;
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kCloseButtonHorzFuzz = 5;
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Vertical adjustment to the favicon when the tab has a large icon.
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kAppTapFaviconVerticalAdjustment = 2;
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// When a non-mini-tab becomes a mini-tab the width of the tab animates. If
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the width of a mini-tab is >= kMiniTabRendererAsNormalTabWidth then the tab
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is rendered as a normal tab. This is done to avoid having the title
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// immediately disappear when transitioning a tab from normal to mini-tab.
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMiniTabRendererAsNormalTabWidth =
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_defaults::kMiniTabWidth + 30;
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// How opaque to make the hover state (out of 1).
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const double kHoverOpacity = 0.33;
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic const double kHoverSlideOpacity = 0.5;
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Opacity for non-active selected tabs.
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const double kSelectedTabOpacity = .45;
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Selected (but not active) tabs have their throb value scaled down by this.
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const double kSelectedTabThrobScale = .5;
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTab::TabImage Tab::tab_alpha_ = {0};
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTab::TabImage Tab::tab_active_ = {0};
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTab::TabImage Tab::tab_inactive_ = {0};
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Durations for the various parts of the mini tab title animation.
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMiniTitleChangeAnimationDuration1MS = 1600;
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMiniTitleChangeAnimationStart1MS = 0;
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMiniTitleChangeAnimationEnd1MS = 1900;
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMiniTitleChangeAnimationDuration2MS = 0;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMiniTitleChangeAnimationDuration3MS = 550;
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMiniTitleChangeAnimationStart3MS = 150;
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMiniTitleChangeAnimationEnd3MS = 800;
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Offset from the right edge for the start of the mini title change animation.
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMiniTitleChangeInitialXOffset = 6;
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Radius of the radial gradient used for mini title change animation.
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMiniTitleChangeGradientRadius = 20;
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Colors of the gradient used during the mini title change animation.
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SkColor kMiniTitleChangeGradientColor1 = SK_ColorWHITE;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SkColor kMiniTitleChangeGradientColor2 =
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SkColorSetARGB(0, 255, 255, 255);
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Hit mask constants.
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SkScalar kTabCapWidth = 15;
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SkScalar kTabTopCurveWidth = 4;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SkScalar kTabBottomCurveWidth = 3;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char Tab::kViewClassName[] = "browser/tabs/Tab";
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tab, public:
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTab::Tab(TabController* controller)
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : BaseTab(controller),
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      showing_icon_(false),
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      showing_close_button_(false),
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      close_button_color_(0) {
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitTabResources();
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTab::~Tab() {
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Tab::StartMiniTabTitleAnimation() {
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!mini_title_animation_.get()) {
1113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    ui::MultiAnimation::Parts parts;
1123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    parts.push_back(
1133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        ui::MultiAnimation::Part(kMiniTitleChangeAnimationDuration1MS,
1143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                 ui::Tween::EASE_OUT));
1153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    parts.push_back(
1163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        ui::MultiAnimation::Part(kMiniTitleChangeAnimationDuration2MS,
1173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                 ui::Tween::ZERO));
1183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    parts.push_back(
1193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        ui::MultiAnimation::Part(kMiniTitleChangeAnimationDuration3MS,
1203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                 ui::Tween::EASE_IN));
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    parts[0].start_time_ms = kMiniTitleChangeAnimationStart1MS;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    parts[0].end_time_ms = kMiniTitleChangeAnimationEnd1MS;
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    parts[2].start_time_ms = kMiniTitleChangeAnimationStart3MS;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    parts[2].end_time_ms = kMiniTitleChangeAnimationEnd3MS;
1253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    mini_title_animation_.reset(new ui::MultiAnimation(parts));
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    mini_title_animation_->SetContainer(animation_container());
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    mini_title_animation_->set_delegate(this);
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  mini_title_animation_->Start();
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Tab::StopMiniTabTitleAnimation() {
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (mini_title_animation_.get())
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    mini_title_animation_->Stop();
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size Tab::GetMinimumUnselectedSize() {
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitTabResources();
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size minimum_size;
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  minimum_size.set_width(kLeftPadding + kRightPadding);
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Since we use bitmap images, the real minimum height of the image is
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // defined most accurately by the height of the end cap images.
14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  minimum_size.set_height(tab_active_.image_l->height());
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return minimum_size;
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size Tab::GetMinimumSelectedSize() {
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size minimum_size = GetMinimumUnselectedSize();
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  minimum_size.set_width(kLeftPadding + kFaviconSize + kRightPadding);
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return minimum_size;
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size Tab::GetStandardSize() {
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size standard_size = GetMinimumUnselectedSize();
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  standard_size.set_width(
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      standard_size.width() + kFaviconTitleSpacing + kStandardTitleWidth);
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return standard_size;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint Tab::GetMiniWidth() {
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return browser_defaults::kMiniTabWidth;
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tab, protected:
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst gfx::Rect& Tab::GetTitleBounds() const {
173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return title_bounds_;
174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst gfx::Rect& Tab::GetIconBounds() const {
177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return favicon_bounds_;
178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Tab::DataChanged(const TabRendererData& old) {
181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (data().blocked == old.blocked)
182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return;
183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (data().blocked)
185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    StartPulse();
186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  else
187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    StopPulse();
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tab, views::View overrides:
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid Tab::OnPaint(gfx::Canvas* canvas) {
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Don't paint if we're narrower than we can render correctly. (This should
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // only happen during animations).
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (width() < GetMinimumUnselectedSize().width() && !data().mini)
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // See if the model changes whether the icons should be painted.
200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const bool show_icon = ShouldShowIcon();
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool show_close_button = ShouldShowCloseBox();
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (show_icon != showing_icon_ || show_close_button != showing_close_button_)
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Layout();
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PaintTabBackground(canvas);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkColor title_color = GetThemeProvider()->
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GetColor(IsSelected() ?
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          ThemeService::COLOR_TAB_TEXT :
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          ThemeService::COLOR_BACKGROUND_TAB_TEXT);
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!data().mini || width() > kMiniTabRendererAsNormalTabWidth)
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PaintTitle(canvas, title_color);
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (show_icon)
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PaintIcon(canvas);
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the close button color has changed, generate a new one.
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!close_button_color_ || title_color != close_button_color_) {
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    close_button_color_ = title_color;
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    close_button()->SetBackground(close_button_color_,
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rb.GetBitmapNamed(IDR_TAB_CLOSE),
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK));
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Tab::Layout() {
22972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gfx::Rect lb = GetContentsBounds();
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (lb.IsEmpty())
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  lb.Inset(kLeftPadding, kTopPadding, kRightPadding, kBottomPadding);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The height of the content of the Tab is the largest of the favicon,
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the title text and the close button graphic.
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int content_height = std::max(kFaviconSize, font_height());
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gfx::Size close_button_size(close_button()->GetPreferredSize());
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  content_height = std::max(content_height, close_button_size.height());
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Size the Favicon.
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  showing_icon_ = ShouldShowIcon();
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (showing_icon_) {
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Use the size of the favicon as apps use a bigger favicon size.
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    int favicon_top = kTopPadding + content_height / 2 - kFaviconSize / 2;
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int favicon_left = lb.x();
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    favicon_bounds_.SetRect(favicon_left, favicon_top,
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            kFaviconSize, kFaviconSize);
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (data().mini && width() < kMiniTabRendererAsNormalTabWidth) {
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Adjust the location of the favicon when transitioning from a normal
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // tab to a mini-tab.
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int mini_delta = kMiniTabRendererAsNormalTabWidth - GetMiniWidth();
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int ideal_delta = width() - GetMiniWidth();
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (ideal_delta < mini_delta) {
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        int ideal_x = (GetMiniWidth() - kFaviconSize) / 2;
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        int x = favicon_bounds_.x() + static_cast<int>(
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            (1 - static_cast<float>(ideal_delta) /
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             static_cast<float>(mini_delta)) *
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            (ideal_x - favicon_bounds_.x()));
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        favicon_bounds_.set_x(x);
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    favicon_bounds_.SetRect(lb.x(), lb.y(), 0, 0);
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Size the Close button.
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  showing_close_button_ = ShouldShowCloseBox();
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (showing_close_button_) {
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int close_button_top = kTopPadding + kCloseButtonVertFuzz +
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        (content_height - close_button_size.height()) / 2;
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If the ratio of the close button size to tab width exceeds the maximum.
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    close_button()->SetBounds(lb.width() + kCloseButtonHorzFuzz,
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              close_button_top, close_button_size.width(),
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              close_button_size.height());
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    close_button()->SetVisible(true);
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    close_button()->SetBounds(0, 0, 0, 0);
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    close_button()->SetVisible(false);
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int title_left = favicon_bounds_.right() + kFaviconTitleSpacing;
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int title_top = kTopPadding + (content_height - font_height()) / 2;
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Size the Title text to fill the remaining space.
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth) {
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If the user has big fonts, the title will appear rendered too far down
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // on the y-axis if we use the regular top padding, so we need to adjust it
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // so that the text appears centered.
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Size minimum_size = GetMinimumUnselectedSize();
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int text_height = title_top + font_height() + kBottomPadding;
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (text_height > minimum_size.height())
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      title_top -= (text_height - minimum_size.height()) / 2;
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int title_width;
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (close_button()->IsVisible()) {
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      title_width = std::max(close_button()->x() -
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             kTitleCloseButtonSpacing - title_left, 0);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      title_width = std::max(lb.width() - title_left, 0);
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    title_bounds_.SetRect(title_left, title_top, title_width, font_height());
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    title_bounds_.SetRect(title_left, title_top, 0, 0);
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Certain UI elements within the Tab (the favicon, etc.) are not represented
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // as child Views (which is the preferred method).  Instead, these UI elements
307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // are drawn directly on the canvas from within Tab::OnPaint(). The Tab's
308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // child Views (for example, the Tab's close button which is a views::Button
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // instance) are automatically mirrored by the mirroring infrastructure in
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // views. The elements Tab draws directly on the canvas need to be manually
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // mirrored if the View's layout is right-to-left.
31272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  title_bounds_.set_x(GetMirroredXForRect(title_bounds_));
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Tab::OnThemeChanged() {
31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  LoadTabImages();
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::string Tab::GetClassName() const {
320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return kViewClassName;
321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Tab::HasHitTestMask() const {
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Tab::GetHitTestMask(gfx::Path* path) const {
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(path);
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkScalar h = SkIntToScalar(height());
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkScalar w = SkIntToScalar(width());
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->moveTo(0, h);
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Left end cap.
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->lineTo(kTabBottomCurveWidth, h - kTabBottomCurveWidth);
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->lineTo(kTabCapWidth - kTabTopCurveWidth, kTabTopCurveWidth);
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->lineTo(kTabCapWidth, 0);
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Connect to the right cap.
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->lineTo(w - kTabCapWidth, 0);
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Right end cap.
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->lineTo(w - kTabCapWidth + kTabTopCurveWidth, kTabTopCurveWidth);
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->lineTo(w - kTabBottomCurveWidth, h - kTabBottomCurveWidth);
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->lineTo(w, h);
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Close out the path.
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->lineTo(0, h);
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path->close();
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Tab::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin) {
354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  origin->set_x(title_bounds_.x() + 10);
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  origin->set_y(-views::TooltipManager::GetTooltipHeight() - 4);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Tab::OnMouseMoved(const views::MouseEvent& event) {
360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  hover_point_ = event.location();
36121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // We need to redraw here because otherwise the hover glow does not update
36221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // and follow the new mouse position.
36321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SchedulePaint();
36421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
36521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tab, private
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Tab::PaintTabBackground(gfx::Canvas* canvas) {
370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (IsActive()) {
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PaintActiveTabBackground(canvas);
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (mini_title_animation_.get() && mini_title_animation_->is_animating())
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PaintInactiveTabBackgroundWithTitleChange(canvas);
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PaintInactiveTabBackground(canvas);
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    double throb_value = GetThrobValue();
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (throb_value > 0) {
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      canvas->SaveLayerAlpha(static_cast<int>(throb_value * 0xff),
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             gfx::Rect(width(), height()));
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      canvas->AsCanvasSkia()->drawARGB(0, 255, 255, 255,
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       SkXfermode::kClear_Mode);
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PaintActiveTabBackground(canvas);
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      canvas->Restore();
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) {
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Render the inactive tab background. We'll use this for clipping.
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::CanvasSkia background_canvas(width(), height(), false);
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PaintInactiveTabBackground(&background_canvas);
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap background_image = background_canvas.ExtractBitmap();
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw a radial gradient to hover_canvas.
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::CanvasSkia hover_canvas(width(), height(), false);
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int radius = kMiniTitleChangeGradientRadius;
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int x0 = width() + radius - kMiniTitleChangeInitialXOffset;
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int x1 = radius;
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int x2 = -radius;
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int x;
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (mini_title_animation_->current_part_index() == 0) {
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    x = mini_title_animation_->CurrentValueBetween(x0, x1);
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (mini_title_animation_->current_part_index() == 1) {
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    x = x1;
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    x = mini_title_animation_->CurrentValueBetween(x1, x2);
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkPaint paint;
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkPoint loc = { SkIntToScalar(x), SkIntToScalar(0) };
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkColor colors[2];
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  colors[0] = kMiniTitleChangeGradientColor1;
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  colors[1] = kMiniTitleChangeGradientColor2;
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkShader* shader = SkGradientShader::CreateRadial(
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      loc,
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SkIntToScalar(radius),
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      colors,
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL,
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      2,
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SkShader::kClamp_TileMode);
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  paint.setShader(shader);
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  shader->unref();
4253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  hover_canvas.DrawRectInt(x - radius, -radius, radius * 2, radius * 2, paint);
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw the radial gradient clipped to the background into hover_image.
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap hover_image = SkBitmapOperations::CreateMaskedBitmap(
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      hover_canvas.ExtractBitmap(), background_image);
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw the tab background to the canvas.
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(background_image, 0, 0);
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // And then the gradient on top of that.
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (mini_title_animation_->current_part_index() == 2) {
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    canvas->SaveLayerAlpha(mini_title_animation_->CurrentValueBetween(255, 0));
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    canvas->DrawBitmapInt(hover_image, 0, 0);
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    canvas->Restore();
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    canvas->DrawBitmapInt(hover_image, 0, 0);
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) {
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The tab image needs to be lined up with the background image
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // so that it feels partially transparent.  These offsets represent the tab
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // position within the frame background image.
44872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int offset = GetMirroredX() + background_offset_.x();
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int tab_id;
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (GetWidget() &&
452dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      GetWidget()->GetWindow()->non_client_view()->UseNativeFrame()) {
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tab_id = IDR_THEME_TAB_BACKGROUND_V;
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    tab_id = data().incognito ? IDR_THEME_TAB_BACKGROUND_INCOGNITO :
456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                IDR_THEME_TAB_BACKGROUND;
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(tab_id);
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TabImage* tab_image = &tab_active_;
46272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TabImage* tab_inactive_image = &tab_inactive_;
46372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TabImage* alpha = &tab_alpha_;
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the theme is providing a custom background image, then its top edge
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // should be at the top of the tab. Otherwise, we assume that the background
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // image is a composited foreground + frame image.
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ?
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0 : background_offset_.y();
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
47121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // We need a CanvasSkia object to be able to extract the bitmap from.
47221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // We draw everything to this canvas and then output it to the canvas
47321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // parameter in addition to using it to mask the hover glow if needed.
47421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  gfx::CanvasSkia background_canvas(width(), height(), false);
47521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw left edge.  Don't draw over the toolbar, as we're not the foreground
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // tab.
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *tab_bg, offset, bg_offset_y, tab_image->l_width, height());
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap theme_l =
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l);
48221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  background_canvas.DrawBitmapInt(theme_l,
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap,
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap,
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      false);
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw right edge.  Again, don't draw over the toolbar.
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      offset + width() - tab_image->r_width, bg_offset_y,
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_image->r_width, height());
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap theme_r =
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r);
49321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  background_canvas.DrawBitmapInt(theme_r,
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0, 0, theme_r.width(), theme_r.height() - kToolbarOverlap,
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      width() - theme_r.width(), 0, theme_r.width(),
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      theme_r.height() - kToolbarOverlap, false);
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw center.  Instead of masking out the top portion we simply skip over
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // it by incrementing by kDropShadowHeight, since it's a simple rectangle.
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // And again, don't draw over the toolbar.
50121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  background_canvas.TileImageInt(*tab_bg,
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     offset + tab_image->l_width,
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     bg_offset_y + kDropShadowHeight + tab_image->y_offset,
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     tab_image->l_width,
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     kDropShadowHeight + tab_image->y_offset,
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     width() - tab_image->l_width - tab_image->r_width,
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     height() - kDropShadowHeight - kToolbarOverlap - tab_image->y_offset);
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  canvas->DrawBitmapInt(background_canvas.ExtractBitmap(), 0, 0);
51021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
51121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!GetThemeProvider()->HasCustomImage(tab_id) &&
51272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      hover_animation() &&
51372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      (hover_animation()->IsShowing() || hover_animation()->is_animating())) {
51421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    SkBitmap hover_glow = DrawHoverGlowBitmap(width(), height());
51521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Draw the hover glow clipped to the background into hover_image.
51621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    SkBitmap hover_image = SkBitmapOperations::CreateMaskedBitmap(
51721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        hover_glow, background_canvas.ExtractBitmap());
51821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    canvas->DrawBitmapInt(hover_image, 0, 0);
51921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
52021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now draw the highlights/shadows around the tab edge.
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*tab_inactive_image->image_l, 0, 0);
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*tab_inactive_image->image_c,
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       tab_inactive_image->l_width, 0,
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       width() - tab_inactive_image->l_width -
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           tab_inactive_image->r_width,
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       height());
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*tab_inactive_image->image_r,
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        width() - tab_inactive_image->r_width, 0);
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Tab::PaintActiveTabBackground(gfx::Canvas* canvas) {
53372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int offset = GetMirroredX() + background_offset_.x();
53472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::ThemeProvider* tp = GetThemeProvider();
53572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(tp) << "Unable to get theme provider";
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR);
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TabImage* tab_image = &tab_active_;
54072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TabImage* alpha = &tab_alpha_;
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw left edge.
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap(
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *tab_bg, offset, 0, tab_image->l_width, height());
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap theme_l =
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l);
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(theme_l, 0, 0);
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw right edge.
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg,
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      offset + width() - tab_image->r_width, 0, tab_image->r_width, height());
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap theme_r =
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r);
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(theme_r, width() - tab_image->r_width, 0);
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw center.  Instead of masking out the top portion we simply skip over it
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // by incrementing by kDropShadowHeight, since it's a simple rectangle.
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*tab_bg,
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     offset + tab_image->l_width,
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     kDropShadowHeight + tab_image->y_offset,
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     tab_image->l_width,
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     kDropShadowHeight + tab_image->y_offset,
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     width() - tab_image->l_width - tab_image->r_width,
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     height() - kDropShadowHeight - tab_image->y_offset);
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now draw the highlights/shadows around the tab edge.
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*tab_image->image_l, 0, 0);
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0,
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      width() - tab_image->l_width - tab_image->r_width, height());
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*tab_image->image_r, width() - tab_image->r_width, 0);
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSkBitmap Tab::DrawHoverGlowBitmap(int width_input, int height_input) {
57421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Draw a radial gradient to hover_canvas so we can export the bitmap.
57521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  gfx::CanvasSkia hover_canvas(width_input, height_input, false);
57621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
57721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Draw a radial gradient to hover_canvas.
57821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int radius = width() / 3;
57921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
58021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SkPaint paint;
58121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  paint.setStyle(SkPaint::kFill_Style);
58221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  paint.setFlags(SkPaint::kAntiAlias_Flag);
58321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SkPoint loc = { SkIntToScalar(hover_point_.x()),
58421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                  SkIntToScalar(hover_point_.y()) };
58521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SkColor colors[2];
5863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  const ui::SlideAnimation* hover_slide = hover_animation();
58721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int hover_alpha = 0;
58821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (hover_slide) {
58972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    hover_alpha = static_cast<int>(255 * kHoverSlideOpacity *
59072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   hover_slide->GetCurrentValue());
59121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
59221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  colors[0] = SkColorSetARGB(hover_alpha, 255, 255, 255);
59321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  colors[1] = SkColorSetARGB(0, 255, 255, 255);
59421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SkShader* shader = SkGradientShader::CreateRadial(
59521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      loc,
59621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      SkIntToScalar(radius),
59721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      colors,
59821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      NULL,
59921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      2,
60021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      SkShader::kClamp_TileMode);
6013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // Shader can end up null when radius = 0.
6023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // If so, this results in default full tab glow behavior.
6033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (shader) {
6043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    paint.setShader(shader);
6053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    shader->unref();
6063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    hover_canvas.DrawRectInt(hover_point_.x() - radius,
6073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                             hover_point_.y() - radius,
6083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                             radius * 2, radius * 2, paint);
6093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  }
61021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return hover_canvas.ExtractBitmap();
61121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
61221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint Tab::IconCapacity() const {
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (height() < GetMinimumUnselectedSize().height())
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return (width() - kLeftPadding - kRightPadding) / kFaviconSize;
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Tab::ShouldShowIcon() const {
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data().mini && height() >= GetMinimumUnselectedSize().height())
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!data().show_icon) {
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (IsActive()) {
625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // The active tab clips favicon before close button.
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return IconCapacity() >= 2;
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Non-selected tabs clip close button before favicon.
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return IconCapacity() >= 1;
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool Tab::ShouldShowCloseBox() const {
633ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The active tab never clips close button.
634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return !data().mini && IsCloseable() && (IsActive() || IconCapacity() >= 3);
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdouble Tab::GetThrobValue() {
638ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool is_selected = IsSelected();
639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  double min = is_selected ? kSelectedTabOpacity : 0;
640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  double scale = is_selected ? kSelectedTabThrobScale : 1;
641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (pulse_animation() && pulse_animation()->is_animating())
643ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return pulse_animation()->GetCurrentValue() * kHoverOpacity * scale + min;
644ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
645ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (hover_animation())
646ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return kHoverOpacity * hover_animation()->GetCurrentValue() * scale + min;
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
648ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return is_selected ? kSelectedTabOpacity : 0;
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tab, private:
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
65572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid Tab::InitTabResources() {
65672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  static bool initialized = false;
65772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (initialized)
65872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
65972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
66072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  initialized = true;
66172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
66272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Load the tab images once now, and maybe again later if the theme changes.
66372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  LoadTabImages();
66472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
66572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
66672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Tab::LoadTabImages() {
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We're not letting people override tab images just yet.
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_alpha_.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT);
67272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_alpha_.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT);
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_active_.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
67572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_active_.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
67672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_active_.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
67772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_active_.l_width = tab_active_.image_l->width();
67872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_active_.r_width = tab_active_.image_r->width();
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
68072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_inactive_.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
68172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_inactive_.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
68272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_inactive_.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
68372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_inactive_.l_width = tab_inactive_.image_l->width();
68472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  tab_inactive_.r_width = tab_inactive_.image_r->width();
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
686