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